From c6860471a02cf4c6e7e59131e9934ea97745b371 Mon Sep 17 00:00:00 2001 From: Yun-Ting Lin Date: Wed, 15 Feb 2023 11:29:40 -0800 Subject: [PATCH] [Instrumentation.Process] Exposed required metric `process.cpu.count` for computing CPU utilization in the backend. (#981) --- .../CHANGELOG.md | 3 ++- .../ProcessMetrics.cs | 10 ++++++++++ .../README.md | 17 +++++++++++++++++ .../ProcessMetricsTests.cs | 18 ++++++++++++------ 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md b/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md index ef9871aa97..5a65615f4f 100644 --- a/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md +++ b/src/OpenTelemetry.Instrumentation.Process/CHANGELOG.md @@ -2,7 +2,8 @@ ## Unreleased -TBD +* Added `process.cpu.count` metric. + ([#981](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/981)) ## 1.0.0-alpha.6 diff --git a/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs b/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs index 5835ce228c..222eccaf8f 100644 --- a/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs +++ b/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs @@ -16,6 +16,7 @@ #nullable enable +using System; using System.Collections.Generic; using System.Diagnostics.Metrics; using System.Reflection; @@ -64,6 +65,15 @@ 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.threads", () => diff --git a/src/OpenTelemetry.Instrumentation.Process/README.md b/src/OpenTelemetry.Instrumentation.Process/README.md index 9481e7fb58..b4432e3670 100644 --- a/src/OpenTelemetry.Instrumentation.Process/README.md +++ b/src/OpenTelemetry.Instrumentation.Process/README.md @@ -92,6 +92,23 @@ 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][1] and not part of the +[Process Metrics Spec][2] at this time. + +[1]: https://github.com/open-telemetry/opentelemetry-specification/issues/3200 +[2]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/process-metrics.md + ### process.threads Process threads count. diff --git a/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs b/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs index e63b89f1fe..0ba48f3151 100644 --- a/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs +++ b/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs @@ -38,14 +38,16 @@ public void ProcessMetricsAreCaptured() meterProviderA.ForceFlush(MaxTimeToAllowForFlush); - Assert.True(exportedItemsA.Count == 4); + Assert.True(exportedItemsA.Count == 5); 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 threadMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.threads"); + var processorCountMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.cpu.count"); + Assert.NotNull(processorCountMetric); + var threadMetric = exportedItemsA.FirstOrDefault(i => i.Name == "process.cpu.count"); Assert.NotNull(threadMetric); exportedItemsA.Clear(); @@ -66,8 +68,8 @@ public void ProcessMetricsAreCaptured() meterProviderB.ForceFlush(MaxTimeToAllowForFlush); - Assert.True(exportedItemsA.Count == 4); - Assert.True(exportedItemsB.Count == 4); + Assert.True(exportedItemsA.Count == 5); + Assert.True(exportedItemsB.Count == 5); } [Fact] @@ -142,23 +144,27 @@ public void ProcessMetricsAreCapturedWhenTasksOverlap() Task.WaitAll(tasks.ToArray()); - Assert.True(exportedItemsA.Count == 4); + Assert.True(exportedItemsA.Count == 5); 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.threads"); Assert.NotNull(threadMetricA); - Assert.True(exportedItemsB.Count == 4); + Assert.True(exportedItemsB.Count == 5); 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.threads"); Assert.NotNull(threadMetricB); }