Merge branch 'logging-groups' into 'v3'
Add invocation ID to log message if available See merge request openflexure/openflexure-microscope-server!647
This commit is contained in:
commit
08f91854a9
2 changed files with 60 additions and 2 deletions
|
|
@ -19,6 +19,8 @@ from typing import Optional
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
from fastapi.responses import PlainTextResponse
|
from fastapi.responses import PlainTextResponse
|
||||||
|
|
||||||
|
from labthings_fastapi.logs import inject_invocation_id
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
OFM_LOG_FILE: Optional[str] = None
|
OFM_LOG_FILE: Optional[str] = None
|
||||||
|
|
||||||
|
|
@ -65,9 +67,12 @@ def configure_logging(log_folder: str, debug: bool = False) -> None:
|
||||||
maxBytes=1000000,
|
maxBytes=1000000,
|
||||||
backupCount=10,
|
backupCount=10,
|
||||||
)
|
)
|
||||||
format_str = "[%(asctime)s] [%(levelname)s] <%(name)s> %(message)s"
|
format_str = (
|
||||||
|
"[%(asctime)s] [%(levelname)s] <%(name)s>%(invocation_id_str)s %(message)s"
|
||||||
|
)
|
||||||
handler.setFormatter(OFMLogFileFormatter(format_str))
|
handler.setFormatter(OFMLogFileFormatter(format_str))
|
||||||
handler.addFilter(UvicornAccessFilter())
|
handler.addFilter(UvicornAccessFilter())
|
||||||
|
handler.addFilter(inject_invocation_id)
|
||||||
root_logger.addHandler(handler)
|
root_logger.addHandler(handler)
|
||||||
|
|
||||||
except PermissionError as e:
|
except PermissionError as e:
|
||||||
|
|
@ -114,7 +119,10 @@ def retrieve_log_from_file() -> PlainTextResponse:
|
||||||
|
|
||||||
|
|
||||||
class OFMLogFileFormatter(logging.Formatter):
|
class OFMLogFileFormatter(logging.Formatter):
|
||||||
"""The formatter used for the OpenFlexure Microscope Server log file."""
|
"""The formatter used for the OpenFlexure Microscope Server log file.
|
||||||
|
|
||||||
|
This is the log that is then read by the GUI.
|
||||||
|
"""
|
||||||
|
|
||||||
def format(self, record: logging.LogRecord) -> str:
|
def format(self, record: logging.LogRecord) -> str:
|
||||||
"""Adjust the logging formatting for uvicorn logs.
|
"""Adjust the logging formatting for uvicorn logs.
|
||||||
|
|
@ -125,6 +133,11 @@ class OFMLogFileFormatter(logging.Formatter):
|
||||||
such as server start up. This can lead to people erroneously thinking that
|
such as server start up. This can lead to people erroneously thinking that
|
||||||
there is an error with their miroscope.
|
there is an error with their miroscope.
|
||||||
"""
|
"""
|
||||||
|
invocation_id = getattr(record, "invocation_id", None)
|
||||||
|
record.invocation_id_str = (
|
||||||
|
f" [invocation:{invocation_id}]" if invocation_id else ""
|
||||||
|
)
|
||||||
|
|
||||||
if record.name == "uvicorn.error" and record.levelno < logging.ERROR:
|
if record.name == "uvicorn.error" and record.levelno < logging.ERROR:
|
||||||
record.name = "uvicorn"
|
record.name = "uvicorn"
|
||||||
return super().format(record)
|
return super().format(record)
|
||||||
|
|
|
||||||
|
|
@ -234,3 +234,48 @@ def test_configure_logging_debug_mode(debug_flag, expected_level):
|
||||||
# Cleanup: Remove the OFM_HANDLER from the root logger so it doesn't
|
# Cleanup: Remove the OFM_HANDLER from the root logger so it doesn't
|
||||||
# interfere with other tests in the suite.
|
# interfere with other tests in the suite.
|
||||||
root_logger.removeHandler(ofm_logging.OFM_HANDLER)
|
root_logger.removeHandler(ofm_logging.OFM_HANDLER)
|
||||||
|
|
||||||
|
|
||||||
|
def test_log_file_formatter_includes_invocation_id():
|
||||||
|
"""Check that invocation IDs are included in logs when available."""
|
||||||
|
formatter = ofm_logging.OFMLogFileFormatter(
|
||||||
|
"[%(levelname)s]%(invocation_id_str)s %(message)s"
|
||||||
|
)
|
||||||
|
|
||||||
|
record = logging.LogRecord(
|
||||||
|
name="test",
|
||||||
|
level=logging.INFO,
|
||||||
|
pathname="",
|
||||||
|
lineno=0,
|
||||||
|
msg="Test message",
|
||||||
|
args=(),
|
||||||
|
exc_info=None,
|
||||||
|
)
|
||||||
|
record.invocation_id = "abc123"
|
||||||
|
|
||||||
|
formatted = formatter.format(record)
|
||||||
|
|
||||||
|
assert "[invocation:abc123]" in formatted
|
||||||
|
assert "Test message" in formatted
|
||||||
|
|
||||||
|
|
||||||
|
def test_log_file_formatter_without_invocation_id():
|
||||||
|
"""Check that logs without invocation IDs still format correctly."""
|
||||||
|
formatter = ofm_logging.OFMLogFileFormatter(
|
||||||
|
"[%(levelname)s]%(invocation_id_str)s %(message)s"
|
||||||
|
)
|
||||||
|
|
||||||
|
record = logging.LogRecord(
|
||||||
|
name="test",
|
||||||
|
level=logging.INFO,
|
||||||
|
pathname="",
|
||||||
|
lineno=0,
|
||||||
|
msg="Test message",
|
||||||
|
args=(),
|
||||||
|
exc_info=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
formatted = formatter.format(record)
|
||||||
|
|
||||||
|
assert "[invocation:" not in formatted
|
||||||
|
assert "Test message" in formatted
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue