Monitoring .NET Application Performance with IMeterFactory
Introduction
Application performance monitoring is crucial for maintaining healthy production systems. In this article, we’ll explore how to use IMeterFactory in .NET to create custom metrics and improve application observability.
What is IMeterFactory?
IMeterFactory is part of the System.Diagnostics.Metrics namespace introduced in .NET 6+. It provides a standardized way to create and manage custom metrics in your applications.
Key Benefits
- Standardized API: Consistent interface across different monitoring tools
- Performance: Low overhead metric collection
- Flexibility: Support for various metric types (counters, histograms, gauges)
- Integration: Works seamlessly with OpenTelemetry and other observability platforms
Getting Started
First, inject IMeterFactory into your services:
public class OrderService
{
private readonly IMeterFactory _meterFactory;
private readonly Meter _meter;
private readonly Counter<long> _orderCounter;
public OrderService(IMeterFactory meterFactory)
{
_meterFactory = meterFactory;
_meter = _meterFactory.Create("OrderService");
_orderCounter = _meter.CreateCounter<long>("orders.processed");
}
}
Creating Custom Metrics
Counters
Counters track values that only increase:
public async Task ProcessOrder(Order order)
{
// Process order logic
await _orderRepository.SaveAsync(order);
// Increment counter
_orderCounter.Add(1,
new KeyValuePair<string, object?>("status", order.Status),
new KeyValuePair<string, object?>("region", order.Region));
}
Histograms
Track distribution of values over time:
private readonly Histogram<double> _orderProcessingTime;
public OrderService(IMeterFactory meterFactory)
{
_meter = _meterFactory.Create("OrderService");
_orderProcessingTime = _meter.CreateHistogram<double>("order.processing.duration");
}
public async Task ProcessOrder(Order order)
{
var stopwatch = Stopwatch.StartNew();
// Process order
await _orderRepository.SaveAsync(order);
stopwatch.Stop();
_orderProcessingTime.Record(stopwatch.ElapsedMilliseconds);
}
Best Practices
- Use Dependency Injection: Always inject
IMeterFactoryrather than creating static instances - Reuse Meter instances: Create meters once and reuse them throughout the service lifetime
- Add relevant tags: Include contextual information with your metrics
- Monitor resource usage: Keep an eye on the overhead of metric collection
Integration with Application Insights
Configure your application to export metrics to Azure Application Insights:
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics =>
{
metrics.AddMeter("OrderService");
metrics.AddAzureMonitorMetricExporter(options =>
{
options.ConnectionString = configuration["ApplicationInsights:ConnectionString"];
});
});
Performance Considerations
- Metrics have minimal overhead when not actively observed
- Use appropriate metric types for your use case
- Avoid creating too many unique tag combinations
- Consider sampling for high-frequency operations
Conclusion
IMeterFactory provides a powerful, standardized approach to application monitoring in .NET. By implementing custom metrics, you gain valuable insights into your application’s behavior and performance, enabling proactive issue detection and optimization.
Start small with a few key metrics and gradually expand your monitoring coverage as you identify critical areas of your application.