Structured logging with request correlation.
Provides request_id propagation via ContextVar and a structured_log helper for JSON-formatted logs with request_id, user_id, path, etc.
WhenAppConfig.log_format == "json"the framework installs a crash-proof
JSONFormatter on the "chirp"logger at freeze time
(configure_json_logging()) so Chirp's own log lines share the same JSON
envelope the server (Pounce) emits, instead of leaking the divergent ad-hoc
json.dumpspayload as an unformatted line.
This module is internal — it is intentionally absent from
chirp.__all__ / chirp._LAZY_IMPORTS and from docs/public-api.md.
logging
| Name | Type | Default | Description |
|---|---|---|---|
type
|
|
— | |
qualified_name
|
|
— | |
element_type
|
|
— | |
description
|
|
— | |
source_file
|
|
— | |
line_number
|
|
— | |
is_autodoc
|
|
— | |
autodoc_element
|
|
— | |
_autodoc_template
|
|
— | |
_autodoc_url_path
|
|
— | |
_autodoc_page_type
|
|
— | |
title
|
|
— | |
doc_content_hash
|
|
— |
Symbols on this page
Return the current request ID, or None if outside a request context.
Best-effort (trace_id, span_id) hex pair from the active OTel span.
Chirp has no opentelemetry dependency — OTel is delegated to the server (Pounce) via …
Log a structured JSON message with correlation fields.
Merges request_id from context if not provided. Use for audit trails and observability pipelines that expect…
Crash-proof JSON log formatter matching the server (Pounce) envelope.
Produces{"ts", "level", "logger", "message"} (plus "exception"when
the record carriesexc_info), the same…
InstallJSONFormatter on the "chirp"logger, idempotently.
Called once at app freeze whenAppConfig.log_format == "json"so the framework's own logs match the server…
get_request_id
function
def get_request_id() -> str | None
Return the current request ID, or None if outside a request context.
No parameters.
_current_trace_context
function
def _current_trace_context() -> tuple[str, str] | None
Best-effort (trace_id, span_id) hex pair from the active OTel span.
Chirp has no opentelemetry dependency — OTel is delegated to the server
(Pounce) viaAppConfig.otel_endpoint. This reads the ambient span behind
a guarded import so logs join the trace pillar when OTel is configured and
are unchanged otherwise. ReturnsNonewhen opentelemetry is absent, no
span is active, or the span context is invalid (the no-op default span).
SSE note: the SSE drain re-establishes request context from a captured
snapshot and starts the producer inside acopy_context()
snapshot so OTel span context survives intoEventStreamgenerators.
Buffered responses and theSuspense / Streamdrains (which do
copy_contexton worker threads) keep the span for free.
No parameters.
structured_log
function
def structured_log(level: int, message: str, *, request_id: str | None = None, user_id: str | None = None, path: str | None = None, method: str | None = None, **extra: Any) -> None
Log a structured JSON message with correlation fields.
Merges request_id from context if not provided. Use for audit trails and observability pipelines that expect JSON logs.
When an OpenTelemetry span is active (configured via
AppConfig.otel_endpoint), trace_id and span_idare best-effort
bound fromget_current_span() so logs join the
trace pillar. The lookup is fully guarded — no opentelemetry dependency, no
failure surface. See_current_trace_context() for the SSE blind spot:
trace context survives buffered,Suspense, and Streamrenders and
SSEEventStream generators (via a connect-time copy_context
snapshot). See_current_trace_context() for historical context.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
level
|
int
|
— | |
message
|
str
|
— | |
request_id
|
str | None
|
None
|
|
user_id
|
str | None
|
None
|
|
path
|
str | None
|
None
|
|
method
|
str | None
|
None
|
|
**extra
|
Any
|
— |
JSONFormatter
class
Crash-proof JSON log formatter matching the server (Pounce) envelope.
Produces{"ts", "level", "logger", "message"} (plus "exception"when
the record carriesexc_info), the same shape Pounce's _JSONFormatter
emits, so Chirp's own"chirp"logger lines and the server's request lines
parse identically in a log pipeline.
Defensive by design: a record with a non-serializable extra, an exploding
getMessage, or an unformattable exception must never raise out of
format() (a logging handler that raises drops the log line and can
surface the error at the call site). Every step degrades through a nested
fallback to a minimal still-valid JSON object.
configure_json_logging
function
def configure_json_logging() -> None
InstallJSONFormatter on the "chirp"logger, idempotently.
Called once at app freeze whenAppConfig.log_format == "json"so the
framework's own logs match the server JSON shape. Idempotent — a second
call is a no-op (the marker handler is detected and reused), so repeated
freeze()calls or test re-runs never stack handlers on the process-global
logging.Logger.
Scope discipline (free-threading / shared-state safety):
- Mutates the
"chirp"logger only — neverlogging.basicConfig, which would clobber root configuration the server (Pounce) owns. propagate = Falseso a chirp JSON line is not re-emitted through an ancestor handler (no double logging through Pounce's root handler).- Installs exactly one
StreamHandlertagged with a private marker; a foreign handler an app added to the"chirp"logger is left untouched.
No parameters.
View source · /home/runner/work/chirp/chirp/site/../src/chirp/logging.py:1