This is an Instrumentation Library, which instruments .NET Runtime and collect telemetry about runtime behavior.
Add a reference to the
OpenTelemetry.Instrumentation.Runtime
package.
dotnet add package OpenTelemetry.Instrumentation.Runtime
Runtime instrumentation should be enabled at application startup using the
AddRuntimeInstrumentation
extension on MeterProviderBuilder
:
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddRuntimeInstrumentation()
.AddPrometheusHttpListener()
.Build();
Refer to Program.cs for a complete demo.
Additionally, the above example snippet sets up the OpenTelemetry Prometheus Exporter
HttpListener as well, which requires adding the package
OpenTelemetry.Exporter.Prometheus.HttpListener
to the application.
Number of garbage collections that have occurred since process start.
Note
.NET uses a generational GC which divides the heap into different generations numbered 0, 1, and 2. In each collection the GC decides which generation to search for reclaimable memory, then it searches that generation and all the lower ones. A GC collection that searches generations 0, 1, and 2 is called a "gen2" collection, searching generations 0 and 1 is a "gen1" collection and searching generation 0 only is a "gen0" collection. The gen0, gen1, and gen2 attribute values for this metric count respectively the number of gen0, gen1, and gen2 collections which have occurred since the process started.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
{collections} |
ObservableCounter | Int64 |
generation | gen0, gen1, gen2 |
The metric can be computed using the GC.CollectionCount API:
count_gen0_collections = GC.CollectionCount(0) - GC.CollectionCount(1)
count_gen1_collections = GC.CollectionCount(1) - GC.CollectionCount(2)
count_gen2_collections = GC.CollectionCount(2)
GC.CollectionCount(X) counts the number of times objects in generation X have
been searched during any GC collection. Although it may sound similar, notice
this is not the same as the number of genX collections. For example objects in
generation 0 are searched during gen0, gen1, and gen2 collections so
GC.CollectionCount(0) = count_gen0_collections + count_gen1_collections + count_gen2_collections
.
This is why the expressions above are not direct assignments.
Count of bytes currently in use by objects in the GC heap that haven't been collected yet. Fragmentation and other GC committed memory pools are excluded. The value is available even before first garbage collection has occurred.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
bytes |
ObservableUpDownCounter | Int64 |
No Attributes | N/A |
The API used to retrieve the value is:
- GC.GetTotalMemory:
Retrieves the number of bytes currently thought to be allocated.
The value is an approximate count. API is called with
false
as a value of forceFullCollection parameter. Returns an instantaneous value at the time of observation.
Count of bytes allocated on the managed GC heap since the process start. .NET objects are allocated from this heap. Object allocations from unmanaged languages such as C/C++ do not use this heap.
Note
This metric is only available when targeting .NET 6 or later.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
bytes |
ObservableCounter | Int64 |
No Attributes | N/A |
The API used to retrieve the value is:
- GC.GetTotalAllocatedBytes: Gets a count of the bytes allocated over the lifetime of the process. The returned value does not include any native allocations. The value is an approximate count.
The amount of committed virtual memory for the managed GC heap, as observed during the latest garbage collection. Committed virtual memory may be larger than the heap size because it includes both memory for storing existing objects (the heap size) and some extra memory that is ready to handle newly allocated objects in the future. The value will be unavailable until at least one garbage collection has occurred.
Note
This metric is only available when targeting .NET 6 or later.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
bytes |
ObservableUpDownCounter | Int64 |
No Attributes | N/A |
The API used to retrieve the value is:
- GCMemoryInfo.TotalCommittedBytes: Gets the total committed bytes of the managed heap.
The heap size (including fragmentation), as observed during the latest garbage collection. The value will be unavailable until at least one garbage collection has occurred.
Note
This metric is only available when targeting .NET 6 or later.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
bytes |
ObservableUpDownCounter | Int64 |
generation | gen0, gen1, gen2, loh, poh |
The API used to retrieve the value is:
- GC.GetGCMemoryInfo().GenerationInfo[i].SizeAfterBytes:
Represents the size in bytes of a generation on exit of the GC reported in GCMemoryInfo.
Note that this API on .NET 6 has a bug.
For .NET 6, heap size is retrieved with an internal method
GC.GetGenerationSize
, which is how the well-known EventCounters retrieve the values. See source code here.
The heap fragmentation, as observed during the latest garbage collection. The value will be unavailable until at least one garbage collection has occurred.
Note
This metric is only available when targeting .NET 7 or later.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
bytes |
ObservableUpDownCounter | Int64 |
generation | gen0, gen1, gen2, loh, poh |
The API used to retrieve the value is:
- GCGenerationInfo.FragmentationAfterBytes Property Gets the fragmentation in bytes on exit from the reported collection.
The total amount of time paused in GC since the process start.
Note
This metric is only available when targeting .NET 7 or later.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
ns |
ObservableCounter | Int64 |
No Attributes | N/A |
The API used to retrieve the value is:
- GC.GetTotalPauseDuration Gets the total amount of time paused in GC since the beginning of the process.
These metrics are only available when targeting .NET6 or later.
Count of bytes of intermediate language that have been compiled since the process start.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
bytes |
ObservableCounter | Int64 |
No Attributes | N/A |
The number of times the JIT compiler compiled a method since the process start. The JIT compiler may be invoked multiple times for the same method to compile with different generic parameters, or because tiered compilation requested different optimization settings.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
{methods} |
ObservableCounter | Int64 |
No Attributes | N/A |
The amount of time the JIT compiler has spent compiling methods since the process start.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
ns |
ObservableCounter | Int64 |
No Attributes | N/A |
The APIs used to retrieve the values are:
-
JitInfo.GetCompiledILBytes: Gets the number of bytes of intermediate language that have been compiled. The scope of this value is global. The same applies for other JIT related metrics.
-
JitInfo.GetCompiledMethodCount: Gets the number of methods that have been compiled.
-
JitInfo.GetCompilationTime: Gets the amount of time the JIT Compiler has spent compiling methods.
These metrics are only available when targeting .NET 6 or later.
The number of times there was contention when trying to acquire a monitor lock since the process start. Monitor locks are commonly acquired by using the lock keyword in C#, or by calling Monitor.Enter() and Monitor.TryEnter().
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
{contended_acquisitions} |
ObservableCounter | Int64 |
No Attributes | N/A |
The number of thread pool threads that currently exist.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
{threads} |
ObservableUpDownCounter | Int32 |
No Attributes | N/A |
The number of work items that have been processed by the thread pool since the process start.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
{items} |
ObservableCounter | Int64 |
No Attributes | N/A |
The number of work items that are currently queued to be processed by the thread pool.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
{items} |
ObservableUpDownCounter | Int64 |
No Attributes | N/A |
The number of timer instances that are currently active. Timers can be created by many sources such as System.Threading.Timer, Task.Delay, or the timeout in a CancellationSource. An active timer is registered to tick at some point in the future and has not yet been canceled.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
{timers} |
ObservableUpDownCounter | Int64 |
No Attributes | N/A |
The APIs used to retrieve the values are:
- Monitor.LockContentionCount: Gets the number of times there was contention when trying to take the monitor's lock.
- ThreadPool.ThreadCount: Gets the number of thread pool threads that currently exist.
- ThreadPool.CompletedWorkItemCount: Gets the number of work items that have been processed so far.
- ThreadPool.PendingWorkItemCount: Gets the number of work items that are currently queued to be processed.
- Timer.ActiveCount: Gets the number of timers that are currently active. An active timer is registered to tick at some point in the future, and has not yet been canceled.
The number of .NET assemblies that are currently loaded.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
{assemblies} |
ObservableUpDownCounter | Int64 |
No Attributes | N/A |
The API used to retrieve the value is:
- AppDomain.GetAssemblies: Gets the number of the assemblies that have been loaded into the execution context of this application domain.
Count of exceptions that have been thrown in managed code, since the observation started. The value will be unavailable until an exception has been thrown after OpenTelemetry.Instrumentation.Runtime initialization.
Note
The value is tracked by incrementing a counter whenever an AppDomain.FirstChanceException event occurs. The observation starts when the Runtime instrumentation library is initialized, so the value will be unavailable until an exception has been thrown after the initialization.
Units | Instrument Type | Value Type | Attribute Key(s) | Attribute Values |
---|---|---|---|---|
{exceptions} |
Counter | Int64 |
No Attributes | N/A |
Relevant API:
- AppDomain.FirstChanceException Occurs when an exception is thrown in managed code, before the runtime searches the call stack for an exception handler in the application domain.
If a metric is missing, review the list of metrics to see if the metric is available in the .NET version you are running.
Some GC related metrics are unavailable until at least one garbage collection has occurred.