Skip to content

Commit 0a4365a

Browse files
authored
[storyteller] adding a grep wrapper with predefined scenarios (#1349)
* [storyteller] adding a grep wrapper with predefined scenarios Introduce storyteller tool to grep syslog (or any other logs) for a story line of a certain scenario. Defined scenarios are: - reboot : device reboot related events. - service : service start/stop events. - link : link up/down events. - lag : LAG up/down events. - bgp : BGP config change events. - crash : process/service crash events. Unmatched cateory is used as grepping regex directly. Signed-off-by: Ying Xie <[email protected]>
1 parent 22d79f3 commit 0a4365a

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

scripts/storyteller

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#!/usr/bin/env python3
2+
3+
'''
4+
Story Teller:
5+
Utility to help analyze log for certain sequence of events.
6+
e.g.: reboot (including warm/fast reboot), interface flapping, etc.
7+
'''
8+
9+
import argparse
10+
import subprocess
11+
12+
regex_dict = {
13+
'bgp' : 'bgpcfgd',
14+
'crash' : 'what\|unexpected exception\|notify_OA_about_syncd_exception\|SIG\|not expected',
15+
'interface' : 'updatePortOperStatus\|Configure .* to',
16+
'lag' : 'link becomes\|addLag',
17+
'reboot' : 'BOOT\|rc.local\|old_config\|minigraph.xml\|Rebooting\|reboot\|executeOperationsOnAsic\|getAsicView\|dumpVidToAsicOperatioId',
18+
'service' : 'Starting\|Stopping\|Started\|Stopped',
19+
}
20+
21+
22+
def exec_cmd(cmd):
23+
out = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, text=True)
24+
stdout, stderr = out.communicate()
25+
return out.returncode, stdout, stderr
26+
27+
28+
def build_options(after=0, before=0, context=0):
29+
options = []
30+
if after:
31+
options.append('-A {}'.format(after))
32+
if before:
33+
options.append('-B {}'.format(before))
34+
if context:
35+
options.append('-C {}'.format(context))
36+
37+
return ' '.join(x for x in options)
38+
39+
40+
def find_log(log, regex, after=0, before=0, context=0):
41+
options = build_options(after, before, context)
42+
cmd = 'ls -rt /var/log/{}* | xargs zgrep -a {} "{}"'.format(log, options, regex)
43+
_, out, _ = exec_cmd(cmd)
44+
'''
45+
Opportunity to improve:
46+
output (out) can be split to lines and send to a filter to
47+
decide if a line should be printed out or not.
48+
e.g. limited to a certain time span.
49+
'''
50+
print(out)
51+
52+
53+
def build_regex(category):
54+
regex = []
55+
for c in category.split(','):
56+
# if c is not found, add c to grep list directly
57+
regex.append(regex_dict[c] if c in regex_dict else c)
58+
59+
return '\|'.join(x for x in regex)
60+
61+
62+
def main():
63+
parser = argparse.ArgumentParser(description='Story Teller')
64+
65+
parser.add_argument('-l', '--log', help='log file prefix, e.g. syslog; default: syslog',
66+
type=str, required=False, default='syslog')
67+
parser.add_argument('-c', '--category', help='Categories: bgp, crash, interface, lag, reboot, service Specify multiple categories as c1,c2,c3; default: reboot',
68+
type=str, required=False, default='reboot')
69+
parser.add_argument('-A', '--after', help='Show N lines after match',
70+
type=int, required=False, default=0)
71+
parser.add_argument('-B', '--before', help='Show N lines before match',
72+
type=int, required=False, default=0)
73+
parser.add_argument('-C', '--context', help='Show N lines before and after match',
74+
type=int, required=False, default=0)
75+
76+
args = parser.parse_args()
77+
78+
log = args.log
79+
reg = build_regex(args.category)
80+
81+
find_log(log, reg, args.after, args.before, args.context)
82+
83+
84+
if __name__ == '__main__':
85+
main()

setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
'scripts/route_check.py',
107107
'scripts/route_check_test.sh',
108108
'scripts/sfpshow',
109+
'scripts/storyteller',
109110
'scripts/syseeprom-to-json',
110111
'scripts/tempershow',
111112
'scripts/update_json.py',

0 commit comments

Comments
 (0)