[bug] resource attributes are not added to metrics defined without dependency injection
Package
OpenTelemetry.Extensions.Hosting
Package Version
| Package Name | Version |
|---|---|
| OpenTelemetry.Api | 1.12.0 |
| OpenTelemetry | 1.12.0 |
Runtime Version
net9.0
Description
metrics defined using the IMeterFactory send default tags defined by the following:
builder.Services.AddOpenTelemetry()
.ConfigureResource(resource =>
{
resource.AddAttributes(
[
new("service_name", builder.Environment.ApplicationName)
]);
})
metrics defined as static metrics don't include these added attributes as tags (such as https://github.com/dotnet/runtime/blob/b55365541d8666ef358fda08514165d6a7da47fb/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/RuntimeMetrics.cs#L39)
Steps to Reproduce
generating a new project using dotnet new aspire-starter with 9.3 templates installed.
then in the Extenstions.cs file add the following
builder.Services.AddOpenTelemetry()
.ConfigureResource(resource =>
{
+ resource.AddAttributes(
+ [
+ new("service_name", builder.Environment.ApplicationName)
+ ]);
})
.WithMetrics(metrics =>
{
metrics.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation();
+ metrics.AddMeter("Meir-service");
+ metrics.AddMeter("Meir-service-with-di");
})
then in the Program.cs of the web-api project:
add the following:
public class CustomMetersWithoutDI
{
public static readonly Meter _meter = new("Meir-service", "1.0.0");
private static readonly Counter<long> _counter = _meter.CreateCounter<long>("custom_counter", "1.0.0", "A custom counter for demonstration purposes");
private static readonly Histogram<double> _histogram = _meter.CreateHistogram<double>("custom_histogram", "1.0.0", "A custom histogram for demonstration purposes");
private static readonly UpDownCounter<long> _upDownCounter = _meter.CreateUpDownCounter<long>("custom_updown_counter", "1.0.0", "A custom up-down counter for demonstration purposes");
private static readonly ObservableGauge<double> _observableGauge = _meter.CreateObservableGauge<double>("custom_observable_gauge", () => Random.Shared.NextDouble() * 100, "A custom observable gauge for demonstration purposes");
private static readonly ObservableCounter<long> _observableCounter = _meter.CreateObservableCounter<long>("custom_observable_counter", () => Random.Shared.Next(1, 100), "A custom observable counter for demonstration purposes");
private static readonly ObservableUpDownCounter<long> _observableUpDownCounter = _meter.CreateObservableUpDownCounter<long>("custom_observable_updown_counter", () => Random.Shared.Next(-50, 50), "A custom observable up-down counter for demonstration purposes");
public static void ReportMetrics()
{
_counter.Add(1);
_histogram.Record(Random.Shared.NextDouble() * 100);
_upDownCounter.Add(1);
}
}
public class CustomMetersWithDI
{
private readonly Counter<long> _counter;
private readonly Histogram<double> _histogram;
private readonly UpDownCounter<long> _upDownCounter;
private readonly ObservableGauge<double> _observableGauge;
private readonly ObservableCounter<long> _observableCounter;
private readonly ObservableUpDownCounter<long> _observableUpDownCounter;
public CustomMetersWithDI(IMeterFactory meterFactory)
{
var meter = meterFactory.Create(new MeterOptions("Meir-service-with-di"));
_counter = meter.CreateCounter<long>("custom_counter", "1.0.0", "A custom counter for demonstration purposes");
_histogram = meter.CreateHistogram<double>("custom_histogram", "1.0.0", "A custom histogram for demonstration purposes");
_upDownCounter = meter.CreateUpDownCounter<long>("custom_updown_counter", "1.0.0", "A custom up-down counter for demonstration purposes");
_observableGauge = meter.CreateObservableGauge<double>("custom_observable_gauge", () => Random.Shared.NextDouble() * 100, "A custom observable gauge for demonstration purposes");
_observableCounter = meter.CreateObservableCounter<long>("custom_observable_counter", () => Random.Shared.Next(1, 100), "A custom observable counter for demonstration purposes");
_observableUpDownCounter = meter.CreateObservableUpDownCounter<long>("custom_observable_updown_counter", () => Random.Shared.Next(-50, 50), "A custom observable up-down counter for demonstration purposes");
}
public void ReportMetrics()
{
_counter.Add(1);
_histogram.Record(Random.Shared.NextDouble() * 100);
_upDownCounter.Add(1);
}
}
and modify the code:
service:
builder.Services.AddOpenApi();
+builder.Services.AddSingleton<CustomMetersWithDI>();
var app = builder.Build();
endpoint:
-app.MapGet("/weatherforecast", () =>
+app.MapGet("/weatherforecast", ([FromServices] CustomMetersWithDI customMeters) =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
+ CustomMetersWithoutDI.ReportMetrics();
+ customMeters.ReportMetrics();
return forecast;
})
Expected Result
the service_name tag should appear on all metrics
Actual Result
the service_name tag appears on all the aspnetcore metrics, not on the HttpClient metrics nor the runtime metrics
Additional Context
No response
the service_name tag appears on all the aspnetcore metrics, not on the HttpClient metrics nor the runtime metrics
Where and how are you validating this? Are you using ConsoleExporter? Or OTLP?
Resource attributes ("service_name" in the example) is not added as a tag in any metric by default. They are exported as Resource attributes itself, outside of any metric... So it is unclear what you meant by "service_name tag appears on all aspnetcore metrics.." Once you describe how you are validating, that can help us understand more.
I just observed the same issue when I swapped SetResourceBuilder() on each of logs, metrics and traces for a single call to ConfigureResource().
When I deployed the change my data disappeared from my observability dashboard as service.name was no longer being set. Here's the commit that reverts that change to restore things to working order: https://github.com/martincostello/costellobot/commit/c32e9fc5b83131589d74af3e73e5da7f640c6ff6
@cijothomas I'm using the aspire dashboard for to view the telemetry.
complete sample project here - https://github.com/Meir017/resource-attributes-are-not-added-to-metrics-defined-without-dependency-injection
@JamesNK is the dashboard doing anything special when collecting metrics that could explain this?