Ultimate Guide to Azure Custom Metrics Development

Azure Monitor provides hundreds of built-in metrics for every Azure service: CPU, memory, disk I/O, network throughput, queue depth. What it cannot provide out of the box is anything specific to your application: the number of active user sessions, the order processing rate, the cache hit ratio for your application-level cache, or the time taken for a critical business process.

Custom metrics fill this gap. They are emitted by your application, stored in Azure Monitor, and treated identically to built-in metrics for alerting, dashboarding, and integration. This guide covers the three methods to emit custom metrics, when to use each, and how to make them useful in practice.

Method 1: Application Insights SDK (recommended for application metrics)

Application Insights includes a TelemetryClient that can emit custom metrics alongside traces, dependencies, and exceptions. This is the simplest path for application-level custom metrics in .NET, Node.js, Java, and Python.

using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;

// Inject via DI
public class OrderService
{
    private readonly TelemetryClient _telemetry;

    public OrderService(TelemetryClient telemetry)
    {
        _telemetry = telemetry;
    }

    public async Task ProcessOrder(Order order)
    {
        var stopwatch = Stopwatch.StartNew();

        try
        {
            await _processOrder(order);
            stopwatch.Stop();

            // Track the processing time as a custom metric
            _telemetry.TrackMetric("OrderProcessingTimeMs", stopwatch.ElapsedMilliseconds,
                new Dictionary<string, string>
                {
                    { "OrderType", order.Type.ToString() },
                    { "Region", order.Region }
                });

            // Track event count
            _telemetry.TrackMetric("OrdersProcessed", 1);
        }
        catch
        {
            _telemetry.TrackMetric("OrderProcessingFailures", 1);
            throw;
        }
    }
}

Application Insights stores these in the customMetrics table in Log Analytics. Query them:

customMetrics
| where name == "OrderProcessingTimeMs"
| where timestamp > ago(24h)
| summarize
    avg(value),
    percentile(value, 95),
    percentile(value, 99)
  by bin(timestamp, 5m), tostring(customDimensions.OrderType)
| render timechart

The dimensions (properties) you attach to each metric data point allow you to slice the metric in queries and dashboards. Design dimensions deliberately: OrderType, Region, ProductCategory are useful. High-cardinality dimensions like OrderId or UserId will generate millions of distinct dimension combinations and make queries expensive.

Method 2: Azure Monitor REST API for custom metrics

The Azure Monitor Metrics REST API allows you to push custom metric data points directly to Azure Monitor, associated with any Azure resource. This method stores metrics in the Azure Monitor metrics store (not Log Analytics) and integrates natively with Azure Monitor alerts and dashboards.

The API endpoint requires authentication via a managed identity or service principal with the Monitoring Metrics Publisher role on the target resource.

import requests
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()
token = credential.get_token("https://monitoring.azure.com/")

resource_id = "/subscriptions/{subId}/resourceGroups/{rg}/providers/Microsoft.Web/sites/{appName}"

payload = {
    "time": "2025-01-15T10:30:00.000Z",
    "data": {
        "baseData": {
            "metric": "ActiveSessions",
            "namespace": "MyApp",
            "dimNames": ["Environment", "Region"],
            "series": [
                {
                    "dimValues": ["Production", "UKSouth"],
                    "min": 145,
                    "max": 210,
                    "sum": 1850,
                    "count": 10
                }
            ]
        }
    }
}

response = requests.post(
    f"https://eastus.monitoring.azure.com{resource_id}/metrics",
    headers={
        "Authorization": f"Bearer {token.token}",
        "Content-Type": "application/json"
    },
    json=payload
)

Custom metrics pushed via the REST API appear in the Azure Monitor Metrics Explorer alongside built-in metrics, making them available for the same dashboard and alerting features. They are retained for 93 days.

The REST API is appropriate for: - Non-.NET languages where the Application Insights SDK integration is limited - Infrastructure-level metrics emitted from scripts or automation - Business process metrics emitted from logic outside the application (ETL jobs, batch processes)

Method 3: OpenTelemetry (for polyglot and cross-cloud environments)

For organisations using OpenTelemetry for observability, custom metrics can be emitted using the OpenTelemetry Metrics API and exported to Azure Monitor via the Azure Monitor Exporter.

using OpenTelemetry;
using OpenTelemetry.Metrics;
using Azure.Monitor.OpenTelemetry.Exporter;

// Configure at startup
var meterProvider = Sdk.CreateMeterProviderBuilder()
    .AddMeter("MyApp.OrderProcessing")
    .AddAzureMonitorMetricExporter(options =>
    {
        options.ConnectionString = Environment.GetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING");
    })
    .Build();

// In application code
private static readonly Meter Meter = new("MyApp.OrderProcessing");
private static readonly Counter<long> OrdersProcessed = Meter.CreateCounter<long>("orders.processed");
private static readonly Histogram<double> OrderProcessingTime = Meter.CreateHistogram<double>(
    "orders.processing_time_ms",
    unit: "ms",
    description: "Time to process an order");

// Emit metrics
OrdersProcessed.Add(1, new KeyValuePair<string, object?>("order_type", "physical"));
OrderProcessingTime.Record(stopwatch.ElapsedMilliseconds, new KeyValuePair<string, object?>("order_type", "physical"));

OpenTelemetry is the right choice for: - Organisations standardising on vendor-neutral instrumentation - Polyglot environments where the same instrumentation library works across services in different languages - Workloads that need to export metrics to both Azure Monitor and a third-party observability platform (like Datadog)

Design custom metrics for actionability

A custom metric that nobody queries and no alert watches is instrumentation debt. Design custom metrics around questions you need to answer:

What are the business-critical rates? Orders per minute, payments processed per hour, documents indexed per day. These tell you whether the business process is running at expected volume.

What are the SLI (Service Level Indicator) metrics? The latency, error rate, and throughput metrics that define whether your service is meeting its SLOs. These are the metrics that alert when something is wrong.

What are the leading indicators of problems? Queue depth growing? Cache hit rate falling? Connection pool utilisation rising? Leading indicators allow you to act before users are affected.

For each metric, define the alert condition upfront. A metric without an associated alert or dashboard is probably not worth the instrumentation cost.

Setting up alerts on custom metrics

Once a custom metric is flowing, create an alert in Azure Monitor:

  1. Navigate to Monitor > Alerts > Create > Alert rule
  2. Set the scope to the resource emitting the metric
  3. Select the signal: your custom metric from the namespace you defined
  4. Set the condition: threshold, aggregation type, evaluation frequency
  5. Set the action group: who gets notified and how

For rate-based metrics, alert on deviation from a rolling average rather than a fixed threshold. A fixed threshold of "alert if orders < 100" misses the fact that orders normally run at 1,000 and dropping to 100 is a serious problem, while a drop to 95 from a normal 100 is noise.

Where Critical Cloud comes in

Custom metrics are the instrumentation that makes business-critical processes observable. Defining the right metrics, building them into the application from the start rather than retrofitting during an incident, and connecting them to alerting that reaches the right people, is part of how we build and operate systems for technology-led businesses. As the world's first Powered by Datadog accredited partner, we integrate Azure custom metrics with Datadog's correlation capabilities so application metrics appear in the same view as infrastructure and trace data. See how Critical Support works.