[bug] Not inject service.name into OpenTelemetry metric labels (e.g., dotnet_assembly_count{...})
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
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?
#5407 Looks like this was added, but requires
openmetricsformat.. 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
Encountered the same issue on <PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.14.0-beta.1" />
#5407 Looks like this was added, but requires
openmetricsformat.. 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
targetmetric is an info-typed metric whose labels MUST include the resource attributes, and MUST NOT include any other labels other thanjobandinstance. There MUST be at most onetargetinfo metric exported for each unique combination ofjobandinstance.
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