Search code examples
c#asp.net.netazure-application-insightsopen-telemetry

Is there a way to instrument metrics/tracing in a .NET library for both Prometheus AND application insights


I am building internal libraries for my current company and I want to instrument metrics and tracing for both Prometheus and Application insights.

The metrics will consist of gauges, histograms, and counters.

I also have a need for tracing.

It's my understanding that system.diagnostics.activity and system.diagnostics.metrics would allow me to support prometheus-net and OpenTelemetry, but not application insights.

Am I missing some way allowing all 3 collectors to work out of the box with my library?

I'd really hate to have to have 2 separate calls to metrics/tracing libraries.

Contrived Example:

public class CookieService{
    private readonly ICookieRepository _cookieRepository;
    public CookieService(ICookieRepository cookieRepository){
        _cookieRepository = cookieRepository;
    }
    public async Task AddCookies(CookieDto dto){ 
         // Track cookie flavor
         // Start span
         // Track timing
         _cookieRepository.Add(dto);
         // End timing
         // End span
    }
}

Not the greatest example, but hopefully you all will get the idea


Solution

  • The .NET OpenTelemetry SDK has exporters for Azure Monitor (Application Insights is a part of this now) and Prometheus.

    Install these packages:

    In your WithTracing block, setup the Azure Monitor exporter:

    .AddAzureMonitorTraceExporter(o => o.ConnectionString = "InstrumentationKey=your_key")
    

    In your WithMetrics block, setup the Azure Monitor and Prometheus exporters:

    .AddAzureMonitorMetricExporter(o => o.ConnectionString = "InstrumentationKey=your_key")
    .AddPrometheusExporter()
    

    The Prometheus exporter will create a /metrics route to scrape like normal.


    An alternative solution is to fully adopt the OpenTelemetry Collector. This has Azure Monitor and Prometheus remote write exporters and would any other agents you're running to scrape metrics and traces.

    If you go this route, you only need the OTLP exporter:

    It's setup is very simple:

    // Endpoint defaults to localhost:4317
    .AddOtlpExporter(config => config.Endpoint = new Uri("http://host:port"))
    

    Here is a Collector config that exports to both destinations, be sure to swap out the real values for the placeholders in all caps:

    extensions:
      basicauth/metrics:
        client_auth:
          username: METRICS_USER_ID
          password: API_KEY
    
    receivers:
      otlp:
        protocols:
          grpc:
          http:
    
    processors:
      batch:
        timeout: 1s
        send_batch_size: 1024
    
    exporters:
      logging:
        loglevel: debug
      prometheusremotewrite:
        endpoint: https://PROMETHEUS_URL
        auth:
          authenticator: basicauth/metrics
      azuremonitor:
        instrumentation_key: INSTRUMENTATION_KEY
    
    service:
      extensions: [basicauth/metrics]
      pipelines:
        metrics:
          receivers: [otlp]
          processors: [batch]
          exporters: [prometheusremotewrite]
        traces:
          receivers: [otlp]
          processors: [batch]
          exporters: [azuremonitor]