asp.netasp.net-coregrafanaopen-telemetryopen-telemetry-collector

ASP.NET Core 7: using OpenTelemetry to send traces/metrics to Grafana


I'm trying to send metrics/traces from my ASP.NET Core 7 application to Grafana.

Here's my Docker Compose file.

version: '3.4'

networks:
  my-network:
    name: my_network

services:
  sample.restaurant.server:
    image: ${DOCKER_REGISTRY-}samplerestaurantserver
    build:
      context: .
      dockerfile: sample/Sample.Restaurant.Server/Dockerfile
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=https://+:443;http://+:80
      - OTEL_EXPORTER_OTLP_ENDPOINT=grpc://otel-collector:4317
      - OTEL_METRICS_EXPORTER=otlp
      - OTEL_RESOURCE_ATTRIBUTES=service.name=Sample.Restaurant.Server
    ports:
      - 54576:80
      - 54577:443
    volumes:
      - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
      - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
    depends_on:
      - database
      - otel-collector
    networks:
      - my-network
  otel-collector:
    image: otel/opentelemetry-collector
    ports:
      - 4317:4317
    volumes:
      - ./collector-config.yml:/etc/otel-collector/collector-config.yml
    networks:
      - my-network
  grafana:
    image: grafana/grafana
    restart: unless-stopped
    ports:
      - 3000:3000
    volumes:
      - grafana_data:/var/lib/grafanaa
    depends_on:
      - otel-collector
    networks:
      - my-network

volumes:
  grafana_data: {}

And here's my collector config:

receivers:
  otlp:
    protocols:
      grpc:

exporters:
  otlp:
    endpoint: otel-collector:4317

service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [otlp]
    metrics:
      receivers: [otlp]
      exporters: [otlp]

And here's my service collection extension method that configures OpenTelemetry.

public static class TelemetryConfiguration
{
    public static IServiceCollection AddTelemetry(this IServiceCollection services,
        IWebHostEnvironment webHostEnvironment,
        string telemetryNamespace)
    {
        services.AddOpenTelemetry()
            .ConfigureResource(resource =>
            {
                resource
                    .AddService(
                        serviceName: webHostEnvironment.ApplicationName,
                        serviceNamespace: telemetryNamespace,
                        serviceVersion: Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? "1.0.0",
                        serviceInstanceId: Environment.MachineName)
                    .AddAttributes(new Dictionary<string, object>
                    {
                        { "deployment.environment", webHostEnvironment.EnvironmentName }
                    });
            })
            .WithMetrics(metrics =>
            {
                metrics
                    .AddAspNetCoreInstrumentation()
                    .AddConsoleExporter((exporterOptions, metricReaderOptions) =>
                    {
                        metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = 1000;
                    })
                    .AddOtlpExporter(builder => builder.Endpoint = new Uri("http://localhost:4317"));
            })
            .WithTracing(tracing =>
            {
                tracing
                    .AddAspNetCoreInstrumentation()
                    .AddConsoleExporter()
                    .AddOtlpExporter(builder => builder.Endpoint = new Uri("http://localhost:4317"));
            });

        return services;
    }
}

Firstly, is this correctly configured?

Secondly, how do I setup the data source in Grafana to receive the data from my collector?


Solution

  • The issue here is that you're attempting to use the OpenTelemetry collector as a Datastore. It collects, processes and forwards data to datastores, so in your example, you'll need to add a series of datastores for the various signals.

    My recommendation would be:

    If you want to, you can then use the free local version of Grafana to visualise things like Metrics.

    For production, I'd highly recommend thinking about a SaaS solution as scaling of those can be hard if you're not used to running lots of containers and datastores. That said, all of those OSS/Free solutions can be hosted and scaled if you choose to.