Skip to content

Azure Functions Logging

Production-oriented, developer-friendly logging for the Azure Functions Python v2 programming model.

azure-functions-logging keeps setup small while giving you structured context, cold start visibility, and practical local ergonomics.

Five-Second Start

Copy this into your function module:

from azure_functions_logging import get_logger, setup_logging

setup_logging()
logger = get_logger(__name__)

logger.info("logging initialized")

That setup is enough to begin.

Why Teams Use It

Azure Functions projects often outgrow default logging quickly:

  • Raw logs are hard to scan locally.
  • Invocation metadata is missing unless manually carried around.
  • Startup behavior is unclear during cold-start debugging.
  • Local and production log consumers need different output formats.

This library addresses those gaps with a small API surface.

Core Features

  • setup_logging() one-liner startup configuration.
  • Local colorized output (format="color") for fast visual scanning.
  • Structured NDJSON output (format="json") for production ingestion.
  • inject_context(context) to add invocation metadata fields.
  • Automatic cold_start flag detection on first invocation per process.
  • FunctionLogger.bind() for immutable request-scoped context binding.
  • Host-level host.json conflict warnings when Azure suppresses lower-level logs.
  • Idempotent setup to avoid duplicate reconfiguration.

What Gets Logged

Depending on formatter and context, events include:

  • Timestamp, level, logger name, message.
  • Invocation metadata: invocation_id, function_name, trace_id, cold_start.
  • Structured per-event fields from keyword arguments.
  • Bound context keys from bind().

Azure Handler Example

import azure.functions as func
from azure_functions_logging import get_logger, inject_context, setup_logging

setup_logging(format="json")
logger = get_logger(__name__)

app = func.FunctionApp()


@app.route(route="health")
def health(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
    inject_context(context)
    request_logger = logger.bind(route="/health", method=req.method)
    request_logger.info("health endpoint called")
    return func.HttpResponse("ok", status_code=200)

This combines runtime context injection and request binding in a safe, explicit flow.

Environment-Aware Behavior

Behavior changes intentionally by runtime:

  • Local standalone process: installs handler and formatter (color or json).
  • Azure/Core Tools runtime: installs context filter only and avoids handler duplication.

Warning

In Azure-hosted execution, host-level host.json settings can still suppress logs even when application-level setup appears correct.

Use these defaults unless you have a specific reason to diverge:

  • Local development: setup_logging(format="color")
  • Production environments: setup_logging(format="json")
  • Logger creation: get_logger(__name__)
  • Function entrypoint: inject_context(context) as first operation

Documentation Map

Start here, then branch by need:

Design Goals

The library stays intentionally narrow:

  • Improve application logging ergonomics.
  • Preserve Python standard logging compatibility.
  • Keep runtime dependencies minimal.
  • Avoid replacing tracing/APM platforms.

It is a focused logging utility, not a full observability stack.

Next Actions

If you are integrating today:

  1. Add package and call setup_logging() once.
  2. Update handlers to call inject_context(context).
  3. Add request-scoped keys with bind().
  4. Select json format for production tiers.
  5. Verify host.json level settings to avoid silent suppression.

When these are complete, your logs become immediately easier to read, correlate, and operate.