Example: Context Injection¶
inject_context(context) enriches log records with invocation metadata from Azure Functions context.
Goal¶
Call inject_context(context) once per invocation and observe invocation_id, function_name, trace_id, and cold_start in logs.
Baseline Handler¶
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="hello")
def hello(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
inject_context(context)
logger.info("request started")
return func.HttpResponse("hello")
Fields Added by inject_context()¶
| Field | Source | Example |
|---|---|---|
invocation_id |
context.invocation_id |
9f87... |
function_name |
context.function_name |
hello |
trace_id |
context.trace_context.trace_parent (trace ID portion) |
7ed7... |
cold_start |
internal first-call detection | true or false |
Why Call It Early¶
Call it at the top of each handler before business logic:
- Every subsequent log call includes invocation metadata.
- Errors logged later in the pipeline still carry correlation fields.
- You avoid partial logs missing context.
Complete Handler with Error Path¶
import json
import azure.functions as func
from azure_functions_logging import get_logger, inject_context, setup_logging
setup_logging(format="json")
logger = get_logger("payments.handler")
app = func.FunctionApp()
@app.route(route="payments")
def payments(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
inject_context(context)
logger.info("payments request received", method=req.method)
try:
body = req.get_json()
amount = body.get("amount")
logger.info("validating payload", amount=amount)
if amount is None:
logger.warning("missing amount field")
return func.HttpResponse("invalid payload", status_code=400)
logger.info("payment accepted", amount=amount)
return func.HttpResponse(json.dumps({"status": "ok"}), mimetype="application/json")
except Exception:
logger.exception("payments handler failed")
return func.HttpResponse("internal error", status_code=500)
Behavior Outside Azure¶
inject_context() is safe outside Azure.
If your object does not contain expected attributes, fields are set to None and execution continues.
from azure_functions_logging import get_logger, inject_context, setup_logging
class DummyContext:
invocation_id = "local-1"
function_name = "dummy"
setup_logging(format="json")
logger = get_logger("local")
inject_context(DummyContext())
logger.info("local simulation")
Recommended Request Flow¶
For each invocation:
inject_context(context)immediately.- Create optional bound logger for request metadata.
- Emit lifecycle logs for start, decision points, and completion.
- Use
logger.exception()in failure paths.
Pairing with bind()¶
request_logger = logger.bind(route="/payments", method=req.method)
request_logger.info("processing started")
This combines invocation metadata (context injection) with request metadata (binding).
What to Verify in Output¶
invocation_idpresent for every event in invocation.function_namematches actual function.trace_idconsistent across related events.cold_starttrue only on first invocation per process.
Common Mistakes¶
- Injecting context after first logs are already emitted.
- Assuming
trace_idis present when trace context is absent. - Forgetting injection in some handlers, causing partial correlation.
Tip
If you use decorators or middleware-like wrappers, place inject_context(context) in the outermost request entrypoint to guarantee consistency.