summaryrefslogtreecommitdiff
path: root/tools/frr-reload.py
diff options
context:
space:
mode:
authorGiovanni Tataranni <g.tataranni@gmail.com>2024-09-19 15:46:02 +0200
committerGiovanni Tataranni <g.tataranni@gmail.com>2025-02-17 17:33:28 +0100
commit44a6e0dfedf97d44d354210ab1f483548580c440 (patch)
tree7d382a01c3f7487647008283ce50a60c4a786d38 /tools/frr-reload.py
parenta09e949e4876faa6ddcf47e78c7f49ec3befda1a (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/frr-reload.py')
-rwxr-xr-xtools/frr-reload.py77
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)