Introduction to Azure Functions Monitoring
Azure Functions is a serverless compute service that runs your code in response to events, scaling automatically as demand increases. But once your functions are deployed, understanding how they perform, whether they're healthy, and how to troubleshoot issues becomes essential. Monitoring Azure Functions means collecting, analyzing, and acting on telemetry data — including metrics, logs, and traces — to ensure reliability, performance, and cost efficiency.
This tutorial covers the complete monitoring story: built-in platform metrics, integrating Application Insights for rich telemetry, configuring alarms and alerts, building dashboards for visualization, and following best practices that keep your serverless applications observable and resilient.
Why Monitoring Matters for Azure Functions
In a serverless model, you don't manage the underlying infrastructure. This shifts operational responsibility upward — you're now responsible for code behavior, invocation patterns, and performance characteristics. Without monitoring, you operate blind. Here's what effective monitoring unlocks:
- Detect anomalies early: Catch execution spikes, failures, or latency degradation before users notice.
- Cost optimization: Identify functions consuming excessive memory or running too long, driving up the bill.
- Debugging and root cause analysis: Trace individual request flows across distributed systems with end-to-end correlation.
- Capacity planning: Understand concurrency, throughput, and scaling limits to configure plan settings appropriately.
- Compliance and auditing: Maintain an audit trail of every invocation, its outcome, and associated metadata.
Built-in Platform Metrics vs. Application Insights
Azure Functions exposes two tiers of monitoring data:
1. Platform Metrics (Host-Level)
These are free, lightweight metrics collected by the Azure Functions runtime itself. They include invocation count, success/failure counts, average execution time, and memory usage. You can view them in the Azure Portal under the "Metrics" blade of your Function App. They don't require any additional configuration but offer limited depth — no distributed tracing, no exception details, no dependency tracking.
2. Application Insights (Application-Level)
Application Insights is Azure's full-featured application performance monitoring (APM) service. When integrated with Azure Functions, it captures rich telemetry: request traces, dependency calls (HTTP, SQL, storage), exceptions with stack traces, custom metrics, and distributed trace correlation. This is the recommended approach for production workloads. It requires connecting your Function App to an Application Insights resource and adding the instrumentation key or connection string.
To enable Application Insights on an existing Function App, you can use the Azure CLI:
# Enable Application Insights on an existing Function App
az functionapp update \
--resource-group myResourceGroup \
--name myFunctionApp \
--set appInsightsInstrumentationKey="your-instrumentation-key"
# Or using the portal-based connection string approach (recommended for Functions v3+)
az functionapp config appsettings set \
--resource-group myResourceGroup \
--name myFunctionApp \
--settings APPINSIGHTS_INSTRUMENTATIONKEY="your-key" \
APPLICATIONINSIGHTS_CONNECTION_STRING="InstrumentationKey=your-key;IngestionEndpoint=https://region.live.applicationinsights.azure.com/"
For new Function Apps, you can specify Application Insights integration at creation time:
az functionapp create \
--resource-group myResourceGroup \
--name myFunctionApp \
--storage-account myStorageAccount \
--runtime dotnet \
--runtime-version 8 \
--functions-version 4 \
--app-insights myAppInsightsResource \
--app-insights-key "your-instrumentation-key"
Key Metrics to Monitor
Understanding which metrics matter is half the battle. Here are the essential ones organized by concern:
Execution Metrics
- Requests / Invocations: Total number of function executions over a time window. Available in both platform metrics and Application Insights as
requests. - Failed Requests: Executions resulting in exceptions or non-success HTTP status codes. Critical for availability tracking.
- Response Time / Duration: End-to-end execution time in milliseconds. Platform metric
AverageResponseTimegives a high-level view; Application Insightsdurationon requests provides percentiles and distribution.
Resource Utilization Metrics
- Memory Working Set: Average memory consumption per execution, measured in MB. High values may indicate memory leaks or inefficient code.
- CPU Time: CPU milliseconds consumed per execution. Useful for diagnosing compute-bound functions.
- IO Operations: Dependency calls tracked by Application Insights, showing latency and failure rates for outbound HTTP calls, database queries, or storage operations.
Health and Scaling Metrics
- Concurrency / Instance Count: Number of active instances serving requests. Sudden drops may indicate cold starts or scale-out delays.
- Throttled Requests: When scaling limits are hit, requests may be throttled. Monitor for HTTP 429 or specific throttle indicators.
- Cold Start Latency: For Consumption and Premium plans, the time to initialize a new instance before processing the first request. Tracked via Application Insights
tracesor custom metrics.
Querying Metrics with Kusto (KQL)
Application Insights stores data in Log Analytics workspaces. You query it using Kusto Query Language (KQL). Here are practical queries you can run in the Azure Portal's "Logs" blade or via the Azure Data Explorer:
Retrieve Invocation Counts Per Function
// Count invocations per function over the last hour
requests
| where timestamp >= ago(1h)
| summarize InvocationCount = count() by operation_Name, bin(timestamp, 5m)
| order by timestamp desc
| render timechart
Analyze Failed Requests with Exception Details
// Join failed requests with exceptions for detailed failure analysis
requests
| where timestamp >= ago(1h)
| where success == false
| join kind=leftouter (exceptions | project operation_Id, exceptionType = type, exceptionMessage = outerMessage) on operation_Id
| project timestamp, operation_Name, resultCode, duration, exceptionType, exceptionMessage
| order by timestamp desc
Track Dependency Performance (HTTP, SQL, Storage)
// Show dependency call performance by target service
dependencies
| where timestamp >= ago(1h)
| summarize
AvgDurationMs = avg(duration),
P95DurationMs = percentile(duration, 95),
FailureCount = countif(success == false)
by target, dependencyType = type
| order by AvgDurationMs desc
Monitor Memory Usage Per Instance
// Track memory working set per instance over time
performanceCounters
| where timestamp >= ago(1h)
| where name == "Private Bytes"
| project timestamp, value, cloud_RoleInstance
| summarize AvgMemoryMB = avg(value / 1024 / 1024) by bin(timestamp, 5m), cloud_RoleInstance
| render timechart
Detect Cold Starts
// Identify cold start traces
traces
| where timestamp >= ago(24h)
| where message contains "JIT compilation" or message contains "Cold start" or message contains "Initializing"
| project timestamp, message, operation_Name, cloud_RoleInstance
| order by timestamp desc
Emitting Custom Metrics from Function Code
Beyond built-in telemetry, you often need business-specific metrics — items processed, external API call latencies, queue depths, or custom dimensions. Application Insights SDKs let you emit custom metrics directly from your function code.
C# (Isolated Worker Process)
using System;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Metrics;
public class OrderProcessor
{
private readonly TelemetryClient _telemetryClient;
private static readonly MetricIdentifier _processedOrdersMetric =
new MetricIdentifier("custom", "OrdersProcessed", "Status");
public OrderProcessor(TelemetryClient telemetryClient)
{
_telemetryClient = telemetryClient;
}
[Function("ProcessOrder")]
public async Task Run(
[QueueTrigger("orders-queue")] Order order,
FunctionContext context)
{
var logger = context.GetLogger("ProcessOrder");
var startTime = DateTime.UtcNow;
try
{
// Business logic here
await ProcessOrderAsync(order);
// Emit custom metric: orders processed with status dimension
_telemetryClient.GetMetric(_processedOrdersMetric)
.TrackValue(1, "Success");
// Emit custom execution duration metric
var elapsed = (DateTime.UtcNow - startTime).TotalMilliseconds;
_telemetryClient.GetMetric(
new MetricIdentifier("custom", "ProcessingDurationMs"))
.TrackValue(elapsed);
logger.LogInformation($"Order {order.Id} processed successfully.");
}
catch (Exception ex)
{
// Track failed processing metric
_telemetryClient.GetMetric(_processedOrdersMetric)
.TrackValue(1, "Failed");
logger.LogError(ex, $"Failed to process order {order.Id}");
throw;
}
}
}
C# (In-Process Model, .NET 6/8)
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Microsoft.ApplicationInsights;
public class InventoryUpdater
{
private readonly TelemetryClient _telemetryClient;
public InventoryUpdater(TelemetryClient telemetryClient)
{
_telemetryClient = telemetryClient;
}
[FunctionName("UpdateInventory")]
public async Task Run(
[ServiceBusTrigger("inventory-updates")] string message,
ILogger log)
{
// Track a custom event with properties for richer querying
var eventProperties = new Dictionary
{
["EventType"] = "InventoryUpdate",
["Priority"] = "High",
["BatchSize"] = "1"
};
_telemetryClient.TrackEvent("InventoryUpdateReceived", eventProperties);
// Track numeric metric for throughput
_telemetryClient.TrackMetric("InventoryItemsProcessed", 1);
// Process the message
await ProcessInventoryUpdateAsync(message);
log.LogInformation("Inventory updated successfully.");
}
}
Python (v2 Programming Model)
import logging
import azure.functions as func
from opencensus.ext.azure import metrics_exporter
from opencensus.stats import aggregation, measure, stats
# Set up Application Insights metric exporter
# Requires: pip install opencensus-ext-azure
_exporter = metrics_exporter.new_metrics_exporter(
connection_string="InstrumentationKey=your-key;IngestionEndpoint=...")
stats.stats.view_manager.register_exporter(_exporter)
# Define custom measures
processed_items_measure = measure.MeasureInt(
"processed_items", "Items processed count", "items")
processing_time_measure = measure.MeasureFloat(
"processing_time_ms", "Processing time in milliseconds", "ms")
@app.function_name("ProcessBlob")
@app.blob_trigger(arg_name="myblob", path="input-container/{name}")
def process_blob(myblob: func.InputStream):
logging.info(f"Processing blob: {myblob.name}")
# Simulate processing
item_count = len(myblob.read().splitlines())
# Record custom metrics
stats.stats.record_measure(
processed_items_measure, item_count,
{"function": "ProcessBlob", "status": "success"})
logging.info(f"Processed {item_count} items from blob.")
Node.js (JavaScript, v4 Programming Model)
const { app } = require('@azure/functions');
const { TelemetryClient } = require('applicationinsights');
const telemetryClient = new TelemetryClient(
process.env.APPLICATIONINSIGHTS_CONNECTION_STRING
);
app.http('ProcessPayment', {
handler: async (request, context) => {
const startTime = Date.now();
context.log('Processing payment request');
try {
// Business logic
const result = await processPayment(request.body);
const duration = Date.now() - startTime;
// Emit custom event with metrics
telemetryClient.trackEvent({
name: 'PaymentProcessed',
properties: {
paymentType: request.body.type,
amount: request.body.amount.toString()
},
measurements: {
processingDurationMs: duration,
amountValue: request.body.amount
}
});
return { status: 200, body: result };
} catch (error) {
telemetryClient.trackException({
exception: error,
properties: { context: 'ProcessPayment' }
});
throw error;
}
}
});
Setting Up Alerts and Alarms
Metrics alone are passive. Alerts transform monitoring into an active safety net. Azure offers multiple alert types for Functions: metric-based alerts, log-search alerts (KQL queries), and smart detection alerts from Application Insights. Here's how to configure each.
Metric-Based Alerts via Azure CLI
Metric alerts fire when a platform or Application Insights metric crosses a threshold. This example creates an alert for high failure rate:
# Create an alert rule for Function App failure rate exceeding 5%
az monitor metrics alert create \
--name "HighFailureRate-Alert" \
--resource-group "myResourceGroup" \
--scopes "/subscriptions/sub-id/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/myFunctionApp" \
--condition "Microsoft.Web/sites.Host.FailedRequests > 5" \
--window-size 5m \
--evaluation-frequency 1m \
--description "Alert when function failure rate exceeds threshold" \
--action "/subscriptions/sub-id/resourceGroups/myResourceGroup/providers/microsoft.insights/actionGroups/myActionGroup"
Log-Search Alerts (KQL-Based)
For more sophisticated conditions, use log-search alerts that run a KQL query on a schedule:
# Create a log-search alert for sustained high latency (P95 > 5 seconds over 15 min)
az monitor scheduled-query create \
--resource-group "myResourceGroup" \
--name "HighLatency-Alert" \
--scopes "/subscriptions/sub-id/resourceGroups/myResourceGroup/providers/microsoft.insights/components/myAppInsights" \
--query '
requests
| where timestamp >= ago(15m)
| summarize P95Duration = percentile(duration, 95) by operation_Name
| where P95Duration > 5000
' \
--threshold 1 \
--condition "GreaterThan" \
--evaluation-frequency 5m \
--window-size 15m \
--description "Alert on P95 latency exceeding 5 seconds" \
--action-groups "/subscriptions/sub-id/resourceGroups/myResourceGroup/providers/microsoft.insights/actionGroups/myActionGroup"
Smart Detection Alerts
Application Insights includes built-in machine learning-based anomaly detection. These detect unusual patterns in failure rates, response time degradation, and traffic anomalies automatically. Enable them via the portal under Application Insights > Smart Detection, or via ARM/Bicep. No additional configuration is needed beyond having Application Insights connected.
Creating an Action Group
Alerts need action groups to notify you. Here's how to create one that sends email and triggers a Logic App for automated remediation:
az monitor action-group create \
--resource-group "myResourceGroup" \
--name "CriticalAlerts-ActionGroup" \
--short-name "Critical" \
--action email ops-team-email ops-team@contoso.com \
--action webhook remediation-hook \
"https://prod-01.centralus.logic.azure.com:443/workflows/abc123..." \
"{\"alertType\":\"AzureFunctionAlert\"}"
Building Dashboards for Visualization
Dashboards give you a single-pane-of-glass view of function health. Azure provides several options: Azure Portal dashboards (customizable tiles), Azure Monitor Workbooks (rich KQL-driven reports), and integration with Grafana for cross-platform observability.
Azure Portal Dashboard with Metrics Tiles
You can create a dashboard in the Azure Portal and pin metric charts directly. Here's an ARM-based approach to programmatically define a dashboard:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Portal/dashboards",
"apiVersion": "2020-09-01-preview",
"name": "FunctionMonitoringDashboard",
"properties": {
"lenses": [
{
"order": 0,
"parts": [
{
"position": { "x": 0, "y": 0, "rowSpan": 4, "colSpan": 6 },
"metadata": {
"inputs": [
{
"name": "resourceId",
"value": "/subscriptions/sub-id/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/myFunctionApp"
}
],
"type": "Extension/Microsoft_Azure_Monitoring/Monitoring_MetricChart",
"chart": {
"metrics": [
{
"resourceId": "/subscriptions/sub-id/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/myFunctionApp",
"metricName": "Microsoft.Web/sites.Host.FailedRequests",
"aggregationType": "Sum"
}
],
"title": "Failed Requests (5m)",
"duration": "PT1H",
"dimension": "Microsoft.Web/sites.Host.FunctionName"
}
}
},
{
"position": { "x": 6, "y": 0, "rowSpan": 4, "colSpan": 6 },
"metadata": {
"inputs": [],
"type": "Extension/Microsoft_Azure_Monitoring/Monitoring_MetricChart",
"chart": {
"metrics": [
{
"resourceId": "/subscriptions/sub-id/resourceGroups/myResourceGroup/providers/Microsoft.Web/sites/myFunctionApp",
"metricName": "Microsoft.Web/sites.Host.AverageResponseTime",
"aggregationType": "Average"
}
],
"title": "Average Response Time (ms)",
"duration": "PT1H"
}
}
}
]
}
]
}
}
]
}
Azure Monitor Workbooks
Workbooks offer richer interactivity — parameterized queries, drill-downs, and conditional formatting. Here's a workbook KQL snippet you can embed to show a comprehensive function health summary:
// Workbook query: Function Health Overview
// Parameter: TimeRange (set via workbook parameter)
let timeRange = {TimeRange};
// Summary cards
requests
| where timestamp >= timeRange
| summarize
TotalExecutions = count(),
FailedExecutions = countif(success == false),
AvgDurationMs = avg(duration),
P95DurationMs = percentile(duration, 95),
P99DurationMs = percentile(duration, 99)
| extend SuccessRate = round((1 - (FailedExecutions * 1.0 / TotalExecutions)) * 100, 2)
// Detailed breakdown by function
requests
| where timestamp >= timeRange
| summarize
Executions = count(),
Failures = countif(success == false),
AvgDuration = avg(duration),
P95 = percentile(duration, 95)
by operation_Name
| order by Executions desc
// Dependency failures
dependencies
| where timestamp >= timeRange
| where success == false
| summarize FailureCount = count() by target, dependencyType = type
| order by FailureCount desc
Grafana Integration
For teams already using Grafana, Azure Monitor and Application Insights can serve as data sources. Configure the Azure Monitor data source in Grafana with a service principal, then create panels using KQL or metric queries directly. This is ideal for unified dashboards spanning multiple clouds and services.
# Example Grafana dashboard JSON snippet for Azure Functions panel
{
"datasource": "AzureMonitor-Insights",
"queries": [
{
"query": "requests | where timestamp >= $__timeFrom() and timestamp <= $__timeTo() | summarize count() by bin(timestamp, 5m), operation_Name | render timechart",
"resultFormat": "time_series",
"queryType": "ApplicationInsights",
"appInsights": {
"appId": "/subscriptions/sub-id/resourceGroups/myResourceGroup/providers/microsoft.insights/components/myAppInsights"
}
}
],
"title": "Function Invocations Over Time",
"type": "timeseries"
}
Structured Logging and Trace Correlation
Effective monitoring relies on structured, correlated logs. When a function calls another function or external service, you need to trace that entire chain. Application Insights automatically propagates operation_Id (trace ID) across HTTP and Service Bus triggers when using the SDK properly.
Best practices for structured logging in Azure Functions:
// C# example: structured logging with correlation
public async Task Run([HttpTrigger] HttpRequest req, ILogger log)
{
// Use structured logging with named placeholders
log.LogInformation("Processing order {OrderId} for customer {CustomerId}",
order.Id, order.CustomerId);
// Properties automatically appear in Application Insights customDimensions
// Query: traces | where customDimensions.OrderId == "12345"
// Track dependency with correlation
var correlationId = Activity.Current?.Id; // W3C trace context
await httpClient.GetAsync($"https://api.example.com/orders/{order.Id}");
// This HTTP call automatically appears in dependencies with same operation_Id
}
For Python, use OpenTelemetry for automatic trace correlation across services:
# Python: structured logging with OpenTelemetry
from opentelemetry import trace
from opentelemetry.instrumentation.requests import RequestsInstrumentor
import logging
# Instrument requests library for automatic HTTP dependency tracking
RequestsInstrumentor().instrument()
tracer = trace.get_tracer(__name__)
@app.function_name("ProcessOrder")
@app.http_trigger()
def process_order(req: func.HttpRequest) -> func.HttpResponse:
with tracer.start_as_current_span("process-order") as span:
span.set_attribute("order.id", req.params.get("orderId"))
logging.info({
"event": "OrderProcessingStarted",
"orderId": req.params.get("orderId"),
"traceId": span.get_span_context().trace_id
})
# All outgoing HTTP calls within this span are automatically correlated
response = requests.get("https://api.example.com/inventory/check")
return func.HttpResponse("OK", status_code=200)
Monitoring Cost and Performance on Different Plans
Monitoring considerations vary by hosting plan:
Consumption Plan
- You pay per execution and per GB-second of memory consumption.
- Monitor
FunctionExecutionCountandMemoryWorkingSetto estimate costs. - Cold starts are inevitable — track them and optimize with "Always Ready" instances on Premium if needed.
- Be aware of the 10-minute execution timeout and scale limits (200 instances by default).
Premium Plan
- Pre-warmed instances reduce cold starts; monitor cold start frequency to verify effectiveness.
- You have reserved capacity — monitor instance count vs. your minimum instances setting.
- Track CPU and memory across instances to right-size your Premium plan SKU.
Dedicated (App Service) Plan
- Functions run on always-on VMs — cold starts are minimal.
- Monitor App Service metrics like CPU percentage, memory percentage, and HttpQueueLength.
- Use standard App Service diagnostics for troubleshooting.
Best Practices for Azure Functions Monitoring
- Always enable Application Insights in production. Platform metrics alone are insufficient for debugging failures or understanding dependencies. The cost is proportional to your telemetry volume; use sampling to control it.
- Implement sampling intelligently. For high-throughput functions, enable adaptive sampling in Application Insights (configurable in
host.json) to reduce telemetry volume while preserving statistical accuracy. A sampling rate of 10–20% often provides sufficient insight for high-volume apps. - Use the W3C trace context standard. Ensure all services propagate trace context headers (
traceparent). Azure Functions SDK does this automatically for HTTP triggers; for other triggers, use the Activity API or OpenTelemetry SDK. - Set alerts on leading indicators, not just failures. Alert on elevated latency, increased dependency failures, or abnormal invocation patterns — these often precede outright failures.
- Build dashboards that serve different audiences. Operations teams need real-time health dashboards; developers need detailed per-function performance views; product owners need business KPI dashboards (items processed, conversion rates).
- Correlate deployments with metric changes. Use deployment markers in dashboards or KQL queries joining traces with deployment timestamps to quickly identify whether a recent deployment caused a regression.
- Monitor cold starts and optimize. Cold starts directly impact user experience. Track them, and consider Premium plan "Always Ready" instances or pre-warming techniques for latency-sensitive functions.
- Set up budget alerts. Consumption plan costs can spike unexpectedly. Use Azure Cost Management alerts tied to your Function App resource group to get notified when spending exceeds thresholds.
- Use log-level filtering in host.json. Avoid verbose logging in production. Configure
host.jsonto log only warnings and errors by default, with the ability to dynamically increase verbosity for troubleshooting via Azure App Configuration. - Test your alerts. Periodically trigger synthetic failures to verify alert rules fire and notifications reach the right people. A silent, broken alert pipeline is worse than no alert at all.
Configuring Sampling in host.json
{
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"maxTelemetryItemsPerSecond": 20,
"excludedTypes": "Request;Exception"
},
"enableLiveMetrics": true,
"enableDependencyTracking": true
},
"logLevel": {
"default": "Warning",
"Function": "Information",
"Host.Results": "Error"
}
}
}
Automating Monitoring Setup with Bicep
For production deployments, automate your entire monitoring configuration using Infrastructure as Code. Here's a Bicep snippet that provisions a Function App with Application Insights, an alert rule, and a dashboard:
// main.bicep - Complete monitoring setup for Azure Functions
param location string = resourceGroup().location
param functionAppName string = 'myfuncapp-${uniqueString(resourceGroup().id)}'
param storageAccountName string = 'st${uniqueString(resourceGroup().id)}'
// Application Insights for telemetry
resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
name: 'appinsights-${functionAppName}'
location: location
kind: 'web'
properties: {
Application_Type: 'web'
WorkspaceResourceId: logAnalyticsWorkspace.id
}
}
// Log Analytics workspace (required for log-search alerts)
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' = {
name: 'law-${functionAppName}'
location: location
properties: {
sku: { name: 'PerGB2018' }
retentionInDays: 30
}
}
// Function App with Application Insights connection
resource functionApp 'Microsoft.Web/sites@2022-03-01' = {
name: functionAppName
location: location
kind: 'functionapp'
properties: {
serverFarmId: appServicePlan.id
siteConfig: {
appSettings: [
{ name: 'APPINSIGHTS_INSTRUMENTATIONKEY', value: appInsights.properties.InstrumentationKey }
{ name: 'APPLICATIONINSIGHTS_CONNECTION_STRING', value: appInsights.properties.ConnectionString }
]
}
}
}
// Action group for notifications
resource actionGroup 'microsoft.insights/actionGroups@2022-04-01' = {
name: 'function-alerts-actiongroup'
location: 'Global'
properties: {
groupShortName: 'FuncAlert'
enabled: true
emailReceivers: [
{
name: 'ops-team'
emailAddress: 'ops-team@contoso.com'
useCommonAlertSchema: true
}
]
}
}
// Metric alert: high failure rate
resource failureAlert 'Microsoft.Insights/metricAlerts@2018-03-01' = {
name: 'high-failure-rate-alert'
location: 'Global'
properties: {
description: 'Alert when function failure rate exceeds 5%'
severity: 2
enabled: true
scopes: [functionApp.id]
evaluationFrequency: 'PT1M'
windowSize: 'PT5M'
criteria: {
'odata.type': 'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria'
allOf: [
{
name: 'Metric1'
metricName: 'Microsoft.Web/sites.Host.FailedRequests'
operator: 'GreaterThan'
threshold: 5
timeAggregation: 'Average'
criterionType: 'StaticThresholdCriterion'
}
]
}
actions: [
{ actionGroupId: actionGroup.id }
]
}
}
Conclusion
Monitoring Azure Functions is not optional — it's foundational to running reliable, cost-effective serverless applications. By combining platform metrics for quick health checks, Application Insights for deep telemetry and distributed tracing, and a well-configured alerting strategy, you gain full observability into your function estate. The code examples and patterns in this tutorial give you a practical starting point: emit custom metrics from your functions, query them with KQL, build dashboards that serve your team's specific needs, and automate everything with infrastructure as code. Start with Application Insights integration on day one, configure sampling thoughtfully, and iterate on your alerts and dashboards as your application evolves. With these practices in place, you'll catch issues before they impact users and continuously improve the performance and reliability of your serverless workloads.