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 3 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#nullable enable
OpenTelemetry.Instrumentation.Runtime.RuntimeInstrumentationOptions
OpenTelemetry.Instrumentation.Runtime.RuntimeInstrumentationOptions.RuntimeInstrumentationOptions() -> void
OpenTelemetry.Metrics.MeterProviderBuilderExtensions
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddRuntimeInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder! builder, System.Action<OpenTelemetry.Instrumentation.Runtime.RuntimeInstrumentationOptions!>? configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddRuntimeInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder! builder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#nullable enable
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#nullable enable
OpenTelemetry.Metrics.MeterProviderBuilderExtensions
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddRuntimeInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder! builder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#nullable enable
OpenTelemetry.Instrumentation.Runtime.RuntimeInstrumentationOptions
OpenTelemetry.Instrumentation.Runtime.RuntimeInstrumentationOptions.RuntimeInstrumentationOptions() -> void
OpenTelemetry.Metrics.MeterProviderBuilderExtensions
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddRuntimeInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder! builder, System.Action<OpenTelemetry.Instrumentation.Runtime.RuntimeInstrumentationOptions!>? configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddRuntimeInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder! builder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
3 changes: 3 additions & 0 deletions src/OpenTelemetry.Instrumentation.Runtime/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,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
@@ -1,8 +1,10 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#if !NET9_0_OR_GREATER
using OpenTelemetry.Instrumentation.Runtime;
using OpenTelemetry.Internal;
#endif

namespace OpenTelemetry.Metrics;

Expand All @@ -11,15 +13,24 @@ namespace OpenTelemetry.Metrics;
/// </summary>
public static class MeterProviderBuilderExtensions
{
#if NET9_0_OR_GREATER
private const string DotNetRuntimeMeterName = "System.Runtime";
#endif

/// <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) =>
#if NET9_0_OR_GREATER
builder.AddMeter(DotNetRuntimeMeterName);
#else
Kielek marked this conversation as resolved.
Show resolved Hide resolved
AddRuntimeInstrumentation(builder, configure: null);
#endif

#if !NET9_0_OR_GREATER
/// <summary>
/// Enables runtime instrumentation.
/// </summary>
Expand All @@ -39,4 +50,5 @@ public static MeterProviderBuilder AddRuntimeInstrumentation(
builder.AddMeter(RuntimeMetrics.MeterInstance.Name);
return builder.AddInstrumentation(() => instrumentation);
}
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>$(NetMinimumSupportedVersion);$(NetStandardMinimumSupportedVersion);$(NetFrameworkMinimumSupportedVersion)</TargetFrameworks>
<TargetFrameworks>$(NetMinimumSupportedVersion);$(NetStandardMinimumSupportedVersion);$(NetFrameworkMinimumSupportedVersion);net9.0</TargetFrameworks>
<Description>.NET runtime instrumentation for OpenTelemetry .NET.</Description>
<PackageTags>$(PackageTags);runtime</PackageTags>
<MinVerTagPrefix>Instrumentation.Runtime-</MinVerTagPrefix>
Expand All @@ -13,9 +13,14 @@
<PackageReference Include="OpenTelemetry.Api" Version="$(OpenTelemetryCoreLatestVersion)" />
</ItemGroup>

<ItemGroup>
<Compile Include="$(RepoRoot)\src\Shared\AssemblyVersionExtensions.cs" Link="Includes\AssemblyVersionExtensions.cs" />
<ItemGroup Condition="'$(TargetFramework)' != 'net9.0'">
<Compile Include="$(RepoRoot)\src\Shared\Guard.cs" Link="Includes\Guard.cs" />
<Compile Include="$(RepoRoot)\src\Shared\AssemblyVersionExtensions.cs" Link="Includes\AssemblyVersionExtensions.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
<Compile Remove="RuntimeMetrics.cs" />
<Compile Remove="RuntimeInstrumentationOptions.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 @@ -93,6 +112,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 @@ -101,6 +130,7 @@ public void JitRelatedMetricsTest()

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

[Fact]
Expand All @@ -124,6 +154,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 @@ -166,6 +205,7 @@ static void TimerCallback(object? _)
timers[i].Dispose();
}
}
#endif
}
#endif

Expand Down