Skip to content

Commit 56577b2

Browse files
Richard Barellaribab
authored andcommitted
Moved ElkLogger functionality into its own module
This is to reduce confusion when maintaining Logger.py Signed-off-by: Richard Barella <richard.t.barella@email.com>
1 parent 6217e0b commit 56577b2

File tree

6 files changed

+196
-131
lines changed

6 files changed

+196
-131
lines changed

pyclient/pymtt.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@
277277
# to stdout
278278
testDef.openLogger()
279279

280+
# open the elk logger if given, otherwise don't log to *.elog files
281+
testDef.openElkLogger()
282+
280283
# Read the input test definition file(s)
281284
testDef.configTest()
282285

pylib/System/TestDef.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def __init__(self):
6161
# set aside a spot for a logger object, and
6262
# note that it hasn't yet been defined
6363
self.logger = None
64+
# set aside a spot for the elkLogger object
65+
self.elkLogger = None
6466
self.modcmd = None
6567
# set aside per stage environment module requests
6668
self.module_unload = {}
@@ -525,6 +527,12 @@ def openLogger(self):
525527
self.logger.open(self)
526528
return
527529

530+
def openElkLogger(self):
531+
if not self.utilities.activatePluginByName("ElkLogger", "Base"):
532+
self.elkLogger = None
533+
else:
534+
self.elkLogger = self.utilities.getPluginByName("ElkLogger", "Base").plugin_object
535+
528536
def fill_log_interpolation(self, basestr, sublog):
529537
if isinstance(sublog, str):
530538
self.config.set("LOG", basestr, sublog.replace("$","$$"))

pylib/Utilities/ElkLogger.py

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
2+
from builtins import str
3+
#!/usr/bin/env python
4+
#
5+
# Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
6+
# $COPYRIGHT$
7+
#
8+
# Additional copyrights may follow
9+
#
10+
# $HEADER$
11+
#
12+
13+
import sys
14+
import datetime
15+
from BaseMTTUtility import *
16+
import json
17+
import os
18+
import pwd
19+
import grp
20+
21+
## @addtogroup Utilities
22+
# @{
23+
# @section ElkLogger
24+
# Log results to *.elog files with JSON entries to be later consumed by Elastic Stack (ELK)
25+
# Uses pymtt.py options: elk_head, elk_id, elk_testcycle, elk_testcase, elk_debug, elk_chown, elk_maxsize, elk_nostdout, elk_nostderr
26+
# @}
27+
class ElkLogger(BaseMTTUtility):
28+
def __init__(self):
29+
BaseMTTUtility.__init__(self)
30+
self.options = {}
31+
self.elk_log = None
32+
self.execmds_stash = []
33+
34+
def print_name(self):
35+
return "ElkLogger"
36+
37+
def print_options(self, testDef, prefix):
38+
lines = testDef.printOptions(self.options)
39+
for line in lines:
40+
print(prefix + line)
41+
sys.stdout.flush()
42+
return
43+
44+
def log_to_elk(self, result, logtype, testDef):
45+
result = result.copy()
46+
if testDef.options['elk_head'] is None or testDef.options['elk_id'] is None:
47+
testDef.logger.verbose_print('Error: entered log_to_elk() function without elk_id and elk_head specified')
48+
return
49+
50+
result = {k:(str(v) if isinstance(v, datetime.datetime)
51+
or isinstance(v, datetime.date) else v)
52+
for k,v in list(result.items())}
53+
result['execid'] = testDef.options['elk_id']
54+
result['cycleid'] = testDef.options['elk_testcycle']
55+
result['caseid'] = testDef.options['elk_testcase']
56+
result['logtype'] = logtype
57+
58+
# drop the stderr and stdout, will use the copies that are part of the commands issues
59+
if 'stderr' in result:
60+
del result['stderr']
61+
if 'stdout' in result:
62+
del result['stdout']
63+
64+
# convert ini_files, lists of lists into a comma separated string
65+
if 'options' in result and 'ini_files' in result['options']:
66+
result['options']['ini_files'] = ','.join(t[0] for t in result['options']['ini_files'])
67+
68+
if logtype == 'mtt-sec':
69+
# convert comamands, list of dicts into a dictionary
70+
if self.execmds_stash:
71+
result['commands'] = {"command{}".format(i):c for i,c in enumerate(self.execmds_stash)}
72+
self.execmds_stash = []
73+
74+
# convert parameters, list of lists into a dictionary
75+
if 'parameters' in result:
76+
result['parameters'] = { p[0]:p[1] for p in result['parameters'] }
77+
78+
# convert profile, list of lists into a dictionary
79+
if 'profile' in result:
80+
result['profile'] = { k:' '.join(v) for k,v in list(result['profile'].items()) }
81+
82+
if testDef.options['elk_debug']:
83+
testDef.logger.verbose_print('Logging to elk_head={}/{}.elog: {}'.format(testDef.options['elk_head'], testDef.options['elk_id'], result))
84+
85+
if self.elk_log is None:
86+
allpath = '/'
87+
for d in os.path.normpath(testDef.options['elk_head']).split(os.path.sep):
88+
allpath = os.path.join(allpath, d)
89+
if not os.path.exists(allpath):
90+
os.mkdir(allpath)
91+
uid = None
92+
gid = None
93+
if testDef.options['elk_chown'] is not None and ':' in testDef.options['elk_chown']:
94+
user = testDef.options['elk_chown'].split(':')[0]
95+
group = testDef.options['elk_chown'].split(':')[1]
96+
uid = pwd.getpwnam(user).pw_uid
97+
gid = grp.getgrnam(group).gr_gid
98+
os.chown(allpath, uid, gid)
99+
self.elk_log = open(os.path.join(testDef.options['elk_head'], '{}-{}.elog'.format(testDef.options['elk_testcase'], testDef.options['elk_id'])), 'a+')
100+
self.elk_log.write(json.dumps(result) + '\n')
101+
return
102+
103+
def log_execmd_elk(self, cmdargs, status, stdout, stderr, timedout, starttime, endtime, elapsed_secs, slurm_job_ids, testDef):
104+
if testDef.options['elk_id'] is not None:
105+
if testDef.options['elk_maxsize'] is not None:
106+
try:
107+
maxsize = int(testDef.options['elk_maxsize'])
108+
except:
109+
maxsize = None
110+
if maxsize is not None and len(stdout) > maxsize:
111+
if maxsize > 0:
112+
stdout = ['<truncated>'] + stdout[-maxsize:]
113+
else:
114+
stdout = ['<truncated>']
115+
if maxsize is not None and len(stderr) > maxsize:
116+
if maxsize > 0:
117+
stderr = ['<truncated>'] + stderr[-maxsize:]
118+
else:
119+
stderr = ['<truncated>']
120+
self.execmds_stash.append({'cmdargs': ' '.join(cmdargs),
121+
'status': status,
122+
'stdout': stdout if testDef.options['elk_nostdout'] is not None else ['<ignored>'],
123+
'stderr': stderr if testDef.options['elk_nostderr'] is not None else ['<ignored>'],
124+
'timedout': timedout,
125+
'starttime': str(starttime),
126+
'endtime': str(endtime),
127+
'elapsed': elapsed_secs,
128+
'slurm_job_ids': ','.join([str(j) for j in slurm_job_ids])
129+
})
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#
2+
# Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
3+
# $COPYRIGHT$
4+
#
5+
# Additional copyrights may follow
6+
#
7+
# $HEADER$
8+
#
9+
10+
[Core]
11+
Name = ElkLogger
12+
Module = ElkLogger
13+
14+
[Documentation]
15+
Author = Richard Barella
16+
Version = 0.1
17+
Website = N/A
18+
Description = Log results to *.elog files with JSON entries to be later consumed by Elastic Stack (ELK). Uses pymtt.py options: elk_head, elk_id, elk_testcycle, elk_testcase, elk_debug, elk_chown, elk_maxsize, elk_nostdout, elk_nostderr

pylib/Utilities/ExecuteCmd.py

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -227,15 +227,15 @@ def execute(self, options, cmdargs, testDef, quiet=False):
227227

228228
if not mycmdargs:
229229
testDef.logger.verbose_print("ExecuteCmd error: no cmdargs")
230-
if not quiet:
231-
testDef.logger.log_execmd_elk(cmdargs,
232-
1, None,
233-
'ExecuteCmd error: no cmdargs',
234-
None,
235-
datetime.datetime.now(),
236-
datetime.datetime.now(),
237-
0, None,
238-
testDef)
230+
if not quiet and testDef.elkLogger is not None and testDef.options['elk_id'] is not None:
231+
testDef.elkLogger.log_execmd_elk(cmdargs,
232+
1, None,
233+
'ExecuteCmd error: no cmdargs',
234+
None,
235+
datetime.datetime.now(),
236+
datetime.datetime.now(),
237+
0, None,
238+
testDef)
239239
return (1, [], ["MTT ExecuteCmd error: no cmdargs"], 0)
240240

241241
# define storage to catch the output
@@ -313,17 +313,17 @@ def execute(self, options, cmdargs, testDef, quiet=False):
313313
elapsed_datetime = endtime - starttime
314314
results['elapsed_secs'] = elapsed_datetime.total_seconds()
315315

316-
if not quiet:
317-
testDef.logger.log_execmd_elk(cmdargs,
318-
results['status'] if 'status' in results else None,
319-
results['stdout'] if 'stdout' in results else None,
320-
results['stderr'] if 'stderr' in results else None,
321-
results['timedout'] if 'timedout' in results else None,
322-
starttime,
323-
endtime,
324-
(endtime - starttime).total_seconds,
325-
results['slurm_job_ids'] if 'slurm_job_ids' in results else None,
326-
testDef)
316+
if not quiet and testDef.elkLogger is not None and testDef.options['elk_id'] is not None:
317+
testDef.elkLogger.log_execmd_elk(cmdargs,
318+
results['status'] if 'status' in results else None,
319+
results['stdout'] if 'stdout' in results else None,
320+
results['stderr'] if 'stderr' in results else None,
321+
results['timedout'] if 'timedout' in results else None,
322+
starttime,
323+
endtime,
324+
(endtime - starttime).total_seconds,
325+
results['slurm_job_ids'] if 'slurm_job_ids' in results else None,
326+
testDef)
327327
return results
328328

329329
if time_exec:
@@ -350,16 +350,16 @@ def execute(self, options, cmdargs, testDef, quiet=False):
350350
results['stderr'] = [str(e)]
351351
results['slurm_job_ids'] = []
352352

353-
if not quiet:
354-
testDef.logger.log_execmd_elk(cmdargs,
355-
results['status'] if 'status' in results else None,
356-
results['stdout'] if 'stdout' in results else None,
357-
results['stderr'] if 'stderr' in results else None,
358-
results['timedout'] if 'timedout' in results else None,
359-
starttime,
360-
endtime,
361-
(endtime - starttime).total_seconds(),
362-
results['slurm_job_ids'] if 'slurm_job_ids' in results else None,
363-
testDef)
353+
if not quiet and testDef.elkLogger is not None and testDef.options['elk_id'] is not None:
354+
testDef.elkLogger.log_execmd_elk(cmdargs,
355+
results['status'] if 'status' in results else None,
356+
results['stdout'] if 'stdout' in results else None,
357+
results['stderr'] if 'stderr' in results else None,
358+
results['timedout'] if 'timedout' in results else None,
359+
starttime,
360+
endtime,
361+
(endtime - starttime).total_seconds(),
362+
results['slurm_job_ids'] if 'slurm_job_ids' in results else None,
363+
testDef)
364364

365365
return results

0 commit comments

Comments
 (0)