From f011c1fd4f0868ee46051098dc680c8cbc172875 Mon Sep 17 00:00:00 2001 From: martincostello Date: Thu, 9 Apr 2026 17:35:07 +0100 Subject: [PATCH 1/6] [Instrumentation.Process] Add schema URL Add schema URL to metrics. Contributes to #4064. --- .../CHANGELOG.md | 3 + .../MeterProviderBuilderExtensions.cs | 2 +- ...enTelemetry.Instrumentation.Process.csproj | 1 + .../ProcessMetrics.cs | 11 +- .../ProcessMetricsTests.cs | 111 ++++++++++-------- 5 files changed, 68 insertions(+), 60 deletions(-) diff --git a/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md index c6bf3663b5..b48a9e77f8 100644 --- a/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md @@ -5,6 +5,9 @@ * Updated OpenTelemetry core component version(s) to `1.15.2`. ([#4080](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4080)) +* Add instrumentation scope version and schema URL to metrics. + ([#TODO](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/TODO)) + ## 1.15.0-beta.1 Released 2026-Jan-21 diff --git a/src/OpenTelemetry.Instrumentation.Process/MeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Instrumentation.Process/MeterProviderBuilderExtensions.cs index de2f9e97df..71160e78c3 100644 --- a/src/OpenTelemetry.Instrumentation.Process/MeterProviderBuilderExtensions.cs +++ b/src/OpenTelemetry.Instrumentation.Process/MeterProviderBuilderExtensions.cs @@ -21,7 +21,7 @@ public static MeterProviderBuilder AddProcessInstrumentation( { Guard.ThrowIfNull(builder); - builder.AddMeter(ProcessMetrics.MeterName); + builder.AddMeter(ProcessMetrics.MeterInstance.Name); return builder.AddInstrumentation(() => new ProcessMetrics()); } } diff --git a/src/OpenTelemetry.Instrumentation.Process/OpenTelemetry.Instrumentation.Process.csproj b/src/OpenTelemetry.Instrumentation.Process/OpenTelemetry.Instrumentation.Process.csproj index 49f9e9cb35..fd75263cbc 100644 --- a/src/OpenTelemetry.Instrumentation.Process/OpenTelemetry.Instrumentation.Process.csproj +++ b/src/OpenTelemetry.Instrumentation.Process/OpenTelemetry.Instrumentation.Process.csproj @@ -25,6 +25,7 @@ + diff --git a/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs b/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs index 05142e8bc1..62a5184c4a 100644 --- a/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs +++ b/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs @@ -2,21 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 using System.Diagnostics.Metrics; -using System.Reflection; -using OpenTelemetry.Internal; using Diagnostics = System.Diagnostics; namespace OpenTelemetry.Instrumentation.Process; internal sealed class ProcessMetrics { - internal static readonly Assembly Assembly = typeof(ProcessMetrics).Assembly; - internal static readonly AssemblyName AssemblyName = Assembly.GetName(); -#pragma warning disable IDE0370 // Suppression is unnecessary - internal static readonly string MeterName = AssemblyName.Name!; -#pragma warning restore IDE0370 // Suppression is unnecessary - - private static readonly Meter MeterInstance = new(MeterName, Assembly.GetPackageVersion()); + internal static readonly Version SemanticConventionsVersion = new(1, 25, 0); + internal static readonly Meter MeterInstance = Trace.MeterFactory.Create(SemanticConventionsVersion); static ProcessMetrics() { diff --git a/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs b/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs index f10a36d8b7..a21eb64a84 100644 --- a/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs +++ b/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs @@ -13,58 +13,69 @@ public class ProcessMetricsTests [Fact] public void ProcessMetricsAreCaptured() { - var exportedItemsA = new List(); - var meterProviderA = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(exportedItemsA) - .Build(); + var firstMetrics = new List(); - meterProviderA.ForceFlush(MaxTimeToAllowForFlush); + using (var first = Sdk.CreateMeterProviderBuilder() + .AddProcessInstrumentation() + .AddInMemoryExporter(firstMetrics) + .Build()) + { + first.ForceFlush(MaxTimeToAllowForFlush); + } - Assert.Equal(5, exportedItemsA.Count); - var physicalMemoryMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.memory.usage"); + Assert.Equal(5, firstMetrics.Count); + var physicalMemoryMetric = firstMetrics.FirstOrDefault(i => i.Name == "process.memory.usage"); Assert.NotNull(physicalMemoryMetric); - var virtualMemoryMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.memory.virtual"); + var virtualMemoryMetric = firstMetrics.FirstOrDefault(i => i.Name == "process.memory.virtual"); Assert.NotNull(virtualMemoryMetric); - var cpuTimeMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.cpu.time"); + var cpuTimeMetric = firstMetrics.FirstOrDefault(i => i.Name == "process.cpu.time"); Assert.NotNull(cpuTimeMetric); - var processorCountMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.cpu.count"); + var processorCountMetric = firstMetrics.FirstOrDefault(i => i.Name == "process.cpu.count"); Assert.NotNull(processorCountMetric); - var threadMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.thread.count"); + var threadMetric = firstMetrics.FirstOrDefault(i => i.Name == "process.thread.count"); Assert.NotNull(threadMetric); - exportedItemsA.Clear(); - - var exportedItemsB = new List(); - - using var meterProviderB = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(exportedItemsA, metricReaderOptions => - { - metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = 1500; - }) - .AddInMemoryExporter(exportedItemsB, metricReaderOptions => - { - metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = 5000; - }) - .Build(); + firstMetrics.Clear(); + + var secondMetrics = new List(); + + using (var second = Sdk.CreateMeterProviderBuilder() + .AddProcessInstrumentation() + .AddInMemoryExporter(firstMetrics, metricReaderOptions => + { + metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = 1500; + }) + .AddInMemoryExporter(secondMetrics, metricReaderOptions => + { + metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = 5000; + }) + .Build()) + { + second.ForceFlush(MaxTimeToAllowForFlush); + } - meterProviderB.ForceFlush(MaxTimeToAllowForFlush); + Assert.Equal(5, firstMetrics.Count); + Assert.Equal(5, secondMetrics.Count); - Assert.Equal(5, exportedItemsA.Count); - Assert.Equal(5, exportedItemsB.Count); + foreach (var metric in firstMetrics) + { + Assert.NotNull(metric.MeterVersion); + Assert.NotEmpty(metric.MeterVersion); + Assert.StartsWith("https://opentelemetry.io/schemas/", metric.MeterSchemaUrl); + } } [Fact] public void CpuTimeMetricsAreCaptured() { var exportedItems = new List(); - using var meterProvider = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(exportedItems) - .Build(); - - meterProvider.ForceFlush(MaxTimeToAllowForFlush); + using (var meterProvider = Sdk.CreateMeterProviderBuilder() + .AddProcessInstrumentation() + .AddInMemoryExporter(exportedItems) + .Build()) + { + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + } var cpuTimeMetric = exportedItems.FirstOrDefault(i => i.Name == "process.cpu.time"); Assert.NotNull(cpuTimeMetric); @@ -104,10 +115,10 @@ public async Task ProcessMetricsAreCapturedWhenTasksOverlap() { Task.Run(() => { - var meterProviderA = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(exportedItemsA) - .Build(); + using var meterProviderA = Sdk.CreateMeterProviderBuilder() + .AddProcessInstrumentation() + .AddInMemoryExporter(exportedItemsA) + .Build(); Thread.Sleep(3000); // increase the odds of 2 tasks overlaps @@ -116,10 +127,10 @@ public async Task ProcessMetricsAreCapturedWhenTasksOverlap() Task.Run(() => { - var meterProviderB = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(exportedItemsB) - .Build(); + using var meterProviderB = Sdk.CreateMeterProviderBuilder() + .AddProcessInstrumentation() + .AddInMemoryExporter(exportedItemsB) + .Build(); Thread.Sleep(3000); // increase the odds of 2 tasks overlaps @@ -161,14 +172,14 @@ public void CheckValidGaugeValueWhen2MeterProviderInstancesHaveTheSameMeterName( var exportedItemsB = new List(); using var meterProviderA = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(exportedItemsA) - .Build(); + .AddProcessInstrumentation() + .AddInMemoryExporter(exportedItemsA) + .Build(); using (var meterProviderB = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(exportedItemsB) - .Build()) + .AddProcessInstrumentation() + .AddInMemoryExporter(exportedItemsB) + .Build()) { meterProviderA.ForceFlush(MaxTimeToAllowForFlush); meterProviderB.ForceFlush(MaxTimeToAllowForFlush); From 6d48c94360b0e467af6f49f422dbd80f7e85d11d Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Thu, 9 Apr 2026 17:36:21 +0100 Subject: [PATCH 2/6] [Instrumentation.Process] Update CHANGELOG Add PR number. --- src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md index b48a9e77f8..886ac43d13 100644 --- a/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md @@ -6,7 +6,7 @@ ([#4080](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4080)) * Add instrumentation scope version and schema URL to metrics. - ([#TODO](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/TODO)) + ([#4088](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4088)) ## 1.15.0-beta.1 From efb183a452d6af07049e6f827ecef6ecf005b90c Mon Sep 17 00:00:00 2001 From: martincostello Date: Thu, 9 Apr 2026 17:57:50 +0100 Subject: [PATCH 3/6] [Instrumentation.Process] Fix tests Revert refactoring. --- .../ProcessMetricsTests.cs | 127 +++++++++--------- 1 file changed, 66 insertions(+), 61 deletions(-) diff --git a/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs b/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs index a21eb64a84..0c69690c65 100644 --- a/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs +++ b/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs @@ -13,69 +13,61 @@ public class ProcessMetricsTests [Fact] public void ProcessMetricsAreCaptured() { - var firstMetrics = new List(); + var exportedItemsA = new List(); + var meterProviderA = Sdk.CreateMeterProviderBuilder() + .AddProcessInstrumentation() + .AddInMemoryExporter(exportedItemsA) + .Build(); - using (var first = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(firstMetrics) - .Build()) - { - first.ForceFlush(MaxTimeToAllowForFlush); - } + meterProviderA.ForceFlush(MaxTimeToAllowForFlush); - Assert.Equal(5, firstMetrics.Count); - var physicalMemoryMetric = firstMetrics.FirstOrDefault(i => i.Name == "process.memory.usage"); + Assert.Equal(5, exportedItemsA.Count); + var physicalMemoryMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.memory.usage"); Assert.NotNull(physicalMemoryMetric); - var virtualMemoryMetric = firstMetrics.FirstOrDefault(i => i.Name == "process.memory.virtual"); + var virtualMemoryMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.memory.virtual"); Assert.NotNull(virtualMemoryMetric); - var cpuTimeMetric = firstMetrics.FirstOrDefault(i => i.Name == "process.cpu.time"); + var cpuTimeMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.cpu.time"); Assert.NotNull(cpuTimeMetric); - var processorCountMetric = firstMetrics.FirstOrDefault(i => i.Name == "process.cpu.count"); + var processorCountMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.cpu.count"); Assert.NotNull(processorCountMetric); - var threadMetric = firstMetrics.FirstOrDefault(i => i.Name == "process.thread.count"); + var threadMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.thread.count"); Assert.NotNull(threadMetric); - firstMetrics.Clear(); - - var secondMetrics = new List(); - - using (var second = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(firstMetrics, metricReaderOptions => - { - metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = 1500; - }) - .AddInMemoryExporter(secondMetrics, metricReaderOptions => - { - metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = 5000; - }) - .Build()) - { - second.ForceFlush(MaxTimeToAllowForFlush); - } + exportedItemsA.Clear(); - Assert.Equal(5, firstMetrics.Count); - Assert.Equal(5, secondMetrics.Count); + var exportedItemsB = new List(); - foreach (var metric in firstMetrics) - { - Assert.NotNull(metric.MeterVersion); - Assert.NotEmpty(metric.MeterVersion); - Assert.StartsWith("https://opentelemetry.io/schemas/", metric.MeterSchemaUrl); - } + using var meterProviderB = Sdk.CreateMeterProviderBuilder() + .AddProcessInstrumentation() + .AddInMemoryExporter(exportedItemsA, metricReaderOptions => + { + metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = 1500; + }) + .AddInMemoryExporter(exportedItemsB, metricReaderOptions => + { + metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = 5000; + }) + .Build(); + + meterProviderB.ForceFlush(MaxTimeToAllowForFlush); + + Assert.Equal(5, exportedItemsA.Count); + Assert.Equal(5, exportedItemsB.Count); + + AssertMetrics(exportedItemsA); + AssertMetrics(exportedItemsB); } [Fact] public void CpuTimeMetricsAreCaptured() { var exportedItems = new List(); - using (var meterProvider = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(exportedItems) - .Build()) - { - meterProvider.ForceFlush(MaxTimeToAllowForFlush); - } + using var meterProvider = Sdk.CreateMeterProviderBuilder() + .AddProcessInstrumentation() + .AddInMemoryExporter(exportedItems) + .Build(); + + meterProvider.ForceFlush(MaxTimeToAllowForFlush); var cpuTimeMetric = exportedItems.FirstOrDefault(i => i.Name == "process.cpu.time"); Assert.NotNull(cpuTimeMetric); @@ -115,10 +107,10 @@ public async Task ProcessMetricsAreCapturedWhenTasksOverlap() { Task.Run(() => { - using var meterProviderA = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(exportedItemsA) - .Build(); + var meterProviderA = Sdk.CreateMeterProviderBuilder() + .AddProcessInstrumentation() + .AddInMemoryExporter(exportedItemsA) + .Build(); Thread.Sleep(3000); // increase the odds of 2 tasks overlaps @@ -127,10 +119,10 @@ public async Task ProcessMetricsAreCapturedWhenTasksOverlap() Task.Run(() => { - using var meterProviderB = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(exportedItemsB) - .Build(); + var meterProviderB = Sdk.CreateMeterProviderBuilder() + .AddProcessInstrumentation() + .AddInMemoryExporter(exportedItemsB) + .Build(); Thread.Sleep(3000); // increase the odds of 2 tasks overlaps @@ -163,6 +155,9 @@ public async Task ProcessMetricsAreCapturedWhenTasksOverlap() Assert.NotNull(processorCountMetricB); var threadMetricB = exportedItemsB.FirstOrDefault(i => i.Name == "process.thread.count"); Assert.NotNull(threadMetricB); + + AssertMetrics(exportedItemsA); + AssertMetrics(exportedItemsB); } [Fact] @@ -172,14 +167,14 @@ public void CheckValidGaugeValueWhen2MeterProviderInstancesHaveTheSameMeterName( var exportedItemsB = new List(); using var meterProviderA = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(exportedItemsA) - .Build(); + .AddProcessInstrumentation() + .AddInMemoryExporter(exportedItemsA) + .Build(); using (var meterProviderB = Sdk.CreateMeterProviderBuilder() - .AddProcessInstrumentation() - .AddInMemoryExporter(exportedItemsB) - .Build()) + .AddProcessInstrumentation() + .AddInMemoryExporter(exportedItemsB) + .Build()) { meterProviderA.ForceFlush(MaxTimeToAllowForFlush); meterProviderB.ForceFlush(MaxTimeToAllowForFlush); @@ -232,4 +227,14 @@ private static double GetValue(Metric metric) return sum; } + + private static void AssertMetrics(IEnumerable metrics) + { + foreach (var metric in metrics) + { + Assert.NotNull(metric.MeterVersion); + Assert.NotEmpty(metric.MeterVersion); + Assert.StartsWith("https://opentelemetry.io/schemas/", metric.MeterSchemaUrl); + } + } } From 98947b2d214f9ad40ccd27e764992b9f957f7022 Mon Sep 17 00:00:00 2001 From: martincostello Date: Tue, 14 Apr 2026 16:43:41 +0100 Subject: [PATCH 4/6] [Instrumentation.Process] Fix namespace The type was moved in main. --- src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs b/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs index 62a5184c4a..c306dfdd47 100644 --- a/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs +++ b/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs @@ -9,7 +9,7 @@ namespace OpenTelemetry.Instrumentation.Process; internal sealed class ProcessMetrics { internal static readonly Version SemanticConventionsVersion = new(1, 25, 0); - internal static readonly Meter MeterInstance = Trace.MeterFactory.Create(SemanticConventionsVersion); + internal static readonly Meter MeterInstance = Metrics.MeterFactory.Create(SemanticConventionsVersion); static ProcessMetrics() { From 89cc97afd705346519f6e79d0ee83c0efc242eb4 Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Tue, 21 Apr 2026 18:12:18 +0100 Subject: [PATCH 5/6] [Process] Update CHANGELOG Move to unreleased. --- src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md index feff7ea244..5010357800 100644 --- a/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +* Add instrumentation scope version and schema URL to metrics. + ([#4088](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4088)) + ## 1.15.1-beta.1 Released 2026-Apr-21 @@ -9,9 +12,6 @@ Released 2026-Apr-21 * Updated OpenTelemetry core component version(s) to `1.15.3`. ([#4166](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4166)) -* Add instrumentation scope version and schema URL to metrics. - ([#4088](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4088)) - ## 1.15.0-beta.1 Released 2026-Jan-21 From b819f874c6087cf32827428ee36791dc4bd5c209 Mon Sep 17 00:00:00 2001 From: martincostello Date: Wed, 29 Apr 2026 09:16:32 +0100 Subject: [PATCH 6/6] [Instrumentation.Process] Remove process.cpu.count Remove the `process.cpu.count` metric which is not part of the Semantic Conventions. --- .../CHANGELOG.md | 6 ++++++ .../ProcessMetrics.cs | 9 --------- .../README.md | 18 ------------------ .../ProcessMetricsTests.cs | 16 +++++----------- 4 files changed, 11 insertions(+), 38 deletions(-) diff --git a/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md index 5010357800..99335df9fb 100644 --- a/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md @@ -5,6 +5,12 @@ * Add instrumentation scope version and schema URL to metrics. ([#4088](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4088)) +* Removed the `process.cpu.count` metric as it is not part of + the semantic conventions. Use the + [`dotnet.process.cpu.count`](https://github.com/open-telemetry/semantic-conventions/blob/v1.41.0/docs/runtime/dotnet-metrics.md#metric-dotnetprocesscpucount) + metric as an alternative. + ([#4088](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4088)) + ## 1.15.1-beta.1 Released 2026-Apr-21 diff --git a/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs b/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs index c306dfdd47..7f0d993495 100644 --- a/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs +++ b/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs @@ -47,15 +47,6 @@ static ProcessMetrics() unit: "s", description: "Total CPU seconds broken down by different states."); - MeterInstance.CreateObservableUpDownCounter( - "process.cpu.count", - () => - { - return Environment.ProcessorCount; - }, - unit: "{processors}", - description: "The number of processors (CPU cores) available to the current process."); - MeterInstance.CreateObservableUpDownCounter( "process.thread.count", () => diff --git a/src/OpenTelemetry.Instrumentation.Process/README.md b/src/OpenTelemetry.Instrumentation.Process/README.md index 69b95a2cf0..6e17593a7c 100644 --- a/src/OpenTelemetry.Instrumentation.Process/README.md +++ b/src/OpenTelemetry.Instrumentation.Process/README.md @@ -118,24 +118,6 @@ Gets the user processor time for this process. * [Process.PrivilegedProcessorTime](https://learn.microsoft.com/dotnet/api/system.diagnostics.process.privilegedprocessortime): Gets the privileged processor time for this process. -### process.cpu.count - -The number of processors (CPU cores) available to the current process. - -| Units | Instrument Type | Value Type | -| ------------- | ----------------------- | ---------- | -| `{processors}`| ObservableUpDownCounter | `Int32` | - -The API used to retrieve the value is -[System.Environment.ProcessorCount](https://learn.microsoft.com/dotnet/api/system.environment.processorcount). - -> [!NOTE] -> This metric is under -> [discussion](https://github.com/open-telemetry/opentelemetry-specification/issues/3200) -and not part of the [Process Metrics -Spec](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/system/process-metrics.md) -at this time. - ### process.thread.count Process threads count. diff --git a/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs b/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs index 0c69690c65..2c778e9a04 100644 --- a/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs +++ b/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs @@ -21,17 +21,15 @@ public void ProcessMetricsAreCaptured() meterProviderA.ForceFlush(MaxTimeToAllowForFlush); - Assert.Equal(5, exportedItemsA.Count); var physicalMemoryMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.memory.usage"); Assert.NotNull(physicalMemoryMetric); var virtualMemoryMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.memory.virtual"); Assert.NotNull(virtualMemoryMetric); var cpuTimeMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.cpu.time"); Assert.NotNull(cpuTimeMetric); - var processorCountMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.cpu.count"); - Assert.NotNull(processorCountMetric); var threadMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.thread.count"); Assert.NotNull(threadMetric); + Assert.Equal(4, exportedItemsA.Count); exportedItemsA.Clear(); @@ -51,8 +49,8 @@ public void ProcessMetricsAreCaptured() meterProviderB.ForceFlush(MaxTimeToAllowForFlush); - Assert.Equal(5, exportedItemsA.Count); - Assert.Equal(5, exportedItemsB.Count); + Assert.Equal(4, exportedItemsA.Count); + Assert.Equal(4, exportedItemsB.Count); AssertMetrics(exportedItemsA); AssertMetrics(exportedItemsB); @@ -132,29 +130,25 @@ public async Task ProcessMetricsAreCapturedWhenTasksOverlap() await Task.WhenAll(tasks); - Assert.Equal(5, exportedItemsA.Count); var physicalMemoryMetricA = exportedItemsA.FirstOrDefault(i => i.Name == "process.memory.usage"); Assert.NotNull(physicalMemoryMetricA); var virtualMemoryMetricA = exportedItemsA.FirstOrDefault(i => i.Name == "process.memory.virtual"); Assert.NotNull(virtualMemoryMetricA); var cpuTimeMetricA = exportedItemsA.FirstOrDefault(i => i.Name == "process.cpu.time"); Assert.NotNull(cpuTimeMetricA); - var processorCountMetricA = exportedItemsA.FirstOrDefault(i => i.Name == "process.cpu.count"); - Assert.NotNull(processorCountMetricA); var threadMetricA = exportedItemsA.FirstOrDefault(i => i.Name == "process.thread.count"); Assert.NotNull(threadMetricA); + Assert.Equal(4, exportedItemsA.Count); - Assert.Equal(5, exportedItemsB.Count); var physicalMemoryMetricB = exportedItemsB.FirstOrDefault(i => i.Name == "process.memory.usage"); Assert.NotNull(physicalMemoryMetricB); var virtualMemoryMetricB = exportedItemsB.FirstOrDefault(i => i.Name == "process.memory.virtual"); Assert.NotNull(virtualMemoryMetricB); var cpuTimeMetricB = exportedItemsB.FirstOrDefault(i => i.Name == "process.cpu.time"); Assert.NotNull(cpuTimeMetricB); - var processorCountMetricB = exportedItemsB.FirstOrDefault(i => i.Name == "process.cpu.count"); - Assert.NotNull(processorCountMetricB); var threadMetricB = exportedItemsB.FirstOrDefault(i => i.Name == "process.thread.count"); Assert.NotNull(threadMetricB); + Assert.Equal(4, exportedItemsB.Count); AssertMetrics(exportedItemsA); AssertMetrics(exportedItemsB);