Browse code

convert devstack from awk to outfilter

The complexity of the awk script was pretty high, and it would
be good to do it in summaries as well, which starts to get a bit
squirelly. Instead bring over the outfilter.py from grenade and
use it for the timestamping.

Any additional overhead from python should be offset from not
shelling out to date on every line of output.

Change-Id: Ic2b86ddba3e7f6520a0fd35599b01143936c6deb

Sean Dague authored on 2014/06/12 00:06:32
Showing 2 changed files
... ...
@@ -548,25 +548,14 @@ if [[ -n "$LOGFILE" ]]; then
548 548
     exec 3>&1
549 549
     if [[ "$VERBOSE" == "True" ]]; then
550 550
         # Set fd 1 and 2 to write the log file
551
-        exec 1> >( awk -v logfile=${LOGFILE} '
552
-                /((set \+o$)|xtrace)/ { next }
553
-                {
554
-                    cmd ="date +\"%Y-%m-%d %H:%M:%S.%3N | \""
555
-                    cmd | getline now
556
-                    close("date +\"%Y-%m-%d %H:%M:%S.%3N | \"")
557
-                    sub(/^/, now)
558
-                    print > logfile
559
-                    fflush(logfile)
560
-                    print
561
-                    fflush("")
562
-                }' ) 2>&1
551
+        exec 1> >( ./tools/outfilter.py -v -o "${LOGFILE}" ) 2>&1
563 552
         # Set fd 6 to summary log file
564
-        exec 6> >( tee "${SUMFILE}" )
553
+        exec 6> >( ./tools/outfilter.py -o "${SUMFILE}" )
565 554
     else
566 555
         # Set fd 1 and 2 to primary logfile
567
-        exec 1> "${LOGFILE}" 2>&1
556
+        exec 1> >( ./tools/outfilter.py -o "${LOGFILE}" ) 2>&1
568 557
         # Set fd 6 to summary logfile and stdout
569
-        exec 6> >( tee "${SUMFILE}" >&3 )
558
+        exec 6> >( ./tools/outfilter.py -v -o "${SUMFILE}" >&3 )
570 559
     fi
571 560
 
572 561
     echo_summary "stack.sh log $LOGFILE"
... ...
@@ -583,7 +572,7 @@ else
583 583
         exec 1>/dev/null 2>&1
584 584
     fi
585 585
     # Always send summary fd to original stdout
586
-    exec 6>&3
586
+    exec 6> >( ./tools/outfilter.py -v >&3 )
587 587
 fi
588 588
 
589 589
 # Set up logging of screen windows
590 590
new file mode 100755
... ...
@@ -0,0 +1,87 @@
0
+#!/usr/bin/env python
1
+#
2
+# Copyright 2014 Hewlett-Packard Development Company, L.P.
3
+#
4
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
5
+# not use this file except in compliance with the License. You may obtain
6
+# a copy of the License at
7
+#
8
+#      http://www.apache.org/licenses/LICENSE-2.0
9
+#
10
+# Unless required by applicable law or agreed to in writing, software
11
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+# License for the specific language governing permissions and limitations
14
+# under the License.
15
+
16
+# This is an output filter to filter and timestamp the logs from grenade and
17
+# devstack. Largely our awk filters got beyond the complexity level which were
18
+# sustainable, so this provides us much more control in a single place.
19
+#
20
+# The overhead of running python should be less than execing `date` a million
21
+# times during a run.
22
+
23
+import argparse
24
+import datetime
25
+import re
26
+import sys
27
+
28
+IGNORE_LINES = re.compile('(set \+o|xtrace)')
29
+HAS_DATE = re.compile('^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3} \|')
30
+
31
+
32
+def get_options():
33
+    parser = argparse.ArgumentParser(
34
+        description='Filter output by devstack and friends')
35
+    parser.add_argument('-o', '--outfile',
36
+                        help='Output file for content',
37
+                        default=None)
38
+    parser.add_argument('-v', '--verbose', action='store_true',
39
+                        default=False)
40
+    return parser.parse_args()
41
+
42
+
43
+def skip_line(line):
44
+    """Should we skip this line."""
45
+    return IGNORE_LINES.search(line) is not None
46
+
47
+
48
+def main():
49
+    opts = get_options()
50
+    outfile = None
51
+    if opts.outfile:
52
+        outfile = open(opts.outfile, 'a', 0)
53
+
54
+    # otherwise fileinput reprocess args as files
55
+    sys.argv = []
56
+    while True:
57
+        line = sys.stdin.readline()
58
+        if not line:
59
+            return 0
60
+
61
+        # put skip lines here
62
+        if skip_line(line):
63
+            continue
64
+
65
+        # this prevents us from nesting date lines, because
66
+        # we'd like to pull this in directly in grenade and not double
67
+        # up on devstack lines
68
+        if HAS_DATE.search(line) is None:
69
+            now = datetime.datetime.utcnow()
70
+            line = ("%s | %s" % (
71
+                now.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3],
72
+                line))
73
+
74
+        if opts.verbose:
75
+            sys.stdout.write(line)
76
+            sys.stdout.flush()
77
+        if outfile:
78
+            outfile.write(line)
79
+            outfile.flush()
80
+
81
+
82
+if __name__ == '__main__':
83
+    try:
84
+        sys.exit(main())
85
+    except KeyboardInterrupt:
86
+        sys.exit(1)