Skip to content

Instantly share code, notes, and snippets.

@danielgoncalves
Last active December 13, 2015 17:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielgoncalves/4947345 to your computer and use it in GitHub Desktop.
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.
# -*- 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)
print
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
print
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