Skip to content

Instantly share code, notes, and snippets.

@dunkelstern
Created September 7, 2016 16:57
Show Gist options
  • Save dunkelstern/1d34459e9f6b7747363584b8469419d8 to your computer and use it in GitHub Desktop.
Save dunkelstern/1d34459e9f6b7747363584b8469419d8 to your computer and use it in GitHub Desktop.
ScribeJS commandline logfile dumper and filtering tool (python 3)
#!/usr/bin/env python
import json
import argparse
import itertools
import time
from dateutil.parser import parse
import datetime
# date parser
class ParseDate(argparse.Action):
def __init__(self, option_strings, dest, nargs=None, **kwargs):
super().__init__(option_strings, dest, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, parse(values))
# simple follow iterator
def follow(fp):
fp.seek(0,2) # Go to the end of the file
while True:
line = fp.readline()
if not line:
time.sleep(1) # Sleep briefly
continue
yield line
# argument parser setup
parser = argparse.ArgumentParser(description='Show a ScribeJS logfile.')
parser.add_argument(
'-t', '--tag',
type=str,
action='append',
nargs=1,
help='only show log lines with this tag'
)
parser.add_argument(
'--from',
type=str,
action=ParseDate,
nargs=1,
dest='from_date',
help='earliest date to show'
)
parser.add_argument(
'--to',
type=str,
action=ParseDate,
nargs=1,
dest='to_date',
help='latest date to show'
)
parser.add_argument(
'--type',
type=str,
nargs=1,
dest='type',
help='type of log messages to show (log|error|info)'
)
parser.add_argument(
'--file',
type=str,
nargs=1,
action='append',
dest='file_filter',
help='only show log entries from that file'
)
parser.add_argument(
'-c', '--color',
action='store_true',
help='if this flag is set display original colored ScribeJS output'
)
parser.add_argument(
'-f', '--follow',
action='store_true',
dest='follow',
help='follow the log output while the file is written to (like tail -f)'
)
parser.add_argument(
'file',
nargs='*',
type=str,
help='file to process'
)
args = parser.parse_args()
if args.tag: # flatmap tag list
args.tag = list(itertools.chain(*args.tag))
if args.file_filter: # flatmap file filter list
args.file_filter = list(itertools.chain(*args.file_filter))
# bail out on invalid parameter combinations
if args.follow and len(args.file) > 1:
print("You cannot follow multiple files currently!")
exit(1)
for file in args.file:
# if we're going to show multiple files display file headers
if len(args.file) > 1:
print(40 * '-')
print(file)
print(40 * '-')
# open the file
with open(file, 'r') as fp:
# determine if we follow the file or just dump it completely
iterator = fp
if args.follow:
iterator = follow(fp)
# iterate over lines
for line in iterator:
# parse object
j = json.loads(line)
display = True
# apply type filter
if args.type:
display = (j['type'] == args.type[0])
# apply tag filter (tags are _OR_)
if args.tag and display:
display = False
for tag in j['context']['tags']:
if tag in args.tag:
display = True
break
# apply from and to date filters
t = datetime.datetime.utcfromtimestamp(j['context']['time']/1000)
if args.from_date and display:
display = t > args.from_date
if args.to_date and display:
display = t < args.to_date
# apply file name filter
if args.file_filter and display:
display = False
for file_filter in args.file_filter:
if j['context']['location']['filename'] == file_filter:
display = True
break
# all filters determined we want to display the line?
if display:
# if the user chose --color, we just dump the original line with fixed indents
if args.color:
indent = len(j['contextString'])
esc = j['contextString'].count('\u001b')
indent -= esc * 5
print(j['message'].replace('\n', '\n' + (indent * ' ')))
else:
# user did not want color, build a log line ourselves
indent = 20
tags = ''
# exclude tags the user filtered for as they have to be there
for tag in j['context']['tags']:
if not args.tag or tag not in args.tag:
tags += ' [' + tag + ']'
indent += len(tags)
# fix indent
msg = j['argsString'].replace('\n', '\n' + (indent * ' '))
# print log line
print('{:%Y-%m-%d %H:%M:%S}{} {}'.format(t, tags, msg))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment