diff --git a/src/OpenTelemetry.Instrumentation.Process/MeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Instrumentation.Process/MeterProviderBuilderExtensions.cs
index 516945ebd1..223808b4a4 100644
--- a/src/OpenTelemetry.Instrumentation.Process/MeterProviderBuilderExtensions.cs
+++ b/src/OpenTelemetry.Instrumentation.Process/MeterProviderBuilderExtensions.cs
@@ -41,7 +41,7 @@ public static MeterProviderBuilder AddProcessInstrumentation(
configure?.Invoke(options);
var instrumentation = new ProcessMetrics(options);
- builder.AddMeter(ProcessMetrics.MeterInstance.Name);
+ builder.AddMeter(instrumentation.MeterInstance.Name);
return builder.AddInstrumentation(() => instrumentation);
}
}
diff --git a/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs b/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs
index 563ff11452..f4e1c74283 100644
--- a/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs
+++ b/src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs
@@ -20,42 +20,56 @@
namespace OpenTelemetry.Instrumentation.Process;
-internal class ProcessMetrics
+internal sealed class ProcessMetrics
{
internal static readonly AssemblyName AssemblyName = typeof(ProcessMetrics).Assembly.GetName();
- internal static readonly Meter MeterInstance = new(AssemblyName.Name, AssemblyName.Version.ToString());
- private static readonly Diagnostics.Process CurrentProcess = Diagnostics.Process.GetCurrentProcess();
+ internal readonly Meter MeterInstance = new(AssemblyName.Name, AssemblyName.Version.ToString());
- static ProcessMetrics()
+ private readonly Diagnostics.Process currentProcess = Diagnostics.Process.GetCurrentProcess();
+ private double? memoryUsage;
+ private double? virtualMemoryUsage;
+
+ public ProcessMetrics(ProcessInstrumentationOptions options)
{
// TODO: change to ObservableUpDownCounter
- MeterInstance.CreateObservableGauge(
+ this.MeterInstance.CreateObservableGauge(
"process.memory.usage",
() =>
{
- CurrentProcess.Refresh();
- return CurrentProcess.WorkingSet64;
+ if (!this.memoryUsage.HasValue)
+ {
+ this.Snapshot();
+ }
+
+ var value = this.memoryUsage.Value;
+ this.memoryUsage = null;
+ return value;
},
unit: "By",
- description: "The amount of physical memory in use.");
+ description: "The amount of physical memory allocated for this process.");
// TODO: change to ObservableUpDownCounter
- MeterInstance.CreateObservableGauge(
+ this.MeterInstance.CreateObservableGauge(
"process.memory.virtual",
() =>
{
- CurrentProcess.Refresh();
- return CurrentProcess.VirtualMemorySize64;
+ if (!this.virtualMemoryUsage.HasValue)
+ {
+ this.Snapshot();
+ }
+
+ var value = this.virtualMemoryUsage.Value;
+ this.virtualMemoryUsage = null;
+ return value;
},
unit: "By",
- description: "The amount of committed virtual memory.");
+ description: "The amount of virtual memory allocated for this process that cannot be shared with other processes.");
}
- ///
- /// Initializes a new instance of the class.
- ///
- /// The options to define the metrics.
- public ProcessMetrics(ProcessInstrumentationOptions options)
+ private void Snapshot()
{
+ this.currentProcess.Refresh();
+ this.memoryUsage = this.currentProcess.WorkingSet64;
+ this.virtualMemoryUsage = this.currentProcess.PrivateMemorySize64;
}
}
diff --git a/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs b/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs
index e227506a81..7adc9fa789 100644
--- a/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs
+++ b/test/OpenTelemetry.Instrumentation.Process.Tests/ProcessMetricsTests.cs
@@ -15,6 +15,7 @@
//
using System.Collections.Generic;
+using System.Diagnostics.Metrics;
using System.Linq;
using OpenTelemetry.Metrics;
using Xunit;
@@ -42,4 +43,50 @@ public void ProcessMetricsAreCaptured()
var virtualMemoryMetric = exportedItems.FirstOrDefault(i => i.Name == "process.memory.virtual");
Assert.NotNull(virtualMemoryMetric);
}
+
+ [Fact]
+ public void CheckValidGaugeValueWhen2MeterProviderInstancesHaveTheSameMeterName()
+ {
+ var exportedItemsA = new List();
+ var exportedItemsB = new List();
+
+ using var meterProviderA = Sdk.CreateMeterProviderBuilder()
+ .AddProcessInstrumentation()
+ .AddInMemoryExporter(exportedItemsA)
+ .Build();
+
+ using var meterProviderB = Sdk.CreateMeterProviderBuilder()
+ .AddProcessInstrumentation()
+ .AddInMemoryExporter(exportedItemsB)
+ .Build();
+
+ meterProviderA.ForceFlush(MaxTimeToAllowForFlush);
+ meterProviderB.ForceFlush(MaxTimeToAllowForFlush);
+
+ var metricA = exportedItemsA.FirstOrDefault(i => i.Name == "process.memory.usage");
+ var metricB = exportedItemsB.FirstOrDefault(i => i.Name == "process.memory.usage");
+
+ Assert.True(GetValue(metricA) > 0);
+ Assert.True(GetValue(metricB) > 0);
+ }
+
+ private static double GetValue(Metric metric)
+ {
+ Assert.NotNull(metric);
+ double sum = 0;
+
+ foreach (ref readonly var metricPoint in metric.GetMetricPoints())
+ {
+ if (metric.MetricType.IsGauge())
+ {
+ sum += metricPoint.GetGaugeLastValueDouble();
+ }
+ else if (metric.MetricType.IsDouble())
+ {
+ sum += metricPoint.GetSumDouble();
+ }
+ }
+
+ return sum;
+ }
}