# 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 and `get_logger()` factory.
- `_setup.py`: setup orchestration, environment detection, idempotency.
- `_logger.py`: `FunctionLogger` wrapper and immutable `bind()` behavior.
- `_context.py`: context variables, `inject_context()`, and `ContextFilter`.
- `_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_logging`
- `get_logger`
- `FunctionLogger`
- `JsonFormatter`
- `inject_context`

Everything else remains internal to keep migration and evolution manageable.

## Setup Pipeline

`setup_logging()` is the entrypoint for configuration.

Behavior summary:

1. Validate input (`format` must be `color` or `json`).
2. Enforce idempotency (first call wins).
3. Build `ContextFilter`.
4. Detect runtime environment.
5. Apply local or runtime-safe setup strategy.
6. 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 `ContextFilter` onto 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.
- `StreamHandler` is created when needed.
- Formatter is selected by `format` parameter.
- `ContextFilter` is attached for metadata fields.

This gives deterministic local behavior with minimal code.

## Context Propagation Model

Invocation metadata is carried through `contextvars`:

- `invocation_id_var`
- `function_name_var`
- `trace_id_var`
- `cold_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:

1. Handler calls `inject_context(context)`.
2. Context values are extracted and stored in context variables.
3. `ContextFilter` reads values for each log record.
4. 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()` sets `cold_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.json` when 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.

## Related Documents

- [Usage Guide](usage.md)
- [Configuration](configuration.md)
- [API Reference](api.md)
- [Troubleshooting](troubleshooting.md)
