mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-09 14:50:58 +00:00
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>
This commit is contained in:
parent
a09e949e48
commit
44a6e0dfed
@ -14,6 +14,7 @@ This program
|
|||||||
|
|
||||||
from __future__ import print_function, unicode_literals
|
from __future__ import print_function, unicode_literals
|
||||||
import argparse
|
import argparse
|
||||||
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import os, os.path
|
import os, os.path
|
||||||
import random
|
import random
|
||||||
@ -1978,6 +1979,50 @@ def compare_context_objects(newconf, running):
|
|||||||
return (lines_to_add, lines_to_del)
|
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__":
|
if __name__ == "__main__":
|
||||||
# Command line options
|
# Command line options
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
@ -2045,15 +2090,24 @@ if __name__ == "__main__":
|
|||||||
action="store_true",
|
action="store_true",
|
||||||
help="Used by topotest to not delete debug or log file commands",
|
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()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
# For --test log to stdout
|
# For --test log to stdout
|
||||||
# For --reload log to /var/log/frr/frr-reload.log
|
# For --reload log to /var/log/frr/frr-reload.log
|
||||||
if args.test or args.stdout:
|
# If --logfmt, use the logfmt format
|
||||||
logging.basicConfig(format="%(asctime)s %(levelname)5s: %(message)s")
|
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
|
# Color the errors and warnings in red
|
||||||
logging.addLevelName(
|
logging.addLevelName(
|
||||||
logging.ERROR, "\033[91m %s\033[0m" % logging.getLevelName(logging.ERROR)
|
logging.ERROR, "\033[91m %s\033[0m" % logging.getLevelName(logging.ERROR)
|
||||||
@ -2061,20 +2115,15 @@ if __name__ == "__main__":
|
|||||||
logging.addLevelName(
|
logging.addLevelName(
|
||||||
logging.WARNING, "\033[91m%s\033[0m" % logging.getLevelName(logging.WARNING)
|
logging.WARNING, "\033[91m%s\033[0m" % logging.getLevelName(logging.WARNING)
|
||||||
)
|
)
|
||||||
|
if args.reload:
|
||||||
elif args.reload:
|
|
||||||
if not os.path.isdir("/var/log/frr/"):
|
if not os.path.isdir("/var/log/frr/"):
|
||||||
os.makedirs("/var/log/frr/", mode=0o0755)
|
os.makedirs("/var/log/frr/", mode=0o0755)
|
||||||
|
handler = logging.FileHandler("/var/log/frr/frr-reload.log")
|
||||||
logging.basicConfig(
|
if args.stdout:
|
||||||
filename="/var/log/frr/frr-reload.log",
|
handler = logging.StreamHandler(sys.stdout)
|
||||||
format="%(asctime)s %(levelname)5s: %(message)s",
|
handler.setFormatter(formatter)
|
||||||
)
|
|
||||||
|
|
||||||
# argparse should prevent this from happening but just to be safe...
|
|
||||||
else:
|
|
||||||
raise Exception("Must specify --reload or --test")
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
log.addHandler(handler)
|
||||||
|
|
||||||
if args.debug:
|
if args.debug:
|
||||||
log.setLevel(logging.DEBUG)
|
log.setLevel(logging.DEBUG)
|
||||||
|
Loading…
Reference in New Issue
Block a user