tail support, log filtering, executable, and splitlines bug fix
Change-Id: I81e928fb5222d055f248d50a5332ea39d4b9ebc1
This commit is contained in:
parent
aed513015c
commit
c6379afce0
63
oslo_log/cmds/convert_json.py
Normal file → Executable file
63
oslo_log/cmds/convert_json.py
Normal file → Executable file
@ -1,3 +1,4 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
@ -16,15 +17,16 @@ import argparse
|
|||||||
import collections
|
import collections
|
||||||
import functools
|
import functools
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
from oslo_utils import importutils
|
from oslo_utils import importutils
|
||||||
import six
|
import six
|
||||||
|
|
||||||
termcolor = importutils.try_import('termcolor')
|
|
||||||
|
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
|
||||||
|
termcolor = importutils.try_import('termcolor')
|
||||||
|
|
||||||
|
|
||||||
_USE_COLOR = False
|
_USE_COLOR = False
|
||||||
|
|
||||||
@ -33,9 +35,29 @@ def main():
|
|||||||
global _USE_COLOR
|
global _USE_COLOR
|
||||||
args = parse_args()
|
args = parse_args()
|
||||||
_USE_COLOR = args.color
|
_USE_COLOR = args.color
|
||||||
formatter = functools.partial(console_format, args.prefix, args.locator)
|
formatter = functools.partial(
|
||||||
for line in reformat_json(args.file, formatter):
|
console_format,
|
||||||
|
args.prefix,
|
||||||
|
args.locator,
|
||||||
|
loggers=args.loggers,
|
||||||
|
levels=args.levels,
|
||||||
|
)
|
||||||
|
if args.lines:
|
||||||
|
# Read backward until we find all of our newline characters
|
||||||
|
# or reach the beginning of the file
|
||||||
|
args.file.seek(0, 2)
|
||||||
|
newlines = 0
|
||||||
|
pos = args.file.tell()
|
||||||
|
while newlines <= args.lines and pos > 0:
|
||||||
|
pos = pos - 1
|
||||||
|
args.file.seek(pos)
|
||||||
|
if args.file.read(1) == '\n':
|
||||||
|
newlines = newlines + 1
|
||||||
|
try:
|
||||||
|
for line in reformat_json(args.file, formatter, args.follow):
|
||||||
print(line)
|
print(line)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
@ -55,6 +77,21 @@ def parse_args():
|
|||||||
parser.add_argument("-c", "--color",
|
parser.add_argument("-c", "--color",
|
||||||
action='store_true', default=False,
|
action='store_true', default=False,
|
||||||
help="Color log levels (requires `termcolor`)")
|
help="Color log levels (requires `termcolor`)")
|
||||||
|
parser.add_argument("-f", "--follow",
|
||||||
|
action='store_true', default=False,
|
||||||
|
help="Continue parsing new data until"
|
||||||
|
" KeyboardInterrupt")
|
||||||
|
parser.add_argument("-n", "--lines",
|
||||||
|
required=False, type=int,
|
||||||
|
help="Last N number of records to view."
|
||||||
|
" (May show less than N records when used"
|
||||||
|
" in conjuction with --loggers or --levels)")
|
||||||
|
parser.add_argument("--loggers",
|
||||||
|
nargs='*', default=[],
|
||||||
|
help="only return results matching given logger(s)")
|
||||||
|
parser.add_argument("--levels",
|
||||||
|
nargs='*', default=[],
|
||||||
|
help="Only return lines matching given log level(s)")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
if args.color and not termcolor:
|
if args.color and not termcolor:
|
||||||
raise ImportError("Coloring requested but `termcolor` is not"
|
raise ImportError("Coloring requested but `termcolor` is not"
|
||||||
@ -85,11 +122,15 @@ def warn(prefix, msg):
|
|||||||
return "%s: %s" % (colorise('exc', prefix), msg)
|
return "%s: %s" % (colorise('exc', prefix), msg)
|
||||||
|
|
||||||
|
|
||||||
def reformat_json(fh, formatter):
|
def reformat_json(fh, formatter, follow=False):
|
||||||
# using readline allows interactive stdin to respond to every line
|
# using readline allows interactive stdin to respond to every line
|
||||||
while True:
|
while True:
|
||||||
line = fh.readline()
|
line = fh.readline()
|
||||||
if not line:
|
if not line:
|
||||||
|
if follow:
|
||||||
|
time.sleep(0.1)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
break
|
break
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if not line:
|
if not line:
|
||||||
@ -103,11 +144,19 @@ def reformat_json(fh, formatter):
|
|||||||
yield out_line
|
yield out_line
|
||||||
|
|
||||||
|
|
||||||
def console_format(prefix, locator, record):
|
def console_format(prefix, locator, record, loggers=[], levels=[]):
|
||||||
# Provide an empty string to format-specifiers the record is
|
# Provide an empty string to format-specifiers the record is
|
||||||
# missing, instead of failing. Doesn't work for non-string
|
# missing, instead of failing. Doesn't work for non-string
|
||||||
# specifiers.
|
# specifiers.
|
||||||
record = collections.defaultdict(str, record)
|
record = collections.defaultdict(str, record)
|
||||||
|
# skip if the record doesn't match a logger we are looking at
|
||||||
|
if loggers:
|
||||||
|
name = record.get('name')
|
||||||
|
if not any(name.startswith(n) for n in loggers):
|
||||||
|
return
|
||||||
|
if levels:
|
||||||
|
if record.get('levelname') not in levels:
|
||||||
|
return
|
||||||
levelname = record.get('levelname')
|
levelname = record.get('levelname')
|
||||||
if levelname:
|
if levelname:
|
||||||
record['levelname'] = colorise(levelname)
|
record['levelname'] = colorise(levelname)
|
||||||
@ -130,7 +179,7 @@ def console_format(prefix, locator, record):
|
|||||||
|
|
||||||
tb = record.get('traceback')
|
tb = record.get('traceback')
|
||||||
if tb:
|
if tb:
|
||||||
for tb_line in tb.splitlines():
|
for tb_line in tb:
|
||||||
yield ' '.join([prefix, tb_line])
|
yield ' '.join([prefix, tb_line])
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user