deer-flow/backend/tests/test_logging_config.py
AnoobFeng e3e5c73b03
feat(observability): add trace-id correlation and enhanced logging (#3902)
* feat(observability): add trace-id correlation and enhanced logging

- add opt-in gateway request trace correlation via X-Trace-Id
- enhance logging with configurable trace_id-aware formatting
- propagate deerflow_trace_id into runtime context and Langfuse metadata
- keep enhanced logging disabled by default to preserve existing behavior

* fix: harden trace correlation wiring

- Make logging enhancement a restart-required startup snapshot and remove per-request config reads from TraceMiddleware
- Restrict trace ids to printable ASCII before writing them to response headers, logs, and Langfuse metadata
- Gate implicit DeerFlowClient trace-id creation behind logging.enhance.enabled while preserving explicit caller opt-in
- Bind embedded client trace context per stream step to avoid generator ContextVar leaks and cross-context reset errors
- Rebind memory update trace ids in Timer/executor worker paths so enhanced logs keep the captured correlation id
- Remove unrelated __run_journal context overwrite from the trace-correlation change set

* fix(gateway): avoid eager app construction on package import

* fix(gateway): avoid config load during app import

Keep Gateway app construction import-safe when config.yaml is absent by
disabling TraceMiddleware only for that construction-time fallback path.
Startup lifespan still performs strict config loading before serving.
2026-07-03 08:01:46 +08:00

41 lines
1.2 KiB
Python

import io
import logging
from types import SimpleNamespace
from deerflow.logging_config import TraceContextFilter, configure_logging
from deerflow.trace_context import request_trace_context
def test_trace_context_filter_injects_current_trace_id() -> None:
record = logging.LogRecord("deerflow.test", logging.INFO, __file__, 1, "hello", (), None)
with request_trace_context("trace-log-1"):
assert TraceContextFilter().filter(record) is True
assert record.trace_id == "trace-log-1"
def test_configure_logging_enhanced_text_includes_trace_id() -> None:
root = logging.getLogger()
old_handlers = root.handlers[:]
old_level = root.level
stream = io.StringIO()
handler = logging.StreamHandler(stream)
try:
root.handlers = [handler]
root.setLevel(logging.INFO)
config = SimpleNamespace(
log_level="info",
logging=SimpleNamespace(enhance=SimpleNamespace(enabled=True, format="text")),
)
configure_logging(config)
with request_trace_context("trace-log-2"):
logging.getLogger("deerflow.test").info("hello")
assert "[trace_id=trace-log-2]" in stream.getvalue()
finally:
root.handlers = old_handlers
root.setLevel(old_level)