Measure Application Performance in .NET Using IMeterFactory
Performance monitoring is essential for ensuring that our applications run efficiently and reliably. .NET offers a powerful set of tools to help with this, and one of the most valuable is IMeterFactory. In this article, we'll explore how to use these tools to check the health of our applications, measure performance, and collect data for optimization.
What is IMeterFactory?
IMeterFactory is part of the System.Diagnostics.Metrics namespace introduced to provide a standardized way to create and manage meters in .NET applications. It serves as a factory for creating Meter instances, which are the foundation for recording application metrics.
Unlike the older approach of creating static Meter instances, IMeterFactory integrates seamlessly with .NET's dependency injection system, making it easier to test and manage the lifecycle of your metrics infrastructure.
Why Use IMeterFactory?
There are several compelling reasons to adopt IMeterFactory in your applications:
- Dependency Injection Support: Easily inject meters into your services
- Testability: Mock meters in unit tests without side effects
- Lifecycle Management: Automatic disposal of meters when the application shuts down
- Standardization: Follows OpenTelemetry standards for observability
Setting Up IMeterFactory
To get started, you'll need to register the metrics services in your application. Here's how to do it in an ASP.NET Core application:
var builder = WebApplication.CreateBuilder(args);
// Add metrics services
builder.Services.AddMetrics();
var app = builder.Build();
The AddMetrics() method registers IMeterFactory and related services with the dependency injection container.
Creating Custom Metrics
Once you have IMeterFactory available, you can inject it into your services and create custom metrics:
public class OrderService
{
private readonly Counter<int> _ordersProcessed;
private readonly Histogram<double> _orderProcessingTime;
public OrderService(IMeterFactory meterFactory)
{
var meter = meterFactory.Create("MyApp.Orders");
_ordersProcessed = meter.CreateCounter<int>(
"orders_processed",
unit: "orders",
description: "Total number of orders processed");
_orderProcessingTime = meter.CreateHistogram<double>(
"order_processing_duration",
unit: "ms",
description: "Time taken to process an order");
}
public async Task ProcessOrderAsync(Order order)
{
var stopwatch = Stopwatch.StartNew();
// Process the order
await ProcessAsync(order);
stopwatch.Stop();
_ordersProcessed.Add(1);
_orderProcessingTime.Record(stopwatch.ElapsedMilliseconds);
}
}
Types of Instruments
.NET provides several instrument types for different measurement scenarios:
- Counter: For values that only increase (e.g., total requests)
- UpDownCounter: For values that can increase or decrease (e.g., active connections)
- Histogram: For distribution of values (e.g., response times)
- ObservableGauge: For values observed at a point in time (e.g., memory usage)
Adding Tags for Better Analysis
Tags (or dimensions) allow you to slice and dice your metrics for more detailed analysis:
_ordersProcessed.Add(1,
new KeyValuePair<string, object?>("status", "completed"),
new KeyValuePair<string, object?>("region", "us-east"));
Exposing Metrics
To make your metrics available for collection, you can use various exporters. For Prometheus, add the following:
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics =>
{
metrics.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddPrometheusExporter();
});
app.MapPrometheusScrapingEndpoint();
Best Practices
When implementing metrics with IMeterFactory, keep these best practices in mind:
- Use meaningful names: Follow naming conventions like
service_operation_metric - Keep cardinality low: Avoid high-cardinality tags that can explode metric storage
- Document your metrics: Include clear descriptions for each instrument
- Group related metrics: Use consistent meter names for related functionality
Conclusion
IMeterFactory provides a modern, testable, and DI-friendly approach to application metrics in .NET. By leveraging this API, you can gain valuable insights into your application's performance, identify bottlenecks, and make data-driven optimization decisions. Start small with a few key metrics and expand as you understand your monitoring needs better.
The integration with OpenTelemetry standards also means your metrics can easily flow into popular observability platforms, giving you a complete picture of your application's health in production.



