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

  1. Use Dependency Injection: Always inject IMeterFactory rather than creating static instances
  2. Reuse Meter instances: Create meters once and reuse them throughout the service lifetime
  3. Add relevant tags: Include contextual information with your metrics
  4. 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.