Browse Source

Add --default-tz

Change-Id: I4b827b257879eae396852e7464236fb86ff0f57d
Matthew Booth 1 year ago
parent
commit
4583d5c340
1 changed files with 50 additions and 17 deletions
  1. 50
    17
      oslogmerger/oslogmerger.py

+ 50
- 17
oslogmerger/oslogmerger.py View File

@@ -102,11 +102,8 @@ class LogEntry(object):
102 102
 
103 103
 
104 104
 class LogParser(object):
105
-    # Default to UTC if we have no explicit TZ
106
-    default_tz = dateutil.tz.tzutc()
107
-
108
-    def __init__(self, filename):
109
-        pass
105
+    def __init__(self, filename, cfg):
106
+        self.cfg = cfg
110 107
 
111 108
     def parse_line(self, line):
112 109
         raise NotImplementedError
@@ -115,7 +112,8 @@ class LogParser(object):
115 112
 class StrptimeParser(LogParser):
116 113
     date_format = None
117 114
 
118
-    def __init__(self, filename):
115
+    def __init__(self, filename, cfg):
116
+        super(StrptimeParser, self).__init__(filename, cfg)
119 117
         self.date_format_words = len(self.date_format.split(' '))
120 118
 
121 119
     def parse_line(self, line):
@@ -127,7 +125,7 @@ class StrptimeParser(LogParser):
127 125
         dt_str = ' '.join(dt_str)
128 126
 
129 127
         dt = datetime.strptime(dt_str, self.date_format)
130
-        dt = dt.replace(tzinfo=self.default_tz)
128
+        dt = dt.replace(tzinfo=self.cfg.default_tz)
131 129
 
132 130
         # +1 to remove the separator so we don't have 2 spaces on output
133 131
         return dt, dt_str, data
@@ -142,8 +140,8 @@ class MsgLogParser(StrptimeParser):
142 140
     """Message format: Oct 15 14:11:19"""
143 141
     date_format = '%b %d %H:%M:%S'
144 142
 
145
-    def __init__(self, filename):
146
-        super(MsgLogParser, self).__init__(filename)
143
+    def __init__(self, filename, cfg):
144
+        super(MsgLogParser, self).__init__(filename, cfg)
147 145
         stat = os.stat(filename)
148 146
 
149 147
         # TODO: handle the case where log file was closed after a year boundary
@@ -159,6 +157,9 @@ def make_tzinfo(name, sign, hours, minutes):
159 157
     tzoffset = int(minutes) * 60 + int(hours) * 3600
160 158
     if sign == '-':
161 159
         tzoffset = -tzoffset
160
+    elif sign != '+':
161
+        raise ValueError('Invalid timezone sign: %s' % sign)
162
+
162 163
     return dateutil.tz.tzoffset(name, tzoffset)
163 164
 
164 165
 
@@ -278,7 +279,9 @@ class RawSyslog(LogParser):
278 279
 class TSLogParser(LogParser):
279 280
     """Timestamped log: [275514.814982]"""
280 281
 
281
-    def __init__(self, filename):
282
+    def __init__(self, filename, cfg):
283
+        super(TSLogParser, self).__init__(filename, cfg)
284
+
282 285
         stat = os.stat(filename)
283 286
         mtime = datetime.fromtimestamp(stat.st_mtime)
284 287
         timestamp = self._get_last_timestamp(filename)
@@ -316,12 +319,12 @@ class TSLogParser(LogParser):
316 319
     def parse_line(self, line):
317 320
         end, timestamp = self._read_timestamp(line)
318 321
         dt = self.start_date + timedelta(seconds=timestamp)
319
-        dt = dt.replace(tzinfo = self.default_tz)
322
+        dt = dt.replace(tzinfo = self.cfg.default_tz)
320 323
         return dt, line[:end + 1], line[end + 1:]
321 324
 
322 325
 
323 326
 class LogFile(object):
324
-    def _detect_format(self, filename):
327
+    def _detect_format(self, filename, cfg):
325 328
         self.open(filename)
326 329
 
327 330
         parsers = []
@@ -330,7 +333,7 @@ class LogFile(object):
330 333
                 continue
331 334
 
332 335
             try:
333
-                parsers.append(cls(filename))
336
+                parsers.append(cls(filename, cfg))
334 337
             except ValueError:
335 338
                 # Don't consider the parser if we can't instantiate it for this
336 339
                 # file
@@ -357,13 +360,13 @@ class LogFile(object):
357 360
 
358 361
         raise ValueError("Failed to detect format of %s" % self.alias)
359 362
 
360
-    def __init__(self, filename, alias, parser_cls=None):
363
+    def __init__(self, filename, alias, cfg, parser_cls=None):
361 364
         self.alias = alias
362 365
 
363 366
         if parser_cls is None:
364
-            self.parser = self._detect_format(filename)
367
+            self.parser = self._detect_format(filename, cfg)
365 368
         else:
366
-            self.parser = parser_cls(filename)
369
+            self.parser = parser_cls(filename, cfg)
367 370
 
368 371
         self.open(filename)
369 372
 
@@ -482,7 +485,8 @@ def process_logs(cfg):
482 485
     logs = []
483 486
     for path, parser_cls in paths_parsers.items():
484 487
         try:
485
-            logs.append(LogFile(path, aliases[path], parser_cls))
488
+            logs.append(LogFile(path, aliases[path], cfg,
489
+                                parser_cls=parser_cls))
486 490
         except ValueError:
487 491
             print('WARNING: %s unable to determine format, ignoring' % path,
488 492
                   file=sys.stderr)
@@ -654,6 +658,29 @@ def all_unique_values(*args):
654 658
     return original_len == len(values)
655 659
 
656 660
 
661
+class TimezoneAction(argparse.Action):
662
+    def __init__(self, option_strings, dest, nargs=None, **kwargs):
663
+        if nargs is not None:
664
+            raise ValueError("nargs not allowed")
665
+
666
+        super(TimezoneAction, self).__init__(option_strings, dest, **kwargs)
667
+
668
+    @staticmethod
669
+    def parse(tzstr):
670
+        # Format: +HHMM
671
+        if len(tzstr) != 5:
672
+            raise ValueError('Invalid timezone: %s' % tzstr)
673
+
674
+        sign = tzstr[0]
675
+        hours = tzstr[1:3]
676
+        minutes = tzstr[3:5]
677
+
678
+        return make_tzinfo(tzstr, sign, hours, minutes)
679
+
680
+    def __call__(self, parser, namespace, values, option_string=None):
681
+        setattr(namespace, self.dest, self.parse(values))
682
+
683
+
657 684
 def parse_args():
658 685
     class MyParser(argparse.ArgumentParser):
659 686
         """Class to print verbose help on error."""
@@ -751,6 +778,12 @@ one has not been provided:'
751 778
     parser.add_argument('--timestamp-logs', '-tl', default=[], nargs='+',
752 779
                         dest='logfiles_t', metavar='file[:ALIAS]',
753 780
                         help='Message log files with timestamp: [   0.003036]')
781
+    parser.add_argument('--default-tz', '-tz',
782
+                        default=TimezoneAction.parse('+0000'),
783
+                        dest='default_tz', action=TimezoneAction,
784
+                        help="Default timezone for timestamps without a "
785
+                             "timezone, specified as UTC offset. "
786
+                             "Default: +0000")
754 787
 
755 788
     return parser.parse_args()
756 789
 

Loading…
Cancel
Save