2026-01-20 03:01:22 -03:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import json
|
|
|
|
|
import logging
|
2026-01-20 18:11:02 -03:00
|
|
|
import sys
|
2026-01-20 03:01:22 -03:00
|
|
|
|
2026-01-20 18:11:02 -03:00
|
|
|
import ariadne.utils.logging as logging_module
|
|
|
|
|
from ariadne.utils.logging import JsonFormatter, LogConfig, configure_logging, task_context
|
2026-01-20 03:01:22 -03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_json_formatter_includes_extra_fields() -> None:
|
|
|
|
|
record = logging.LogRecord(
|
|
|
|
|
name="ariadne.test",
|
|
|
|
|
level=logging.INFO,
|
|
|
|
|
pathname=__file__,
|
|
|
|
|
lineno=10,
|
|
|
|
|
msg="hello",
|
|
|
|
|
args=(),
|
|
|
|
|
exc_info=None,
|
|
|
|
|
)
|
|
|
|
|
record.event = "unit_test"
|
|
|
|
|
record.request_code = "REQ123"
|
|
|
|
|
|
|
|
|
|
formatter = JsonFormatter()
|
|
|
|
|
payload = json.loads(formatter.format(record))
|
|
|
|
|
|
|
|
|
|
assert payload["message"] == "hello"
|
|
|
|
|
assert payload["event"] == "unit_test"
|
|
|
|
|
assert payload["request_code"] == "REQ123"
|
2026-01-20 18:11:02 -03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_configure_logging_idempotent() -> None:
|
|
|
|
|
configure_logging(LogConfig(level="INFO"))
|
|
|
|
|
root = logging.getLogger()
|
|
|
|
|
handlers_before = list(root.handlers)
|
|
|
|
|
|
|
|
|
|
configure_logging(LogConfig(level="DEBUG"))
|
|
|
|
|
assert root.handlers == handlers_before
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_json_formatter_includes_exception() -> None:
|
|
|
|
|
try:
|
|
|
|
|
raise RuntimeError("boom")
|
|
|
|
|
except RuntimeError:
|
|
|
|
|
exc_info = sys.exc_info()
|
|
|
|
|
record = logging.LogRecord(
|
|
|
|
|
name="ariadne.test",
|
|
|
|
|
level=logging.ERROR,
|
|
|
|
|
pathname=__file__,
|
|
|
|
|
lineno=20,
|
|
|
|
|
msg="failed",
|
|
|
|
|
args=(),
|
|
|
|
|
exc_info=exc_info,
|
|
|
|
|
)
|
|
|
|
|
formatter = JsonFormatter()
|
|
|
|
|
payload = json.loads(formatter.format(record))
|
|
|
|
|
assert "exc_info" in payload
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_json_formatter_includes_stack_info() -> None:
|
|
|
|
|
record = logging.LogRecord(
|
|
|
|
|
name="ariadne.test",
|
|
|
|
|
level=logging.INFO,
|
|
|
|
|
pathname=__file__,
|
|
|
|
|
lineno=30,
|
|
|
|
|
msg="hello",
|
|
|
|
|
args=(),
|
|
|
|
|
exc_info=None,
|
|
|
|
|
sinfo="stack",
|
|
|
|
|
)
|
|
|
|
|
formatter = JsonFormatter()
|
|
|
|
|
payload = json.loads(formatter.format(record))
|
|
|
|
|
assert payload["stack_info"] == "stack"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_configure_logging_invalid_level(monkeypatch) -> None:
|
|
|
|
|
monkeypatch.setattr(logging_module, "_LOGGING_CONFIGURED", False)
|
|
|
|
|
configure_logging(LogConfig(level="nope"))
|
|
|
|
|
root = logging.getLogger()
|
|
|
|
|
assert root.level == logging.INFO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_task_context_injects_task_name() -> None:
|
|
|
|
|
record = logging.LogRecord(
|
|
|
|
|
name="ariadne.test",
|
|
|
|
|
level=logging.INFO,
|
|
|
|
|
pathname=__file__,
|
|
|
|
|
lineno=50,
|
|
|
|
|
msg="hello",
|
|
|
|
|
args=(),
|
|
|
|
|
exc_info=None,
|
|
|
|
|
)
|
|
|
|
|
assert getattr(record, "taskName", None) in {None, ""}
|
|
|
|
|
with task_context("schedule.demo"):
|
|
|
|
|
logging_module._ContextFilter().filter(record)
|
|
|
|
|
assert record.taskName == "schedule.demo"
|