opentelemetry-dotnet icon indicating copy to clipboard operation
opentelemetry-dotnet copied to clipboard

[bug] Not inject service.name into OpenTelemetry metric labels (e.g., dotnet_assembly_count{...})

Open masterworgen opened this issue 6 months ago • 5 comments

Package

OpenTelemetry

Package Version

    <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
    <PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.12.0-beta.1" />
    <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.12.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.EntityFrameworkCore" Version="1.12.0-beta.2" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.12.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="1.12.0-beta.1" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.12.0" />

Runtime Version

net9.0

Description

I'm using OpenTelemetry in a .NET application and need to ensure that the service.name is included in the labels (attributes) of all emitted metrics, such as:

dotnet_assembly_count{otel_scope_name="System.Runtime", service_name="my-service"}

Currently, service.name is configured via a custom IResourceDetector:

Steps to Reproduce

public class MyResourceDetector(IWebHostEnvironment webHostEnvironment) : IResourceDetector
{
    public Resource Detect()
    {
        var entryAssembly = Assembly.GetEntryAssembly()?.GetName()!;

        return ResourceBuilder.CreateEmpty()
            .AddService(entryAssembly.Name!, entryAssembly.Name, entryAssembly.Version?.ToString(3), true, Environment.MachineName)
            .AddAttributes(new Dictionary<string, object>
            {
                { "service.name", entryAssembly.Name! },
                { "host.name", Environment.MachineName },
                { "host.environment", webHostEnvironment.EnvironmentName }
            })
            .Build();
    }
}

And the OpenTelemetry setup looks like this:

services.AddOpenTelemetry()
    .ConfigureResource(builder =>
        builder.AddDetector(provider => provider.GetRequiredService<MyResourceDetector>()))
    .WithMetrics(metrics =>
    {
        metrics.AddAspNetCoreInstrumentation();
        metrics.AddProcessInstrumentation();
        metrics.AddRuntimeInstrumentation();
        metrics.AddRebusInstrumentation();
        metrics.AddPrometheusExporter();
        metrics.AddHttpClientInstrumentation();
    })
    .WithTracing(tracing =>
    {
        tracing.AddAspNetCoreInstrumentation(options =>
        {
            options.Filter = context => !context.Request.Path.StartsWithSegments("/metrics");
        });
        tracing.AddHttpClientInstrumentation();
        tracing.AddEntityFrameworkCoreInstrumentation(options => { options.SetDbStatementForText = true; });
        tracing.AddRebusInstrumentation();
        tracing.AddSource(entryAssembly.Name!);
        tracing.AddOtlpExporter(options => { options.Endpoint = new Uri(option.Endpoint); });
    });

Expected Result

Get in prometheus dotnet_assembly_count{otel_scope_name="System.Runtime", service_name="my-service"}

Actual Result

dotnet_assembly_count{otel_scope_name="System.Runtime"}

Additional Context

No response

masterworgen avatar Jun 26 '25 05:06 masterworgen

https://github.com/open-telemetry/opentelemetry-dotnet/pull/5407 Looks like this was added, but requires openmetrics format.. Are you scraping while requesting for open metrics format?

cijothomas avatar Jul 08 '25 15:07 cijothomas

#5407 Looks like this was added, but requires openmetrics format.. Are you scraping while requesting for open metrics format? I didn't look at what was being sent.

I just change OpenTelemetry.Exporter.Prometheus.AspNetCore to OtlpExporter, and i get my labels Problem in OpenTelemetry.Exporter.Prometheus.AspNetCore

masterworgen avatar Jul 09 '25 11:07 masterworgen

Encountered the same issue on <PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.14.0-beta.1" />

czd890 avatar Nov 26 '25 07:11 czd890

#5407 Looks like this was added, but requires openmetrics format.. Are you scraping while requesting for open metrics format?

As noted above, the resource attributes are currently only written if OpenMetricsRequested=true.

https://github.com/open-telemetry/opentelemetry-dotnet/blob/b7fe6b28866bb07ebffcb9755fd4d9ccc32b3df4/src/OpenTelemetry.Exporter.Prometheus.HttpListener/Internal/PrometheusCollectionManager.cs#L233-L235

That was introduced by #5182 to fix #3972.

The relevant part of the specification is here but it isn't immediately obvious to me from reading it whether or not that's where the guard comes from. If it were enabled for OpenMetricsRequested=false, then we'd have to ensure that the job and instance labels were present so.

I think this is the pertinent part in that regard:

The target metric is an info-typed metric whose labels MUST include the resource attributes, and MUST NOT include any other labels other than job and instance. There MUST be at most one target info metric exported for each unique combination of job and instance.

martincostello avatar Nov 26 '25 10:11 martincostello

Thank you @martincostello Get the expected data if adding 'application/openmetrics-text' header.

curl --location --request GET 'http://localhost:8080/metrics' \
--header 'Accept: application/openmetrics-text'

## output
# TYPE target info
# HELP target Target metadata
target_info{env="local",region="aws-east-1"}
# TYPE otel_scope_info info
# HELP otel_scope_info Scope metadata
otel_scope_info{otel_scope_name="test_scope_name"} 1
# TYPE test_metric counter
test_metric_total{otel_scope_name="test_scope_name",otel_scope_version="1.0.0"} 1 1764209766.399
# EOF

czd890 avatar Nov 27 '25 03:11 czd890