Skip to content

Commit

Permalink
[Instrumentation.Runtime] Prefer the built-in runtime metrics for .NE…
Browse files Browse the repository at this point in the history
…T 9 targets. (#2339)

Co-authored-by: Piotr Kiełkowicz <[email protected]>
Co-authored-by: xiang17 <[email protected]>
  • Loading branch information
3 people authored Nov 22, 2024
1 parent a0c764e commit 07f634d
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 2 deletions.
4 changes: 4 additions & 0 deletions src/OpenTelemetry.Instrumentation.Runtime/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
* Updated OpenTelemetry core component version(s) to `1.10.0`.
([#2317](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2317))

* Built-in .NET `System.Runtime` metrics are reported for .NET 9 and greater.
For details about each individual metric check [.NET Runtime metrics docs page](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/built-in-metrics-runtime).
([#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,6 +11,9 @@ 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>
Expand All @@ -32,6 +35,11 @@ public static MeterProviderBuilder AddRuntimeInstrumentation(
{
Guard.ThrowIfNull(builder);

if (Net9OrGreater)
{
return builder.AddMeter(DotNetRuntimeMeterName);
}

var options = new RuntimeInstrumentationOptions();
configure?.Invoke(options);

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
`System.Runtime` metrics. See the [.NET Runtime metrics 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

0 comments on commit 07f634d

Please sign in to comment.