Architecture¶
This document explains how azure-functions-logging is structured internally and why key design choices support Azure Functions production behavior.
Design Objectives¶
The package is intentionally focused:
- Keep logging setup small for application developers.
- Preserve compatibility with Python standard
logging. - Add invocation-aware metadata without invasive patterns.
- Avoid duplicate handlers in runtime-managed environments.
- Stay dependency-light and operationally predictable.
High-Level Components¶
Core modules and responsibilities:
__init__.py: public exports andget_logger()factory._setup.py: setup orchestration, environment detection, idempotency._logger.py:FunctionLoggerwrapper and immutablebind()behavior._context.py: context variables,inject_context(), andContextFilter._formatter.py: local color formatter._json_formatter.py: structured JSON formatter._host_config.py: host policy mismatch warning logic.
Public API Boundary¶
Public symbols intentionally kept small:
setup_loggingget_loggerFunctionLoggerJsonFormatterinject_context
Everything else remains internal to keep migration and evolution manageable.
Setup Pipeline¶
setup_logging() is the entrypoint for configuration.
Behavior summary:
- Validate input (
formatmust becolororjson). - Enforce idempotency (first call wins).
- Build
ContextFilter. - Detect runtime environment.
- Apply local or runtime-safe setup strategy.
- Check potential host-level log suppression mismatch.
Environment Detection Strategy¶
Detection uses runtime environment variables:
- Functions presence:
FUNCTIONS_WORKER_RUNTIME - Azure hosted signal:
WEBSITE_INSTANCE_ID
Why this matters:
- Local standalone Python needs handler setup.
- Azure/Core Tools generally already provide host-managed handlers.
Runtime-Safe Behavior in Azure/Core Tools¶
In Functions runtime contexts, setup avoids replacing host handler graph.
Instead, it:
- Installs
ContextFilteronto existing handlers. - Installs filter on root logger for future handler coverage.
- Preserves host-managed output pipeline.
This prevents duplicate output and alignment issues with platform logging.
Local Standalone Behavior¶
In non-Functions environments:
- Target logger level is set.
StreamHandleris created when needed.- Formatter is selected by
formatparameter. ContextFilteris attached for metadata fields.
This gives deterministic local behavior with minimal code.
Context Propagation Model¶
Invocation metadata is carried through contextvars:
invocation_id_varfunction_name_vartrace_id_varcold_start_var
Benefits of contextvars:
- Thread-safe isolation.
- Async task-safe isolation.
- No need to pass context objects through deep call stacks.
Context Enrichment Flow¶
Request-level flow:
- Handler calls
inject_context(context). - Context values are extracted and stored in context variables.
ContextFilterreads values for each log record.- Formatter outputs record with context fields.
This decouples business code from formatter implementation details.
Cold Start Detection Design¶
Cold start is process-scoped and simple by design:
- Internal flag starts
True. - First
inject_context()setscold_start=True, then flips flag. - Future calls in same process return
False.
This model maps well to Azure Functions worker reuse semantics.
FunctionLogger Wrapper Pattern¶
FunctionLogger wraps standard loggers rather than replacing logging internals.
Key properties:
- Full standard method familiarity (
info,warning,exception, etc.). - Immutable binding (
bind()returns a new wrapper). - Bound keys merged into per-record extra context.
Why wrapper over subclassing global logger:
- Less risky integration with existing libraries.
- Easier incremental adoption.
- Lower chance of side effects in framework code.
Formatter Responsibilities¶
Color Formatter¶
- Optimized for local human readability.
- Shows timestamp, level, logger, message.
- Includes context metadata when present.
- Appends traceback text for exceptions.
JSON Formatter¶
- Outputs one JSON object per line.
- Captures core fields and context metadata.
- Preserves custom record fields under
extra. - Supports downstream indexing and analytics workflows.
host.json Conflict Detection¶
Host-level settings can suppress app-level log events.
The warning helper:
- Reads
host.jsonwhen present. - Resolves host default level into logging equivalent.
- Warns if host policy is stricter than configured level.
This closes a common observability blind spot during setup.
Error Handling Philosophy¶
The library prioritizes application continuity:
- Context extraction failures are silent and non-fatal.
- Missing context fields degrade to
None. - Setup validates format strictly and fails fast for invalid options.
- Host config parsing failures fail safe without crashing the app.
Operational Implications¶
For production teams, this architecture means:
- You can adopt gradually without replacing logging foundations.
- Context correlation is easy with a single injection call.
- Local and runtime behavior differ intentionally to match platform constraints.
- Cold start analysis becomes available without custom plumbing.