Skip to content

Commit

Permalink
[Instrumentation.Process] Implement threadSafe Refresh() (#664)
Browse files Browse the repository at this point in the history
  • Loading branch information
Yun-Ting authored Oct 10, 2022
1 parent 46bad33 commit b9e3d88
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
48 changes: 31 additions & 17 deletions src/OpenTelemetry.Instrumentation.Process/ProcessMetrics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.");
}

/// <summary>
/// Initializes a new instance of the <see cref="ProcessMetrics"/> class.
/// </summary>
/// <param name="options">The options to define the metrics.</param>
public ProcessMetrics(ProcessInstrumentationOptions options)
private void Snapshot()
{
this.currentProcess.Refresh();
this.memoryUsage = this.currentProcess.WorkingSet64;
this.virtualMemoryUsage = this.currentProcess.PrivateMemorySize64;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// </copyright>

using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.Linq;
using OpenTelemetry.Metrics;
using Xunit;
Expand Down Expand Up @@ -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<Metric>();
var exportedItemsB = new List<Metric>();

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;
}
}

0 comments on commit b9e3d88

Please sign in to comment.