diff options
| author | Giovanni Tataranni <g.tataranni@gmail.com> | 2024-09-19 15:46:02 +0200 | 
|---|---|---|
| committer | Giovanni Tataranni <g.tataranni@gmail.com> | 2025-02-17 17:33:28 +0100 | 
| commit | 44a6e0dfedf97d44d354210ab1f483548580c440 (patch) | |
| tree | 7d382a01c3f7487647008283ce50a60c4a786d38 /tools | |
| parent | a09e949e4876faa6ddcf47e78c7f49ec3befda1a (diff) | |
tools: add logfmt option for frr-reload.py
Add the option of printing logs in logfmt format.
Additional machine readable information can be printed via the `extra`
argument.
Example:
```python
log.debug("exit context"), extra={"line": line, "ctx_keys": ctx_keys})
log.error(f"Failed to execute command {' '.join(cmd)}", extra={"cmd": cmd})
```
Signed-off-by: Giovanni Tataranni <g.tataranni@gmail.com>
Diffstat (limited to 'tools')
| -rwxr-xr-x | tools/frr-reload.py | 77 | 
1 files changed, 63 insertions, 14 deletions
diff --git a/tools/frr-reload.py b/tools/frr-reload.py index 94327eb083..ee6f2456af 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -14,6 +14,7 @@ This program  from __future__ import print_function, unicode_literals  import argparse +import datetime  import logging  import os, os.path  import random @@ -1978,6 +1979,50 @@ def compare_context_objects(newconf, running):      return (lines_to_add, lines_to_del) +class LogFmtFormatter(logging.Formatter): +    def format(self, record: logging.LogRecord) -> str: +        """ +        Creates log messages with key=value pairs, in logfmt format. +        """ +        # Escape double quotes in the message, replace newlines with '\n' +        msg = record.getMessage().replace('"', '\\"').replace("\n", "\\n").strip() +        # Format the time in RFC 3339 format +        timestamp = datetime.datetime.fromtimestamp( +            record.created, datetime.timezone.utc +        ) +        asctime = timestamp.astimezone().isoformat(timespec="seconds") +        # Create logfmt style log message, ignore default fields +        logfmt = f'ts={asctime} level={record.levelname} msg="{msg}"' +        default_fields = [ +            "args", +            "asctime", +            "created", +            "exc_info", +            "exc_text", +            "filename", +            "funcName", +            "levelname", +            "levelno", +            "lineno", +            "module", +            "msecs", +            "msg", +            "name", +            "pathname", +            "process", +            "processName", +            "relativeCreated", +            "stack_info", +            "thread", +            "threadName", +        ] +        for key, value in vars(record).items(): +            if key in default_fields: +                continue +            logfmt += f" {key}={value}" +        return logfmt + +  if __name__ == "__main__":      # Command line options      parser = argparse.ArgumentParser( @@ -2045,15 +2090,24 @@ if __name__ == "__main__":          action="store_true",          help="Used by topotest to not delete debug or log file commands",      ) +    parser.add_argument( +        "--logfmt", +        action="store_true", +        help="Use logfmt as log format", +        default=False, +    )      args = parser.parse_args()      # Logging      # For --test log to stdout      # For --reload log to /var/log/frr/frr-reload.log -    if args.test or args.stdout: -        logging.basicConfig(format="%(asctime)s %(levelname)5s: %(message)s") - +    # If --logfmt, use the logfmt format +    formatter = logging.Formatter("%(asctime)s %(levelname)5s: %(message)s") +    handler = logging.StreamHandler() +    if args.logfmt: +        formatter = LogFmtFormatter() +    elif args.test or args.stdout:          # Color the errors and warnings in red          logging.addLevelName(              logging.ERROR, "\033[91m  %s\033[0m" % logging.getLevelName(logging.ERROR) @@ -2061,20 +2115,15 @@ if __name__ == "__main__":          logging.addLevelName(              logging.WARNING, "\033[91m%s\033[0m" % logging.getLevelName(logging.WARNING)          ) - -    elif args.reload: +    if args.reload:          if not os.path.isdir("/var/log/frr/"):              os.makedirs("/var/log/frr/", mode=0o0755) - -        logging.basicConfig( -            filename="/var/log/frr/frr-reload.log", -            format="%(asctime)s %(levelname)5s: %(message)s", -        ) - -    # argparse should prevent this from happening but just to be safe... -    else: -        raise Exception("Must specify --reload or --test") +        handler = logging.FileHandler("/var/log/frr/frr-reload.log") +    if args.stdout: +        handler = logging.StreamHandler(sys.stdout) +    handler.setFormatter(formatter)      log = logging.getLogger(__name__) +    log.addHandler(handler)      if args.debug:          log.setLevel(logging.DEBUG)  | 
