forked from open-telemetry/opentelemetry-dotnet-contrib
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Runtime instrumentation (open-telemetry#207)
- Loading branch information
1 parent
0b5d9a9
commit 432d459
Showing
12 changed files
with
670 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
name: Pack OpenTelemetry.Contrib.Instrumentation.Runtime | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
logLevel: | ||
description: 'Log level' | ||
required: true | ||
default: 'warning' | ||
push: | ||
tags: | ||
- 'Instrumentation.Runtime-*' # trigger when we create a tag with prefix "Instrumentation.Runtime-" | ||
|
||
jobs: | ||
build-test-pack: | ||
runs-on: ${{ matrix.os }} | ||
env: | ||
PROJECT: OpenTelemetry.Contrib.Instrumentation.Runtime | ||
|
||
strategy: | ||
matrix: | ||
os: [windows-latest] | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: 0 # fetching all | ||
|
||
- name: Install dependencies | ||
run: dotnet restore | ||
|
||
- name: dotnet build ${{env.PROJECT}} | ||
run: dotnet build src/${{env.PROJECT}} --configuration Release --no-restore -p:Deterministic=true | ||
|
||
- name: dotnet test ${{env.PROJECT}} | ||
run: dotnet test test/${{env.PROJECT}}.Tests | ||
|
||
- name: dotnet pack ${{env.PROJECT}} | ||
run: dotnet pack src/${{env.PROJECT}} --configuration Release --no-build | ||
|
||
- name: Publish Artifacts | ||
uses: actions/upload-artifact@v2 | ||
with: | ||
name: ${{env.PROJECT}}-packages | ||
path: '**/${{env.PROJECT}}/bin/**/*.*nupkg' | ||
|
||
- name: Publish Nuget | ||
run: | | ||
nuget push **/${{env.PROJECT}}/bin/**/*.nupkg -Source https://api.nuget.org/v3/index.json -ApiKey ${{ secrets.NUGET_TOKEN }} -SymbolApiKey ${{ secrets.NUGET_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
src/OpenTelemetry.Contrib.Instrumentation.Runtime/AssemblyInfo.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// <copyright file="AssemblyInfo.cs" company="OpenTelemetry Authors"> | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// </copyright> | ||
|
||
using System.Runtime.CompilerServices; | ||
|
||
#if SIGNED | ||
[assembly: InternalsVisibleTo("OpenTelemetry.Contrib.Instrumentation.Runtime.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")] | ||
#else | ||
[assembly: InternalsVisibleTo("OpenTelemetry.Contrib.Instrumentation.Runtime.Tests")] | ||
#endif |
50 changes: 50 additions & 0 deletions
50
src/OpenTelemetry.Contrib.Instrumentation.Runtime/MeterProviderBuilderExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// <copyright file="MeterProviderBuilderExtensions.cs" company="OpenTelemetry Authors"> | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// </copyright> | ||
|
||
using System; | ||
using OpenTelemetry.Contrib.Instrumentation.Runtime; | ||
|
||
namespace OpenTelemetry.Metrics | ||
{ | ||
/// <summary> | ||
/// Extension methods to simplify registering of dependency instrumentation. | ||
/// </summary> | ||
public static class MeterProviderBuilderExtensions | ||
{ | ||
/// <summary> | ||
/// Enables runtime instrumentation. | ||
/// </summary> | ||
/// <param name="builder"><see cref="MeterProviderBuilder"/> being configured.</param> | ||
/// <param name="configure">Runtime metrics options.</param> | ||
/// <returns>The instance of <see cref="MeterProviderBuilder"/> to chain the calls.</returns> | ||
public static MeterProviderBuilder AddRuntimeMetrics( | ||
this MeterProviderBuilder builder, | ||
Action<RuntimeMetricsOptions> configure = null) | ||
{ | ||
if (builder == null) | ||
{ | ||
throw new ArgumentNullException(nameof(builder)); | ||
} | ||
|
||
var options = new RuntimeMetricsOptions(); | ||
configure?.Invoke(options); | ||
|
||
var instrumentation = new RuntimeMetrics(options); | ||
builder.AddMeter(RuntimeMetrics.InstrumentationName); | ||
return builder.AddInstrumentation(() => instrumentation); | ||
} | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
...etry.Contrib.Instrumentation.Runtime/OpenTelemetry.Contrib.Instrumentation.Runtime.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFrameworks>netstandard2.0;net461;netcoreapp3.1;net6.0</TargetFrameworks> | ||
<Description>dotnet runtime instrumentation for OpenTelemetry .NET</Description> | ||
<PackageTags>$(PackageTags);OpenTelemetry;runtime</PackageTags> | ||
<MinVerTagPrefix>Instrumentation.Runtime-</MinVerTagPrefix> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="OpenTelemetry.Api" Version="1.2.0-rc2" /> | ||
</ItemGroup> | ||
|
||
</Project> |
88 changes: 88 additions & 0 deletions
88
src/OpenTelemetry.Contrib.Instrumentation.Runtime/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# DotNet Runtime Instrumentation for OpenTelemetry .NET | ||
|
||
[![NuGet](https://img.shields.io/nuget/v/OpenTelemetry.Contrib.Instrumentation.Runtime.svg)](https://www.nuget.org/packages/OpenTelemetry.Contrib.Instrumentation.Runtime) | ||
[![NuGet](https://img.shields.io/nuget/dt/OpenTelemetry.Contrib.Instrumentation.Runtime.svg)](https://www.nuget.org/packages/OpenTelemetry.Contrib.Instrumentation.Runtime) | ||
|
||
This is an [Instrumentation | ||
Library](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/glossary.md#instrumentation-library), | ||
which instruments [.NET Runtime](https://docs.microsoft.com/dotnet) and | ||
collect telemetry about runtime behavior. | ||
|
||
## Steps to enable OpenTelemetry.Contrib.Instrumentation.Runtime | ||
|
||
### Step 1: Install Package | ||
|
||
Add a reference to the | ||
[`OpenTelemetry.Contrib.Instrumentation.Runtime`](https://www.nuget.org/packages/OpenTelemetry.Contrib.Instrumentation.Runtime) | ||
package. Also, add any other instrumentations & exporters you will need. | ||
|
||
```shell | ||
dotnet add package OpenTelemetry.Contrib.Instrumentation.Runtime | ||
``` | ||
|
||
### Step 2: Enable Runtime Instrumentation at application startup | ||
|
||
Runtime instrumentation must be enabled at application startup. This is | ||
typically done in the `ConfigureServices` of your `Startup` class. The example | ||
below enables this instrumentation by using an extension method on | ||
`IServiceCollection`. This extension method requires adding the package | ||
[`OpenTelemetry.Extensions.Hosting`](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry.Extensions.Hosting/README.md) | ||
to the application. This ensures the instrumentation is disposed when the host | ||
is shutdown. | ||
|
||
Additionally, this examples sets up the OpenTelemetry Prometheus exporter, which | ||
requires adding the package | ||
[`OpenTelemetry.Exporter.Prometheus`](https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry.Exporter.Prometheus/README.md) | ||
to the application. | ||
|
||
```csharp | ||
using Microsoft.Extensions.DependencyInjection; | ||
using OpenTelemetry.Metrics; | ||
|
||
public void ConfigureServices(IServiceCollection services) | ||
{ | ||
services.AddOpenTelemetryMetrics((builder) => builder | ||
.AddRuntimeMetrics() | ||
.AddPrometheusExporter() | ||
); | ||
} | ||
``` | ||
|
||
Or configure directly: | ||
|
||
```csharp | ||
using var meterProvider = Sdk.CreateMeterProviderBuilder() | ||
.AddRuntimeMetrics() | ||
.Build(); | ||
``` | ||
|
||
## Advanced configuration | ||
|
||
By default all available runtime metrics will be added. It's also possible to | ||
specify only the required metrics: | ||
|
||
```csharp | ||
using var meterProvider = Sdk.CreateMeterProviderBuilder() | ||
.AddRuntimeMetrics(options => options | ||
{ | ||
options.GcEnabled = true; | ||
options.ThreadingEnabled = true; | ||
options.MemoryEnabled = true; | ||
}) | ||
.Build(); | ||
``` | ||
|
||
## Troubleshooting | ||
|
||
This component uses an | ||
[EventSource](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventsource) | ||
with the name "OpenTelemetry-Instrumentation-Runtime" for its internal | ||
logging. Please refer to [SDK | ||
troubleshooting](https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry#troubleshooting) | ||
for instructions on seeing these internal logs. | ||
|
||
## References | ||
|
||
* [Introduction to ASP.NET | ||
Core](https://docs.microsoft.com/aspnet/core/introduction-to-aspnet-core) | ||
* [OpenTelemetry Project](https://opentelemetry.io/) |
104 changes: 104 additions & 0 deletions
104
src/OpenTelemetry.Contrib.Instrumentation.Runtime/RuntimeMetrics.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// <copyright file="RuntimeMetrics.cs" company="OpenTelemetry Authors"> | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// </copyright> | ||
|
||
using System; | ||
using System.Diagnostics.Metrics; | ||
using System.Reflection; | ||
using System.Threading; | ||
|
||
namespace OpenTelemetry.Contrib.Instrumentation.Runtime | ||
{ | ||
/// <summary> | ||
/// .NET runtime instrumentation. | ||
/// </summary> | ||
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 readonly Meter meter; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="RuntimeMetrics"/> class. | ||
/// </summary> | ||
/// <param name="options">The options to define the metrics.</param> | ||
public RuntimeMetrics(RuntimeMetricsOptions options) | ||
{ | ||
this.meter = new Meter(InstrumentationName, InstrumentationVersion); | ||
|
||
if (options.IsGcEnabled) | ||
{ | ||
this.meter.CreateObservableGauge($"{options.MetricPrefix}gc.heap", () => GC.GetTotalMemory(false), "B", "GC Heap Size"); | ||
this.meter.CreateObservableGauge($"{options.MetricPrefix}gen_0-gc.count", () => GC.CollectionCount(0), description: "Gen 0 GC Count"); | ||
this.meter.CreateObservableGauge($"{options.MetricPrefix}gen_1-gc.count", () => GC.CollectionCount(1), description: "Gen 1 GC Count"); | ||
this.meter.CreateObservableGauge($"{options.MetricPrefix}gen_2-gc.count", () => GC.CollectionCount(2), description: "Gen 2 GC Count"); | ||
#if NETCOREAPP3_1_OR_GREATER | ||
this.meter.CreateObservableCounter($"{options.MetricPrefix}alloc.rate", () => GC.GetTotalAllocatedBytes(), "B", "Allocation Rate"); | ||
this.meter.CreateObservableCounter($"{options.MetricPrefix}gc.fragmentation", GetFragmentation, description: "GC Fragmentation"); | ||
#endif | ||
|
||
#if NET6_0_OR_GREATER | ||
this.meter.CreateObservableCounter($"{options.MetricPrefix}gc.committed", () => (double)(GC.GetGCMemoryInfo().TotalCommittedBytes / 1_000_000), "MB", description: "GC Committed Bytes"); | ||
#endif | ||
} | ||
|
||
#if NET6_0_OR_GREATER | ||
if (options.IsJitEnabled) | ||
{ | ||
this.meter.CreateObservableCounter($"{options.MetricPrefix}il.bytes.jitted", () => System.Runtime.JitInfo.GetCompiledILBytes(), "B", description: "IL Bytes Jitted"); | ||
this.meter.CreateObservableCounter($"{options.MetricPrefix}methods.jitted.count", () => System.Runtime.JitInfo.GetCompiledMethodCount(), description: "Number of Methods Jitted"); | ||
this.meter.CreateObservableGauge($"{options.MetricPrefix}time.in.jit", () => System.Runtime.JitInfo.GetCompilationTime().TotalMilliseconds, "ms", description: "Time spent in JIT"); | ||
} | ||
#endif | ||
|
||
#if NETCOREAPP3_1_OR_GREATER | ||
if (options.IsThreadingEnabled) | ||
{ | ||
this.meter.CreateObservableGauge($"{options.MetricPrefix}monitor.lock.contention.count", () => Monitor.LockContentionCount, description: "Monitor Lock Contention Count"); | ||
this.meter.CreateObservableCounter($"{options.MetricPrefix}threadpool.thread.count", () => ThreadPool.ThreadCount, description: "ThreadPool Thread Count"); | ||
this.meter.CreateObservableGauge($"{options.MetricPrefix}threadpool.completed.items.count", () => ThreadPool.CompletedWorkItemCount, description: "ThreadPool Completed Work Item Count"); | ||
this.meter.CreateObservableCounter($"{options.MetricPrefix}threadpool.queue.length", () => ThreadPool.PendingWorkItemCount, description: "ThreadPool Queue Length"); | ||
this.meter.CreateObservableCounter($"{options.MetricPrefix}active.timer.count", () => Timer.ActiveCount, description: "Number of Active Timers"); | ||
} | ||
#endif | ||
|
||
if (options.IsMemoryEnabled) | ||
{ | ||
this.meter.CreateObservableGauge($"{options.MetricPrefix}memory.usage", () => (double)(Environment.WorkingSet / 1_000_000), "MB", "Working Set"); | ||
} | ||
|
||
if (options.IsAssembliesEnabled) | ||
{ | ||
this.meter.CreateObservableCounter($"{options.MetricPrefix}assembly.count", () => AppDomain.CurrentDomain.GetAssemblies().Length, description: "Number of Assemblies Loaded"); | ||
} | ||
} | ||
|
||
/// <inheritdoc/> | ||
public void Dispose() | ||
{ | ||
this.meter?.Dispose(); | ||
} | ||
|
||
#if NETCOREAPP3_1_OR_GREATER | ||
private static double GetFragmentation() | ||
{ | ||
var gcInfo = GC.GetGCMemoryInfo(); | ||
return gcInfo.HeapSizeBytes != 0 ? gcInfo.FragmentedBytes * 100d / gcInfo.HeapSizeBytes : 0; | ||
} | ||
#endif | ||
} | ||
} |
Oops, something went wrong.