Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Instrumentation.Runtime] Prefer the built-in runtime metrics for .NET 9 targets. #2339

Merged
merged 7 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/OpenTelemetry.Instrumentation.Runtime/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
* Updated OpenTelemetry core component version(s) to `1.10.0`.
([#2317](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2317))

* Prefer built-in .NET runtime metrics for .NET 9 and greater.
([#2339](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2339))

## 1.9.0

Released 2024-Jun-18
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,19 @@ namespace OpenTelemetry.Metrics;
/// </summary>
public static class MeterProviderBuilderExtensions
{
private const string DotNetRuntimeMeterName = "System.Runtime";
private static readonly bool Net9OrGreater = Environment.Version.Major >= 9;

/// <summary>
/// Enables runtime instrumentation.
/// </summary>
/// <param name="builder"><see cref="MeterProviderBuilder"/> being configured.</param>
/// <returns>The instance of <see cref="MeterProviderBuilder"/> to chain the calls.</returns>
public static MeterProviderBuilder AddRuntimeInstrumentation(
this MeterProviderBuilder builder) =>
AddRuntimeInstrumentation(builder, configure: null);
Net9OrGreater
? builder.AddMeter(DotNetRuntimeMeterName)
: AddRuntimeInstrumentation(builder, configure: null);

/// <summary>
/// Enables runtime instrumentation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
</ItemGroup>

<ItemGroup>
<Compile Include="$(RepoRoot)\src\Shared\AssemblyVersionExtensions.cs" Link="Includes\AssemblyVersionExtensions.cs" />
<Compile Include="$(RepoRoot)\src\Shared\Guard.cs" Link="Includes\Guard.cs" />
<Compile Include="$(RepoRoot)\src\Shared\AssemblyVersionExtensions.cs" Link="Includes\AssemblyVersionExtensions.cs" />
</ItemGroup>

</Project>
6 changes: 6 additions & 0 deletions src/OpenTelemetry.Instrumentation.Runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ to the application.

## Metrics

> [!NOTE]
> .NET 9 introduced built-in runtime metrics. As such, when applications target
.NET 9 or greater this package registers a `Meter` to receive the built-in metrics.
See the [Microsoft documentation](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/built-in-metrics-runtime)
for details of the metric and attribute names for the built-in metrics.

### GC related metrics

#### process.runtime.dotnet.**gc.collections.count**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,21 @@ public void RuntimeMetricsAreCaptured()
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.True(exportedItems.Count > 1);

#if NET9_0_OR_GREATER
var assembliesCountMetric = exportedItems.FirstOrDefault(i => i.Name == "dotnet.assembly.count");
Assert.NotNull(assembliesCountMetric);

var exceptionsCountMetric = exportedItems.FirstOrDefault(i => i.Name == "dotnet.exceptions");
Assert.NotNull(exceptionsCountMetric);
Assert.True(GetValue(exceptionsCountMetric) >= 1);
#else
var assembliesCountMetric = exportedItems.FirstOrDefault(i => i.Name == "process.runtime.dotnet.assemblies.count");
Assert.NotNull(assembliesCountMetric);

var exceptionsCountMetric = exportedItems.FirstOrDefault(i => i.Name == "process.runtime.dotnet.exceptions.count");
Assert.NotNull(exceptionsCountMetric);
Assert.True(GetValue(exceptionsCountMetric) >= 1);
#endif
}

[Fact]
Expand All @@ -53,13 +62,23 @@ public void GcMetricsTest()

meterProvider.ForceFlush(MaxTimeToAllowForFlush);

#if NET9_0_OR_GREATER
// We don't need to test all metrics here as those are tested in the runtime.
// This is sufficient to validate that the runtime metrics are enabled.
var gcCountMetric = exportedItems.FirstOrDefault(i => i.Name == "dotnet.gc.collections");
Assert.NotNull(gcCountMetric);

var totalObjectsSize = exportedItems.FirstOrDefault(i => i.Name == "dotnet.gc.heap.total_allocated");
Assert.NotNull(totalObjectsSize);
#else
var gcCountMetric = exportedItems.FirstOrDefault(i => i.Name == "process.runtime.dotnet.gc.collections.count");
Assert.NotNull(gcCountMetric);

var totalObjectsSize = exportedItems.FirstOrDefault(i => i.Name == "process.runtime.dotnet.gc.objects.size");
Assert.NotNull(totalObjectsSize);
#endif

#if NET
#if NET8_0

var gcAllocationSizeMetric = exportedItems.FirstOrDefault(i => i.Name == "process.runtime.dotnet.gc.allocations.size");
Assert.NotNull(gcAllocationSizeMetric);
Expand Down Expand Up @@ -90,6 +109,16 @@ public void JitRelatedMetricsTest()

meterProvider.ForceFlush(MaxTimeToAllowForFlush);

#if NET9_0_OR_GREATER
var jitCompiledSizeMetric = exportedItems.FirstOrDefault(i => i.Name == "dotnet.jit.compiled_il.size");
Assert.NotNull(jitCompiledSizeMetric);

var jitMethodsCompiledCountMetric = exportedItems.FirstOrDefault(i => i.Name == "dotnet.jit.compiled_methods");
Assert.NotNull(jitMethodsCompiledCountMetric);

var jitCompilationTimeMetric = exportedItems.FirstOrDefault(i => i.Name == "dotnet.jit.compilation.time");
Assert.NotNull(jitCompilationTimeMetric);
#else
var jitCompiledSizeMetric = exportedItems.FirstOrDefault(i => i.Name == "process.runtime.dotnet.jit.il_compiled.size");
Assert.NotNull(jitCompiledSizeMetric);

Expand All @@ -98,6 +127,7 @@ public void JitRelatedMetricsTest()

var jitCompilationTimeMetric = exportedItems.FirstOrDefault(i => i.Name == "process.runtime.dotnet.jit.compilation_time");
Assert.NotNull(jitCompilationTimeMetric);
#endif
}

[Fact]
Expand All @@ -121,6 +151,15 @@ public async Task ThreadingRelatedMetricsTest()

meterProvider.ForceFlush(MaxTimeToAllowForFlush);

#if NET9_0_OR_GREATER
// We don't need to test all metrics here as those are tested in the runtime.
// This is sufficient to validate that the runtime metrics are enabled.
var lockContentionCountMetric = exportedItems.FirstOrDefault(i => i.Name == "dotnet.monitor.lock_contentions");
Assert.NotNull(lockContentionCountMetric);

var threadCountMetric = exportedItems.FirstOrDefault(i => i.Name == "dotnet.thread_pool.thread.count");
Assert.NotNull(threadCountMetric);
#else
var lockContentionCountMetric = exportedItems.FirstOrDefault(i => i.Name == "process.runtime.dotnet.monitor.lock_contention.count");
Assert.NotNull(lockContentionCountMetric);

Expand Down Expand Up @@ -163,6 +202,7 @@ static void TimerCallback(object? _)
timers[i].Dispose();
}
}
#endif
}
#endif

Expand Down