OpenTelemetry Metrics in Modern C# Applications
Modern C# applications rely on standardized observability frameworks to track application performance, system health, and operational reliability. This guide explores the built-in diagnostic APIs in .NET, the core OpenTelemetry SDK, essential instrumentation packages, and export pipelines available for collecting and analyzing metrics in contemporary C# projects.
Native .NET Metric APIs
Modern .NET includes native support for generating metrics through
the System.Diagnostics.Metrics namespace, eliminating the
need for third-party dependencies inside core business logic.
Meter: The primary entry point used to group and scope metrics within a library or service.Counter<T>andUpDownCounter<T>: Monotonically increasing or bidirectional values used to measure counts, such as completed requests or active connections.Histogram<T>: Measures the statistical distribution of values, commonly used for recording request durations and payload sizes.ObservableGauge<T>: Periodically samples external states that cannot be calculated incrementally, such as memory usage or queue depth.
These APIs are designed with zero overhead when no listener or collector is active.
OpenTelemetry .NET SDK
The OpenTelemetry .NET SDK acts as the bridge between native
System.Diagnostics.Metrics instruments and external metric
backends. Integration into modern ASP.NET Core applications occurs via
the OpenTelemetry.Extensions.Hosting package.
Configuration is registered during dependency injection setup:
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics =>
{
metrics
.AddMeter("Custom.Application.Meter")
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation()
.AddOtlpExporter();
});The SDK handles aggregation, sampling, and routing without modifying the application code that produces the measurements.
Core Instrumentation Packages
The OpenTelemetry ecosystem provides pre-built instrumentation packages that automatically capture operational metrics across standard .NET libraries:
OpenTelemetry.Instrumentation.AspNetCore: Captures inbound HTTP traffic metrics, including request durations, active requests, and HTTP status code distributions.OpenTelemetry.Instrumentation.Http: Tracks outbound HTTP requests made viaHttpClient, capturing response times and error rates.OpenTelemetry.Instrumentation.Runtime: Gathers critical .NET runtime indicators such as garbage collection frequency and duration, thread pool utilization, and CPU usage.OpenTelemetry.Instrumentation.Process: Collects underlying operating system metrics, including process memory footprints and CPU time.
Additional third-party libraries, such as
OpenTelemetry.Instrumentation.StackExchangeRedis and
database-specific drivers, provide targeted metrics for external
dependencies.
Exporters and Collectors
Once metrics are recorded, they must be exported to an observability platform. OpenTelemetry supports several export strategies:
- OpenTelemetry Protocol (OTLP): Implemented via
OpenTelemetry.Exporter.OpenTelemetryProtocol, this is the industry-standard exporter. It pushes metric data over gRPC or HTTP to an OpenTelemetry Collector or directly to backends like Datadog, Dynatrace, New Relic, or Grafana Mimir. - Prometheus Exporter: Provided by
OpenTelemetry.Exporter.Prometheus.AspNetCore, this package exposes a/metricsscraping endpoint compatible with Prometheus servers. - Console Exporter: Configured via
OpenTelemetry.Exporter.Console, this prints metric payloads directly to the terminal for local testing and debugging.
Diagnostics and Developer Tooling
C# developers have access to purpose-built tools for evaluating metrics during both development and production:
dotnet-counters: A command-line global tool that attaches to running .NET processes to display live metric counters in real time without external infrastructure.- .NET Aspire: An opinionated cloud-ready stack that includes a local developer dashboard designed to visualize OpenTelemetry metrics, traces, and logs instantly during development.