Configuration¶
This guide documents every setup_logging() option and how configuration behaves across local development, Azure Functions Core Tools, and Azure-hosted runtimes.
Function Signature¶
def setup_logging(
*,
level: int = logging.INFO,
format: str = "color",
logger_name: str | None = None,
) -> None
setup_logging() is designed to be called once during startup.
Configuration Principles¶
- Idempotent initialization: repeated calls are no-ops.
- Environment-aware behavior: local and Azure runtime paths differ.
- Standard logging compatibility: no custom logging framework required.
Note
In Azure or Core Tools environments, the library intentionally avoids adding handlers to prevent duplicate output.
Parameter: level¶
level controls message filtering in local standalone execution.
Accepted values are standard logging levels:
logging.DEBUGlogging.INFO(default)logging.WARNINGlogging.ERRORlogging.CRITICAL
Example:
Behavior details:
- Local standalone: applied to target logger.
- Azure/Core Tools: host pipeline governs output; app-level level may be effectively constrained by host config.
Parameter: format¶
format selects output formatter in local standalone mode.
Supported values:
"color"(default)"json"
Example:
If an unsupported value is provided, setup_logging() raises ValueError.
Warning
Use format="json" for machine parsing and centralized ingestion. Color output is optimized for human readability in terminals.
Parameter: logger_name¶
logger_name lets you target a specific logger in local standalone mode.
When logger_name is None:
- Local standalone: root logger is configured.
- Azure/Core Tools: root handlers receive
ContextFilter.
When logger_name is set:
- Local standalone: named logger is configured.
- Azure/Core Tools: filter installation still follows runtime-safe behavior.
Practical recommendation:
- Prefer root configuration unless you have a clear logger isolation strategy.
Idempotency and Reconfiguration¶
setup_logging() uses internal setup state to guarantee idempotency.
Implications:
- First call wins.
- Later calls do not replace handler/formatter choices.
- Conflicting setup calls in different modules can lead to surprising expectations.
Best practice:
from azure_functions_logging import setup_logging
# Run once at module import or startup hook
setup_logging(format="json")
Environment Detection¶
The setup path depends on environment signals:
- Functions environment check:
FUNCTIONS_WORKER_RUNTIME - Azure-hosted check:
WEBSITE_INSTANCE_ID
Execution behavior by environment:
Local standalone Python process¶
- Sets logger level.
- Adds
StreamHandlerif no handlers exist. - Installs
ContextFilteron handlers. - Uses selected formatter (
ColorFormatterorJsonFormatter).
Azure Functions / Core Tools¶
- Does not add new handlers.
- Does not override host-managed handler strategy.
- Installs
ContextFilterto enrich records with invocation fields. - Emits host-level conflict warning checks.
Tip
This split behavior prevents duplicate logs in Azure while still giving rich local developer output.
host.json Level Conflict Warning¶
In Azure/Core Tools paths, the library checks host.json and warns if host defaults are stricter than your configured level.
Example warning intent:
Why this matters:
- You may set
level=logging.INFOin code. - Host config can still suppress
INFOlines. - Without a warning, this looks like missing logs.
Recommended host.json baseline:
Color vs JSON Format Selection¶
Use format="color" when:
- You are iterating locally.
- Humans are primary log consumers.
- You want fast visual scanning of level severity.
Use format="json" when:
- Logs feed aggregation systems.
- You need structured indexing and queries.
- You rely on downstream analytics and alerting.
Using get_logger() with Configuration¶
Typical startup and logger creation:
from azure_functions_logging import get_logger, setup_logging
setup_logging(format="json")
logger = get_logger(__name__)
logger.info("application initialized")
get_logger(name) returns a FunctionLogger wrapper that preserves standard logging ergonomics and supports context binding.
Advanced Pattern: Custom Formatter Pipeline¶
For advanced local scenarios you can still combine standard logging with this package:
import logging
from azure_functions_logging import setup_logging
setup_logging(format="json")
custom_handler = logging.StreamHandler()
custom_handler.setFormatter(logging.Formatter("%(levelname)s %(name)s %(message)s"))
target = logging.getLogger("custom")
target.addHandler(custom_handler)
target.setLevel(logging.INFO)
Guidelines for advanced customization:
- Avoid duplicating handlers on root unless intentional.
- Keep
inject_context(context)in handlers so context fields remain available. - Prefer one canonical output format per deployment tier.
Validation Checklist¶
Before finalizing configuration:
- Verify setup is called exactly once.
- Verify chosen
formatmatches consumer expectations. - Verify
host.jsondoes not suppress required levels. - Verify named logger usage is consistent across modules.
- Verify JSON output can be parsed by your log ingestion tool.