Last active
December 13, 2015 17:19
-
-
Save danielgoncalves/4947345 to your computer and use it in GitHub Desktop.
Minimalist tool to search and list occurrences of unique exceptions in log files. The exceptions should be logged using the `exception` method.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# | |
# logr.py is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU Lesser General Public License as | |
# published by the Free Software Foundation, either version 3 of the | |
# License, or (at your option) any later version. | |
# | |
# logr.py is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU Lesser General Public License for more details. | |
# | |
# You should have received a copy of the GNU Lesser General Public License | |
# along with logr.py. If not, see <http://www.gnu.org/licenses/>. | |
# | |
""" | |
Minimalist tool to search and list occurrences of unique exceptions in log | |
files. The exceptions should be logged using the `exception` method. | |
Usage example:: | |
python logr.py /path/to/file.log | |
Sample output:: | |
Total 115432 line(s) | |
Found 3 unique exception(s)... | |
IOError 4 occurrence(s) at line(s): | |
65227, 81122, 108628, 112905 | |
RuntimeError 5709 occurrence(s) at line(s): | |
3, 16, 29, 42, 55, 68, 82, 95, 130, 143, 156, 169, 182, 195, 208, ... | |
IntegrityError 1472 occurrence(s) at line(s): | |
108, 247, 322, 382, 545, 594, 693, 715, 763, 796, 946, 982, 1133, 1168, | |
1201, ... | |
""" | |
import argparse | |
import re | |
import textwrap | |
VERSION = '0.1' | |
BEGIN_TRACEBACK = re.compile(r'^Traceback \(most recent call last\)\:') | |
EXCEPTION_MESSAGE = re.compile(r'^(?P<exc_name>\w+)\:(?P<exc_message>.*)') | |
def logr_list_exceptions(filename, maxlines=0): | |
exc_map = {} | |
in_traceback = False | |
traceback_line = 0 | |
with open(filename, 'rb') as fhandler: | |
line_num = 0 | |
for line in fhandler: | |
line_num += 1 | |
if BEGIN_TRACEBACK.match(line): | |
in_traceback = True | |
traceback_line = line_num | |
if in_traceback: | |
matcher = EXCEPTION_MESSAGE.match(line) | |
if matcher is not None: | |
exc_name = matcher.group('exc_name') | |
exc_message = matcher.group('exc_message') | |
if exc_name in exc_map: | |
data = exc_map[exc_name] | |
data['count'] += 1 | |
data['lines'].append(traceback_line) | |
else: | |
data = {'count': 1, 'lines': [traceback_line,]} | |
exc_map[exc_name] = data | |
in_traceback = False | |
traceback_line = 0 | |
print 'Total', line_num, 'line(s)' | |
if exc_map: | |
print 'Found %d unique exception(s)...' % len(exc_map) | |
for exc_name, data in exc_map.iteritems(): | |
print exc_name, data['count'], 'occurrence(s) at line(s):' | |
if maxlines > 0: | |
lines = data['lines'][:maxlines] | |
else: | |
lines = data['lines'] | |
ellipses = ', ...' if len(lines) < len(data['lines']) else '' | |
p = ', '.join([str(n) for n in lines]) + ellipses | |
for line in textwrap.wrap(p, 75): | |
print ' ', line | |
else: | |
print 'No tracebacks found.' | |
if __name__ == '__main__': | |
version = '%%(prog)s %s' % VERSION | |
parser = argparse.ArgumentParser( | |
prog='logr', | |
description='Search for exceptions in log files') | |
parser.add_argument('filename', | |
help='The log file to search.') | |
parser.add_argument('--version', action='version', version=version) | |
parser.add_argument('-m', '--maxlines', type=int, | |
default=15, | |
action='store', | |
help='Max line numbers to display (defaults to %(default)d, use 0 to display all)') | |
args = parser.parse_args() | |
logr_list_exceptions(args.filename, maxlines=args.maxlines) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment