diff --git a/.github/workflows/package-Instrumentation.Runtime.yml b/.github/workflows/package-Instrumentation.Runtime.yml
new file mode 100644
index 0000000000..e5ff3f4966
--- /dev/null
+++ b/.github/workflows/package-Instrumentation.Runtime.yml
@@ -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 }}
\ No newline at end of file
diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml
index 5e7f20e319..ed3e8af464 100644
--- a/.github/workflows/pr_build.yml
+++ b/.github/workflows/pr_build.yml
@@ -14,7 +14,7 @@ jobs:
fail-fast: false # ensures the entire test matrix is run, even if one permutation fails
matrix:
os: [windows-latest,ubuntu-latest]
- version: [net461,netcoreapp3.1,net5.0]
+ version: [net461,netcoreapp3.1,net5.0,net6.0]
exclude:
- os: ubuntu-latest
version: net461
diff --git a/opentelemetry-dotnet-contrib.sln b/opentelemetry-dotnet-contrib.sln
index 11ea786c81..0d7d416698 100644
--- a/opentelemetry-dotnet-contrib.sln
+++ b/opentelemetry-dotnet-contrib.sln
@@ -156,6 +156,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Contrib.Exten
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Contrib.Extensions.PersistentStorage.Tests", "test\OpenTelemetry.Contrib.Extensions.PersistentStorage.Tests\OpenTelemetry.Contrib.Extensions.PersistentStorage.Tests.csproj", "{72EBA81D-2933-417C-8F21-D4CFFD72F530}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.Contrib.Instrumentation.Runtime", "src\OpenTelemetry.Contrib.Instrumentation.Runtime\OpenTelemetry.Contrib.Instrumentation.Runtime.csproj", "{F01E8C75-2791-4DBE-BD7A-5510871EBF56}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.Contrib.Instrumentation.Runtime.Tests", "test\OpenTelemetry.Contrib.Instrumentation.Runtime.Tests\OpenTelemetry.Contrib.Instrumentation.Runtime.Tests.csproj", "{FB907DF7-F3F3-4A07-885D-E5FECAE36BDA}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -306,6 +310,14 @@ Global
{72EBA81D-2933-417C-8F21-D4CFFD72F530}.Debug|Any CPU.Build.0 = Debug|Any CPU
{72EBA81D-2933-417C-8F21-D4CFFD72F530}.Release|Any CPU.ActiveCfg = Release|Any CPU
{72EBA81D-2933-417C-8F21-D4CFFD72F530}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F01E8C75-2791-4DBE-BD7A-5510871EBF56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F01E8C75-2791-4DBE-BD7A-5510871EBF56}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F01E8C75-2791-4DBE-BD7A-5510871EBF56}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F01E8C75-2791-4DBE-BD7A-5510871EBF56}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FB907DF7-F3F3-4A07-885D-E5FECAE36BDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FB907DF7-F3F3-4A07-885D-E5FECAE36BDA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FB907DF7-F3F3-4A07-885D-E5FECAE36BDA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FB907DF7-F3F3-4A07-885D-E5FECAE36BDA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -353,6 +365,8 @@ Global
{D52558C8-B7BF-4F59-A0FA-9AA629E68012} = {2097345F-4DD3-477D-BC54-A922F9B2B402}
{433C59A3-D535-421E-BA7F-9BCE0D4A3D25} = {22DF5DC0-1290-4E83-A9D8-6BB7DE3B3E63}
{72EBA81D-2933-417C-8F21-D4CFFD72F530} = {2097345F-4DD3-477D-BC54-A922F9B2B402}
+ {F01E8C75-2791-4DBE-BD7A-5510871EBF56} = {22DF5DC0-1290-4E83-A9D8-6BB7DE3B3E63}
+ {FB907DF7-F3F3-4A07-885D-E5FECAE36BDA} = {2097345F-4DD3-477D-BC54-A922F9B2B402}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B0816796-CDB3-47D7-8C3C-946434DE3B66}
diff --git a/src/OpenTelemetry.Contrib.Instrumentation.Runtime/AssemblyInfo.cs b/src/OpenTelemetry.Contrib.Instrumentation.Runtime/AssemblyInfo.cs
new file mode 100644
index 0000000000..82ef8df4ab
--- /dev/null
+++ b/src/OpenTelemetry.Contrib.Instrumentation.Runtime/AssemblyInfo.cs
@@ -0,0 +1,23 @@
+//
+// 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.
+//
+
+using System.Runtime.CompilerServices;
+
+#if SIGNED
+[assembly: InternalsVisibleTo("OpenTelemetry.Contrib.Instrumentation.Runtime.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010051c1562a090fb0c9f391012a32198b5e5d9a60e9b80fa2d7b434c9e5ccb7259bd606e66f9660676afc6692b8cdc6793d190904551d2103b7b22fa636dcbb8208839785ba402ea08fc00c8f1500ccef28bbf599aa64ffb1e1d5dc1bf3420a3777badfe697856e9d52070a50c3ea5821c80bef17ca3acffa28f89dd413f096f898")]
+#else
+[assembly: InternalsVisibleTo("OpenTelemetry.Contrib.Instrumentation.Runtime.Tests")]
+#endif
diff --git a/src/OpenTelemetry.Contrib.Instrumentation.Runtime/MeterProviderBuilderExtensions.cs b/src/OpenTelemetry.Contrib.Instrumentation.Runtime/MeterProviderBuilderExtensions.cs
new file mode 100644
index 0000000000..7bc2e24aef
--- /dev/null
+++ b/src/OpenTelemetry.Contrib.Instrumentation.Runtime/MeterProviderBuilderExtensions.cs
@@ -0,0 +1,50 @@
+//
+// 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.
+//
+
+using System;
+using OpenTelemetry.Contrib.Instrumentation.Runtime;
+
+namespace OpenTelemetry.Metrics
+{
+ ///
+ /// Extension methods to simplify registering of dependency instrumentation.
+ ///
+ public static class MeterProviderBuilderExtensions
+ {
+ ///
+ /// Enables runtime instrumentation.
+ ///
+ /// being configured.
+ /// Runtime metrics options.
+ /// The instance of to chain the calls.
+ public static MeterProviderBuilder AddRuntimeMetrics(
+ this MeterProviderBuilder builder,
+ Action 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);
+ }
+ }
+}
diff --git a/src/OpenTelemetry.Contrib.Instrumentation.Runtime/OpenTelemetry.Contrib.Instrumentation.Runtime.csproj b/src/OpenTelemetry.Contrib.Instrumentation.Runtime/OpenTelemetry.Contrib.Instrumentation.Runtime.csproj
new file mode 100644
index 0000000000..c6b246f127
--- /dev/null
+++ b/src/OpenTelemetry.Contrib.Instrumentation.Runtime/OpenTelemetry.Contrib.Instrumentation.Runtime.csproj
@@ -0,0 +1,14 @@
+
+
+
+ netstandard2.0;net461;netcoreapp3.1;net6.0
+ dotnet runtime instrumentation for OpenTelemetry .NET
+ $(PackageTags);OpenTelemetry;runtime
+ Instrumentation.Runtime-
+
+
+
+
+
+
+
diff --git a/src/OpenTelemetry.Contrib.Instrumentation.Runtime/README.md b/src/OpenTelemetry.Contrib.Instrumentation.Runtime/README.md
new file mode 100644
index 0000000000..c80f7c713b
--- /dev/null
+++ b/src/OpenTelemetry.Contrib.Instrumentation.Runtime/README.md
@@ -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/)
diff --git a/src/OpenTelemetry.Contrib.Instrumentation.Runtime/RuntimeMetrics.cs b/src/OpenTelemetry.Contrib.Instrumentation.Runtime/RuntimeMetrics.cs
new file mode 100644
index 0000000000..0fe2926d08
--- /dev/null
+++ b/src/OpenTelemetry.Contrib.Instrumentation.Runtime/RuntimeMetrics.cs
@@ -0,0 +1,104 @@
+//
+// 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.
+//
+
+using System;
+using System.Diagnostics.Metrics;
+using System.Reflection;
+using System.Threading;
+
+namespace OpenTelemetry.Contrib.Instrumentation.Runtime
+{
+ ///
+ /// .NET runtime instrumentation.
+ ///
+ 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;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The options to define the metrics.
+ 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");
+ }
+ }
+
+ ///
+ 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
+ }
+}
diff --git a/src/OpenTelemetry.Contrib.Instrumentation.Runtime/RuntimeMetricsOptions.cs b/src/OpenTelemetry.Contrib.Instrumentation.Runtime/RuntimeMetricsOptions.cs
new file mode 100644
index 0000000000..08f8576a97
--- /dev/null
+++ b/src/OpenTelemetry.Contrib.Instrumentation.Runtime/RuntimeMetricsOptions.cs
@@ -0,0 +1,100 @@
+//
+// 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.
+//
+
+namespace OpenTelemetry.Contrib.Instrumentation.Runtime
+{
+ ///
+ /// Options to define the runtime metrics.
+ ///
+ public class RuntimeMetricsOptions
+ {
+ ///
+ /// Gets a prefix used for the metric names.
+ ///
+ public string MetricPrefix { get; } = "process.runtime.dotnet.";
+
+ ///
+ /// Gets or sets a value indicating whether garbage collection metrics should be collected.
+ ///
+ public bool? GcEnabled { get; set; }
+
+#if NET6_0_OR_GREATER
+ ///
+ /// Gets or sets a value indicating whether jitter metrics should be collected.
+ ///
+ public bool? JitEnabled { get; set; }
+#endif
+
+#if NETCOREAPP3_1_OR_GREATER
+ ///
+ /// Gets or sets a value indicating whether threading metrics should be collected.
+ ///
+ public bool? ThreadingEnabled { get; set; }
+#endif
+
+ ///
+ /// Gets or sets a value indicating whether memory metrics should be collected.
+ ///
+ public bool? MemoryEnabled { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether assembly metrics should be collected.
+ ///
+ public bool? AssembliesEnabled { get; set; }
+
+ ///
+ /// Gets a value indicating whether all metrics are enabled.
+ ///
+ internal bool IsAllEnabled => this.GcEnabled == null
+#if NET6_0_OR_GREATER
+ && this.JitEnabled == null
+#endif
+#if NETCOREAPP3_1_OR_GREATER
+ && this.ThreadingEnabled == null
+#endif
+ && this.MemoryEnabled == null
+ && this.AssembliesEnabled == null;
+
+ ///
+ /// Gets a value indicating whether garbage collection metrics is enabled.
+ ///
+ internal bool IsGcEnabled => this.GcEnabled == true || this.IsAllEnabled;
+
+#if NET6_0_OR_GREATER
+ ///
+ /// Gets a value indicating whether jitter metrics is enabled.
+ ///
+ internal bool IsJitEnabled => this.JitEnabled == true || this.IsAllEnabled;
+#endif
+
+#if NETCOREAPP3_1_OR_GREATER
+ ///
+ /// Gets a value indicating whether threading metrics is enabled.
+ ///
+ internal bool IsThreadingEnabled => this.ThreadingEnabled == true || this.IsAllEnabled;
+#endif
+
+ ///
+ /// Gets a value indicating whether memory metrics is enabled.
+ ///
+ internal bool IsMemoryEnabled => this.MemoryEnabled == true || this.IsAllEnabled;
+
+ ///
+ /// Gets a value indicating whether assembly metrics is enabled.
+ ///
+ internal bool IsAssembliesEnabled => this.AssembliesEnabled == true || this.IsAllEnabled;
+ }
+}
diff --git a/test/OpenTelemetry.Contrib.Instrumentation.Runtime.Tests/OpenTelemetry.Contrib.Instrumentation.Runtime.Tests.csproj b/test/OpenTelemetry.Contrib.Instrumentation.Runtime.Tests/OpenTelemetry.Contrib.Instrumentation.Runtime.Tests.csproj
new file mode 100644
index 0000000000..3b801c40fa
--- /dev/null
+++ b/test/OpenTelemetry.Contrib.Instrumentation.Runtime.Tests/OpenTelemetry.Contrib.Instrumentation.Runtime.Tests.csproj
@@ -0,0 +1,26 @@
+
+
+
+ netcoreapp3.1;net6.0
+ $(TargetFrameworks);net461
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+
+
+
+
+
+
+
diff --git a/test/OpenTelemetry.Contrib.Instrumentation.Runtime.Tests/RuntimeMetricsOptionsTests.cs b/test/OpenTelemetry.Contrib.Instrumentation.Runtime.Tests/RuntimeMetricsOptionsTests.cs
new file mode 100644
index 0000000000..e8942649a7
--- /dev/null
+++ b/test/OpenTelemetry.Contrib.Instrumentation.Runtime.Tests/RuntimeMetricsOptionsTests.cs
@@ -0,0 +1,140 @@
+//
+// 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.
+//
+
+using Xunit;
+
+namespace OpenTelemetry.Contrib.Instrumentation.Runtime.Tests
+{
+ public class RuntimeMetricsOptionsTests
+ {
+ [Fact]
+ public void Enable_All_If_Nothing_Was_Defined()
+ {
+ var options = new RuntimeMetricsOptions();
+
+ Assert.True(options.IsGcEnabled);
+#if NET6_0_OR_GREATER
+ Assert.True(options.IsJitEnabled);
+#endif
+#if NETCOREAPP3_1_OR_GREATER
+ Assert.True(options.IsThreadingEnabled);
+#endif
+ Assert.True(options.IsMemoryEnabled);
+ Assert.True(options.IsAssembliesEnabled);
+ Assert.True(options.IsAllEnabled);
+ }
+
+ [Fact]
+ public void Enable_Gc_Only()
+ {
+ var options = new RuntimeMetricsOptions { GcEnabled = true };
+
+ Assert.True(options.IsGcEnabled);
+#if NET6_0_OR_GREATER
+ Assert.False(options.IsJitEnabled);
+#endif
+#if NETCOREAPP3_1_OR_GREATER
+ Assert.False(options.IsThreadingEnabled);
+#endif
+ Assert.False(options.IsMemoryEnabled);
+ Assert.False(options.IsAssembliesEnabled);
+ Assert.False(options.IsAllEnabled);
+ }
+
+#if NET6_0_OR_GREATER
+ [Fact]
+ public void Enable_Jit_Only()
+ {
+ var options = new RuntimeMetricsOptions { JitEnabled = true };
+
+ Assert.False(options.IsGcEnabled);
+ Assert.True(options.IsJitEnabled);
+ Assert.False(options.IsThreadingEnabled);
+ Assert.False(options.IsMemoryEnabled);
+ Assert.False(options.IsAssembliesEnabled);
+ Assert.False(options.IsAllEnabled);
+ }
+#endif
+
+#if NETCOREAPP3_1_OR_GREATER
+ [Fact]
+ public void Enable_Threading_Only()
+ {
+ var options = new RuntimeMetricsOptions { ThreadingEnabled = true };
+
+ Assert.False(options.IsGcEnabled);
+#if NET6_0_OR_GREATER
+ Assert.False(options.IsJitEnabled);
+#endif
+ Assert.True(options.IsThreadingEnabled);
+ Assert.False(options.IsMemoryEnabled);
+ Assert.False(options.IsAssembliesEnabled);
+ Assert.False(options.IsAllEnabled);
+ }
+#endif
+
+ [Fact]
+ public void Enable_Memory_Only()
+ {
+ var options = new RuntimeMetricsOptions { MemoryEnabled = true };
+
+ Assert.False(options.IsGcEnabled);
+#if NET6_0_OR_GREATER
+ Assert.False(options.IsJitEnabled);
+#endif
+#if NETCOREAPP3_1_OR_GREATER
+ Assert.False(options.IsThreadingEnabled);
+#endif
+ Assert.True(options.IsMemoryEnabled);
+ Assert.False(options.IsAssembliesEnabled);
+ Assert.False(options.IsAllEnabled);
+ }
+
+ [Fact]
+ public void Enable_Assemblies_Only()
+ {
+ var options = new RuntimeMetricsOptions { AssembliesEnabled = true };
+
+ Assert.False(options.IsGcEnabled);
+#if NET6_0_OR_GREATER
+ Assert.False(options.IsJitEnabled);
+#endif
+#if NETCOREAPP3_1_OR_GREATER
+ Assert.False(options.IsThreadingEnabled);
+#endif
+ Assert.False(options.IsMemoryEnabled);
+ Assert.True(options.IsAssembliesEnabled);
+ Assert.False(options.IsAllEnabled);
+ }
+
+ [Fact]
+ public void Enable_Multiple()
+ {
+ var options = new RuntimeMetricsOptions { GcEnabled = true, MemoryEnabled = true };
+
+ Assert.True(options.IsGcEnabled);
+#if NET6_0_OR_GREATER
+ Assert.False(options.IsJitEnabled);
+#endif
+#if NETCOREAPP3_1_OR_GREATER
+ Assert.False(options.IsThreadingEnabled);
+#endif
+ Assert.True(options.IsMemoryEnabled);
+ Assert.False(options.IsAssembliesEnabled);
+ Assert.False(options.IsAllEnabled);
+ }
+ }
+}
diff --git a/test/OpenTelemetry.Contrib.Instrumentation.Runtime.Tests/RuntimeMetricsTests.cs b/test/OpenTelemetry.Contrib.Instrumentation.Runtime.Tests/RuntimeMetricsTests.cs
new file mode 100644
index 0000000000..4da53cbb5e
--- /dev/null
+++ b/test/OpenTelemetry.Contrib.Instrumentation.Runtime.Tests/RuntimeMetricsTests.cs
@@ -0,0 +1,61 @@
+//
+// 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.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using OpenTelemetry.Exporter;
+using OpenTelemetry.Metrics;
+using Xunit;
+
+namespace OpenTelemetry.Contrib.Instrumentation.Runtime.Tests
+{
+ public class RuntimeMetricsTests
+ {
+ private MeterProvider meterProvider = null;
+
+ [Fact]
+ public async Task RequestMetricIsCaptured()
+ {
+ var metricItems = new List();
+ var metricExporter = new InMemoryExporter(metricItems);
+
+ var metricReader = new PeriodicExportingMetricReader(metricExporter, 500);
+
+ this.meterProvider = Sdk.CreateMeterProviderBuilder()
+ .AddRuntimeMetrics(options =>
+ {
+ options.GcEnabled = true;
+#if NETCOREAPP3_1_OR_GREATER
+ options.ThreadingEnabled = true;
+#endif
+ options.MemoryEnabled = true;
+#if NET6_0_OR_GREATER
+
+ options.JitEnabled = true;
+#endif
+ options.AssembliesEnabled = true;
+ })
+ .AddReader(metricReader)
+ .Build();
+
+ await Task.Delay(TimeSpan.FromSeconds(2));
+ this.meterProvider.Dispose();
+
+ Assert.True(metricItems.Count > 1);
+ }
+ }
+}