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

Update a few metrics to be in sync of doc updates for gc.heap, gc.fragmentation.ratio, time.in.jit, process.cpu.count and assembly.count #430

Merged
merged 5 commits into from
Jun 22, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions src/OpenTelemetry.Instrumentation.Runtime/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

* Update a few metrics to be in sync of doc updates for `gc.heap`,
`gc.fragmentation.ratio`, `time.in.jit`, `process.cpu.count` and `assembly.count`
([#430](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/430))

## 0.2.0-alpha.1

* Updated OTel SDK package version to 1.3.0
Expand Down
29 changes: 15 additions & 14 deletions src/OpenTelemetry.Instrumentation.Runtime/RuntimeMetrics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,16 @@ public RuntimeMetrics(RuntimeMetricsOptions options)

if (options.IsGcEnabled)
{
// TODO: Almost all the ObservableGauge should be ObservableUpDownCounter (except for CPU utilization and fragmentation.ratio.
// TODO: Almost all the ObservableGauge should be ObservableUpDownCounter (except for CPU utilization).
// Replace them once ObservableUpDownCounter is available.
this.meter.CreateObservableGauge($"{metricPrefix}gc.heap", () => GC.GetTotalMemory(false), "By", "GC Heap Size.");
this.meter.CreateObservableGauge($"{metricPrefix}gc.count", () => GetGarbageCollectionCounts(), description: "GC Count for all generations.");

#if NETCOREAPP3_1_OR_GREATER
this.meter.CreateObservableCounter($"{metricPrefix}gc.allocated.bytes", () => GC.GetTotalAllocatedBytes(), "By", "Allocation Rate.");
this.meter.CreateObservableGauge($"{metricPrefix}gc.fragmentation.ratio", GetFragmentation, description: "GC Fragmentation.");
#endif

#if NET6_0_OR_GREATER
this.meter.CreateObservableGauge($"{metricPrefix}gc.fragmentation.size", GetFragmentationSizes, description: "GC fragmentation.");
this.meter.CreateObservableGauge($"{metricPrefix}gc.committed", () => GC.GetGCMemoryInfo().TotalCommittedBytes, "By", description: "GC Committed Bytes.");
this.meter.CreateObservableGauge($"{metricPrefix}gc.heapsize", () => GetGarbageCollectionHeapSizes(), "By", "Heap size for all generations.");
#endif
Expand All @@ -70,7 +69,7 @@ public RuntimeMetrics(RuntimeMetricsOptions options)
{
this.meter.CreateObservableCounter($"{metricPrefix}il.bytes.jitted", () => System.Runtime.JitInfo.GetCompiledILBytes(), "By", description: "IL Bytes Jitted.");
this.meter.CreateObservableCounter($"{metricPrefix}methods.jitted.count", () => System.Runtime.JitInfo.GetCompiledMethodCount(), description: "Number of Methods Jitted.");
this.meter.CreateObservableGauge($"{metricPrefix}time.in.jit", () => System.Runtime.JitInfo.GetCompilationTime().Ticks * NanosecondsPerTick, "ns", description: "Time spent in JIT.");
this.meter.CreateObservableCounter($"{metricPrefix}time.in.jit", () => System.Runtime.JitInfo.GetCompilationTime().Ticks * NanosecondsPerTick, "ns", description: "Time spent in JIT.");
}
#endif

Expand All @@ -88,16 +87,13 @@ public RuntimeMetrics(RuntimeMetricsOptions options)
if (options.IsProcessEnabled)
{
this.meter.CreateObservableCounter("process.cpu.time", GetProcessorTimes, "s", "Processor time of this process.");

// Not yet official: https://github.com/open-telemetry/opentelemetry-specification/pull/2392
this.meter.CreateObservableGauge("process.cpu.count", () => (long)Environment.ProcessorCount, description: "The number of available logical CPUs.");
this.meter.CreateObservableGauge("process.memory.usage", () => Process.GetCurrentProcess().WorkingSet64, "By", "The amount of physical memory in use.");
this.meter.CreateObservableGauge("process.memory.virtual", () => Process.GetCurrentProcess().VirtualMemorySize64, "By", "The amount of committed virtual memory.");
}

if (options.IsAssembliesEnabled)
{
this.meter.CreateObservableCounter($"{metricPrefix}assembly.count", () => (long)AppDomain.CurrentDomain.GetAssemblies().Length, description: "Number of Assemblies Loaded.");
this.meter.CreateObservableGauge($"{metricPrefix}assembly.count", () => (long)AppDomain.CurrentDomain.GetAssemblies().Length, description: "Number of Assemblies Loaded.");
}
}

Expand All @@ -115,15 +111,20 @@ private static IEnumerable<Measurement<long>> GetGarbageCollectionCounts()
}
}

#if NETCOREAPP3_1_OR_GREATER
private static double GetFragmentation()
#if NET6_0_OR_GREATER
private static IEnumerable<Measurement<long>> GetFragmentationSizes()
{
var gcInfo = GC.GetGCMemoryInfo();
return gcInfo.HeapSizeBytes != 0 ? gcInfo.FragmentedBytes * 1.0d / gcInfo.HeapSizeBytes : 0;
var generationInfo = GC.GetGCMemoryInfo().GenerationInfo;
Measurement<long>[] measurements = new Measurement<long>[generationInfo.Length];
int maxSupportedLength = Math.Min(generationInfo.Length, GenNames.Length);
for (int i = 0; i < maxSupportedLength; ++i)
{
measurements[i] = new(generationInfo[i].FragmentationAfterBytes, new KeyValuePair<string, object>("gen", GenNames[i]));
}

return measurements;
}
#endif

#if NET6_0_OR_GREATER
private static IEnumerable<Measurement<long>> GetGarbageCollectionHeapSizes()
{
var generationInfo = GC.GetGCMemoryInfo().GenerationInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,12 @@ public void ProcessMetricsAreCaptured()

meterProvider.ForceFlush(MaxTimeToAllowForFlush);

Assert.Equal(4, exportedItems.Count);
Assert.Equal(3, exportedItems.Count);

var cpuTimeMetric = exportedItems.First(i => i.Name == "process.cpu.time");
var sumReceived = GetDoubleSum(cpuTimeMetric);
Assert.True(sumReceived > 0);

var cpuCountMetric = exportedItems.First(i => i.Name == "process.cpu.count");
Assert.Equal(Environment.ProcessorCount, (int)GetLongSum(cpuCountMetric));

var memoryMetric = exportedItems.First(i => i.Name == "process.memory.usage");
Assert.True(GetLongSum(memoryMetric) > 0);

Expand Down