014 add json logging
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import json
|
||||
import logging
|
||||
from io import StringIO
|
||||
|
||||
import structlog
|
||||
|
||||
from app.runtime.logging import configure_logging
|
||||
|
||||
|
||||
def test_application_log_is_serialized_as_json() -> None:
|
||||
stream = StringIO()
|
||||
|
||||
configure_logging(stream=stream)
|
||||
|
||||
logging.getLogger("app.test").info("application_event")
|
||||
|
||||
payload = json.loads(stream.getvalue().splitlines()[0])
|
||||
|
||||
assert payload["event"] == "application_event"
|
||||
assert payload["level"] == "info"
|
||||
assert payload["logger"] == "app.test"
|
||||
assert isinstance(payload["timestamp"], str)
|
||||
|
||||
_reset_logging()
|
||||
|
||||
|
||||
def test_uvicorn_loggers_use_shared_json_logging_setup() -> None:
|
||||
stream = StringIO()
|
||||
|
||||
configure_logging(stream=stream)
|
||||
|
||||
logging.getLogger("uvicorn.error").error("uvicorn_error_event")
|
||||
logging.getLogger("uvicorn.access").info("uvicorn_access_event")
|
||||
|
||||
records = [json.loads(line) for line in stream.getvalue().splitlines()]
|
||||
|
||||
assert [record["event"] for record in records] == [
|
||||
"uvicorn_error_event",
|
||||
"uvicorn_access_event",
|
||||
]
|
||||
assert [record["logger"] for record in records] == [
|
||||
"uvicorn.error",
|
||||
"uvicorn.access",
|
||||
]
|
||||
assert all(record["level"] in {"error", "info"} for record in records)
|
||||
assert all(isinstance(record["timestamp"], str) for record in records)
|
||||
|
||||
_reset_logging()
|
||||
|
||||
|
||||
def _reset_logging() -> None:
|
||||
structlog.reset_defaults()
|
||||
root_logger = logging.getLogger()
|
||||
root_logger.handlers = []
|
||||
for logger_name in ("uvicorn", "uvicorn.error", "uvicorn.access"):
|
||||
logging.getLogger(logger_name).handlers = []
|
||||
@@ -6,9 +6,11 @@ from fastapi import FastAPI
|
||||
|
||||
from app import config as config_module
|
||||
from app.config import Settings, get_settings
|
||||
from app.runtime import logging as logging_module
|
||||
|
||||
TEST_CONFIG_FILE = Path(__file__).resolve().parents[2] / "config.test.yaml"
|
||||
|
||||
|
||||
def _import_main_module(monkeypatch):
|
||||
get_settings.cache_clear()
|
||||
monkeypatch.setattr(config_module, "TEST_CONFIG_FILE", str(TEST_CONFIG_FILE))
|
||||
@@ -17,14 +19,27 @@ def _import_main_module(monkeypatch):
|
||||
|
||||
|
||||
def test_app_import_smoke(monkeypatch) -> None:
|
||||
bootstrap_calls: list[None] = []
|
||||
|
||||
def fake_configure_logging() -> None:
|
||||
bootstrap_calls.append(None)
|
||||
|
||||
monkeypatch.setattr(logging_module, "configure_logging", fake_configure_logging)
|
||||
main_module = _import_main_module(monkeypatch)
|
||||
|
||||
assert isinstance(main_module.app, FastAPI)
|
||||
assert isinstance(main_module.app.state.settings, Settings)
|
||||
assert bootstrap_calls == [None]
|
||||
get_settings.cache_clear()
|
||||
|
||||
|
||||
def test_app_created_with_provided_settings(monkeypatch) -> None:
|
||||
bootstrap_calls: list[None] = []
|
||||
|
||||
def fake_configure_logging() -> None:
|
||||
bootstrap_calls.append(None)
|
||||
|
||||
monkeypatch.setattr(logging_module, "configure_logging", fake_configure_logging)
|
||||
main_module = _import_main_module(monkeypatch)
|
||||
monkeypatch.setattr(config_module, "TEST_CONFIG_FILE", str(TEST_CONFIG_FILE))
|
||||
|
||||
@@ -32,4 +47,5 @@ def test_app_created_with_provided_settings(monkeypatch) -> None:
|
||||
instance = main_module.create_app(settings=settings)
|
||||
|
||||
assert instance.state.settings is settings
|
||||
assert bootstrap_calls == [None, None]
|
||||
get_settings.cache_clear()
|
||||
|
||||
Reference in New Issue
Block a user