Example: Cold Start Detection¶
azure-functions-logging automatically flags cold starts through the cold_start field when inject_context(context) is called.
Goal¶
Track first-invocation behavior and build simple metrics patterns from logs.
How It Works¶
Cold start logic is process-scoped:
- First call to
inject_context(context)in a process setscold_start=True. - Subsequent calls set
cold_start=False.
No manual counters are required in your code.
Baseline Azure Function¶
import azure.functions as func
from azure_functions_logging import get_logger, inject_context, setup_logging
setup_logging(format="json")
logger = get_logger("cold-start-demo")
app = func.FunctionApp()
@app.route(route="status")
def status(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
inject_context(context)
logger.info("status endpoint hit")
return func.HttpResponse("ok")
Expected Event Pattern¶
After starting a new process:
{"message":"status endpoint hit","cold_start":true,...}
{"message":"status endpoint hit","cold_start":false,...}
{"message":"status endpoint hit","cold_start":false,...}
The first invocation after startup is your cold start marker.
Local Verification Steps¶
- Start local function host.
- Send one request and inspect logs.
- Confirm
cold_start=trueon first event. - Send additional requests and confirm
false. - Restart host and repeat.
Metrics Pattern: Cold Start Ratio¶
From structured logs:
- Numerator: count of events where
cold_start=true. - Denominator: count of invocation-start events.
- Ratio: cold starts / total invocations.
This gives a simple startup pressure signal over time.
Metrics Pattern: Cold Start Latency Split¶
Log duration and group by cold_start:
import time
start = time.perf_counter()
# ... handler logic ...
elapsed_ms = int((time.perf_counter() - start) * 1000)
logger.info("request completed", duration_ms=elapsed_ms)
Then compare p50/p95 duration where:
cold_start=truecold_start=false
This separates startup cost from warm-path performance.
Alerting Pattern¶
Create alert rules for:
- Spike in cold start ratio.
- Elevated error rate when
cold_start=true. - Long tail latency concentrated in cold starts.
These rules improve operational clarity during scaling events.
Combining with Context Binding¶
request_logger = logger.bind(route="/status", method=req.method)
request_logger.info("request begin")
Now each event includes:
- Invocation metadata from
inject_context(context). - Route/request metadata from
bind().
Caveats¶
- Cold start state is process-local, not global to an app instance fleet.
- Scale-out introduces multiple processes with independent first invocations.
- Restarting host or recycling worker resets the first-call marker.
Practical Dashboard Dimensions¶
Use these dimensions together:
function_namecold_startlevelextra.duration_msextra.route
This enables fast drill-down from availability to startup-specific regressions.
Example Query Intention¶
Look for events like:
message == "request completed"cold_start == true- group by
function_name
Then compare against warm-path events over same time window.