Skip to content

Commit

Permalink
Fix some bugs in Runtime metrics (open-telemetry#409)
Browse files Browse the repository at this point in the history
* Update instrument types, value types and units and some renames
  • Loading branch information
xiang17 authored and swetharavichandrancisco committed Jun 16, 2022
1 parent 4e180bd commit ffdecdc
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 34 deletions.
2 changes: 2 additions & 0 deletions src/OpenTelemetry.Instrumentation.Runtime/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

* Updated OTel SDK package version to 1.3.0
([#411](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/411))
* Fix some bugs in Runtime metrics
([#409](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/409))

## 0.1.0-alpha.1

Expand Down
31 changes: 17 additions & 14 deletions src/OpenTelemetry.Instrumentation.Runtime/RuntimeMetrics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ internal class RuntimeMetrics : IDisposable
internal static readonly AssemblyName AssemblyName = typeof(RuntimeMetrics).Assembly.GetName();
internal static readonly string InstrumentationName = AssemblyName.Name;
internal static readonly string InstrumentationVersion = AssemblyName.Version.ToString();
private const long NanosecondsPerTick = 100;
private static string metricPrefix = "process.runtime.dotnet.";
private readonly Meter meter;

Expand All @@ -46,17 +47,19 @@ public RuntimeMetrics(RuntimeMetricsOptions options)

if (options.IsGcEnabled)
{
// TODO: Almost all the ObservableGauge should be ObservableUpDownCounter (except for CPU utilization and fragmentation.ratio.
// Replace them once ObservableUpDownCounter is available.
this.meter.CreateObservableGauge($"{metricPrefix}gc.heap", () => GC.GetTotalMemory(false), "By", "GC Heap Size");
this.meter.CreateObservableGauge($"{metricPrefix}gen_0-gc.count", () => GC.CollectionCount(0), description: "Gen 0 GC Count");
this.meter.CreateObservableGauge($"{metricPrefix}gen_1-gc.count", () => GC.CollectionCount(1), description: "Gen 1 GC Count");
this.meter.CreateObservableGauge($"{metricPrefix}gen_2-gc.count", () => GC.CollectionCount(2), description: "Gen 2 GC Count");
#if NETCOREAPP3_1_OR_GREATER
this.meter.CreateObservableCounter($"{metricPrefix}alloc.rate", () => GC.GetTotalAllocatedBytes(), "By", "Allocation Rate");
this.meter.CreateObservableCounter($"{metricPrefix}gc.fragmentation", GetFragmentation, description: "GC Fragmentation");
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.CreateObservableCounter($"{metricPrefix}gc.committed", () => (double)(GC.GetGCMemoryInfo().TotalCommittedBytes / 1_000_000), "Mi", description: "GC Committed Bytes");
this.meter.CreateObservableGauge($"{metricPrefix}gc.committed", () => GC.GetGCMemoryInfo().TotalCommittedBytes, "By", description: "GC Committed Bytes");
#endif
}

Expand All @@ -65,34 +68,34 @@ 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().TotalMilliseconds, "ms", description: "Time spent in JIT");
this.meter.CreateObservableGauge($"{metricPrefix}time.in.jit", () => System.Runtime.JitInfo.GetCompilationTime().Ticks * NanosecondsPerTick, "ns", description: "Time spent in JIT");
}
#endif

#if NETCOREAPP3_1_OR_GREATER
if (options.IsThreadingEnabled)
{
this.meter.CreateObservableGauge($"{metricPrefix}monitor.lock.contention.count", () => Monitor.LockContentionCount, description: "Monitor Lock Contention Count");
this.meter.CreateObservableCounter($"{metricPrefix}threadpool.thread.count", () => ThreadPool.ThreadCount, description: "ThreadPool Thread Count");
this.meter.CreateObservableGauge($"{metricPrefix}threadpool.thread.count", () => (long)ThreadPool.ThreadCount, description: "ThreadPool Thread Count");
this.meter.CreateObservableGauge($"{metricPrefix}threadpool.completed.items.count", () => ThreadPool.CompletedWorkItemCount, description: "ThreadPool Completed Work Item Count");
this.meter.CreateObservableCounter($"{metricPrefix}threadpool.queue.length", () => ThreadPool.PendingWorkItemCount, description: "ThreadPool Queue Length");
this.meter.CreateObservableCounter($"{metricPrefix}active.timer.count", () => Timer.ActiveCount, description: "Number of Active Timers");
this.meter.CreateObservableGauge($"{metricPrefix}threadpool.queue.length", () => ThreadPool.PendingWorkItemCount, description: "ThreadPool Queue Length");
this.meter.CreateObservableGauge($"{metricPrefix}active.timer.count", () => Timer.ActiveCount, description: "Number of Active Timers");
}
#endif

if (options.IsProcessEnabled)
{
this.meter.CreateObservableCounter("process.cpu.time", this.GetProcessorTimes, "s", "Processor time of this process");
this.meter.CreateObservableCounter("process.cpu.time", this.GetProcessorTimes, "ns", "Processor time of this process");

// Not yet official: https://github.com/open-telemetry/opentelemetry-specification/pull/2392
this.meter.CreateObservableGauge("process.cpu.count", () => Environment.ProcessorCount, description: "The number of available logical CPUs");
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", () => AppDomain.CurrentDomain.GetAssemblies().Length, description: "Number of Assemblies Loaded");
this.meter.CreateObservableCounter($"{metricPrefix}assembly.count", () => (long)AppDomain.CurrentDomain.GetAssemblies().Length, description: "Number of Assemblies Loaded");
}
}

Expand All @@ -106,17 +109,17 @@ public void Dispose()
private static double GetFragmentation()
{
var gcInfo = GC.GetGCMemoryInfo();
return gcInfo.HeapSizeBytes != 0 ? gcInfo.FragmentedBytes * 100d / gcInfo.HeapSizeBytes : 0;
return gcInfo.HeapSizeBytes != 0 ? gcInfo.FragmentedBytes * 1.0d / gcInfo.HeapSizeBytes : 0;
}
#endif

private IEnumerable<Measurement<double>> GetProcessorTimes()
private IEnumerable<Measurement<long>> GetProcessorTimes()
{
var process = Process.GetCurrentProcess();
return new[]
{
new Measurement<double>(process.UserProcessorTime.TotalSeconds, new KeyValuePair<string, object>("state", "user")),
new Measurement<double>(process.PrivilegedProcessorTime.TotalSeconds, new KeyValuePair<string, object>("state", "system")),
new Measurement<long>(process.UserProcessorTime.Ticks * NanosecondsPerTick, new KeyValuePair<string, object>("state", "user")),
new Measurement<long>(process.PrivilegedProcessorTime.Ticks * NanosecondsPerTick, new KeyValuePair<string, object>("state", "system")),
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public void ProcessMetricsAreCaptured()
Assert.Equal(4, exportedItems.Count);

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

var cpuCountMetric = exportedItems.First(i => i.Name == "process.cpu.count");
Expand All @@ -91,25 +91,6 @@ public void ProcessMetricsAreCaptured()
Assert.True(GetLongSum(virtualMemoryMetric) > 0);
}

private static double GetDoubleSum(Metric metric)
{
double sum = 0;

foreach (ref readonly var metricPoint in metric.GetMetricPoints())
{
if (metric.MetricType.IsSum())
{
sum += metricPoint.GetSumDouble();
}
else
{
sum += metricPoint.GetGaugeLastValueDouble();
}
}

return sum;
}

private static double GetLongSum(Metric metric)
{
double sum = 0;
Expand Down

0 comments on commit ffdecdc

Please sign in to comment.