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

Add support for SqlClient metrics #3875

Merged
merged 1 commit into from
Dec 10, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This component adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.h
- Support for .NET9.
- Support for [RabbitMQ.Client](https://www.nuget.org/packages/RabbitMQ.Client/)
traces instrumentation for versions `7.0.0`+.
- Support for SqlClient metrics.

### Changed

Expand Down
23 changes: 15 additions & 8 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,18 +181,25 @@ due to lack of stable semantic convention.
Metrics are stable, but particular instrumentation are in Experimental status
due to lack of stable semantic convention.

| ID | Instrumented library | Documentation | Supported versions | Instrumentation type | Status |
|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|----------------------|-----------------------------------------------------------------------------------------------------------------------------------|
| `ASPNET` | ASP.NET Framework \[1\] **Not supported on .NET** | [ASP.NET metrics](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/Instrumentation.AspNet-1.9.0-beta.1/src/OpenTelemetry.Instrumentation.AspNet/README.md#list-of-metrics-produced) | * | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
| `ASPNETCORE` | ASP.NET Core **Not supported on .NET Framework** | [ASP.NET Core metrics](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/Instrumentation.AspNetCore-1.10.0/src/OpenTelemetry.Instrumentation.AspNetCore/README.md#list-of-metrics-produced) | * | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
| `HTTPCLIENT` | [System.Net.Http.HttpClient](https://docs.microsoft.com/dotnet/api/system.net.http.httpclient) and [System.Net.HttpWebRequest](https://docs.microsoft.com/dotnet/api/system.net.httpwebrequest) | [HttpClient metrics](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/Instrumentation.Http-1.10.0/src/OpenTelemetry.Instrumentation.Http/README.md#list-of-metrics-produced) | * | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
| `NETRUNTIME` | [OpenTelemetry.Instrumentation.Runtime](https://www.nuget.org/packages/OpenTelemetry.Instrumentation.Runtime) | [Runtime metrics](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/Instrumentation.Runtime-1.10.0/src/OpenTelemetry.Instrumentation.Runtime/README.md#metrics) | * | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
| `PROCESS` | [OpenTelemetry.Instrumentation.Process](https://www.nuget.org/packages/OpenTelemetry.Instrumentation.Process) | [Process metrics](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/Instrumentation.Process-1.10.0-beta.1/src/OpenTelemetry.Instrumentation.Process/README.md#metrics) | * | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
| `NSERVICEBUS` | [NServiceBus](https://www.nuget.org/packages/NServiceBus) | [NServiceBus metrics](https://docs.particular.net/samples/open-telemetry/prometheus-grafana/#reporting-metric-values) | ≥8.0.0 & < 10.0.0 | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
| ID | Instrumented library | Documentation | Supported versions | Instrumentation type | Status |
|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|----------------------|-----------------------------------------------------------------------------------------------------------------------------------|
| `ASPNET` | ASP.NET Framework \[1\] **Not supported on .NET** | [ASP.NET metrics](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/Instrumentation.AspNet-1.9.0-beta.1/src/OpenTelemetry.Instrumentation.AspNet/README.md#list-of-metrics-produced) | * | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
| `ASPNETCORE` | ASP.NET Core **Not supported on .NET Framework** | [ASP.NET Core metrics](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/Instrumentation.AspNetCore-1.10.0/src/OpenTelemetry.Instrumentation.AspNetCore/README.md#list-of-metrics-produced) | * | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
| `HTTPCLIENT` | [System.Net.Http.HttpClient](https://docs.microsoft.com/dotnet/api/system.net.http.httpclient) and [System.Net.HttpWebRequest](https://docs.microsoft.com/dotnet/api/system.net.httpwebrequest) | [HttpClient metrics](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/Instrumentation.Http-1.10.0/src/OpenTelemetry.Instrumentation.Http/README.md#list-of-metrics-produced) | * | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
| `NETRUNTIME` | [OpenTelemetry.Instrumentation.Runtime](https://www.nuget.org/packages/OpenTelemetry.Instrumentation.Runtime) | [Runtime metrics](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/Instrumentation.Runtime-1.10.0/src/OpenTelemetry.Instrumentation.Runtime/README.md#metrics) | * | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
| `NSERVICEBUS` | [NServiceBus](https://www.nuget.org/packages/NServiceBus) | [NServiceBus metrics](https://docs.particular.net/samples/open-telemetry/prometheus-grafana/#reporting-metric-values) | ≥8.0.0 & < 10.0.0 | source & bytecode | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
| `PROCESS` | [OpenTelemetry.Instrumentation.Process](https://www.nuget.org/packages/OpenTelemetry.Instrumentation.Process) | [Process metrics](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/blob/Instrumentation.Process-1.10.0-beta.1/src/OpenTelemetry.Instrumentation.Process/README.md#metrics) | * | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
| `SQLCLIENT` | [Microsoft.Data.SqlClient](https://www.nuget.org/packages/Microsoft.Data.SqlClient), [System.Data.SqlClient](https://www.nuget.org/packages/System.Data.SqlClient) \[2\] and `System.Data` (shipped with .NET Framework) | [SqlClient metrics](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/releases/tag/Instrumentation.SqlClient-1.10.0-beta.1) | * \[3\] | source | [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md) |
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Link leads to changelog, there is no good documentation for metrics yet.


\[1\]: The ASP.NET metrics are generated only if the `AspNet` trace instrumentation
is also enabled.

\[2\]: `System.Data.SqlClient` is [deprecated](https://www.nuget.org/packages/System.Data.SqlClient/4.9.0#readme-body-tab).

\[3\]: `Microsoft.Data.SqlClient` v3.* is not supported on .NET Framework,
due to [issue](https://github.com/open-telemetry/opentelemetry-dotnet/issues/4243).
`System.Data.SqlClient` is supported from version 4.8.5.

### Logs instrumentations

**Status**: [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static void AddGrpcClient(LazyInstrumentationLoader lazyInstrumentationLo
[MethodImpl(MethodImplOptions.NoInlining)]
public static void AddSqlClient(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager, TracerSettings tracerSettings)
{
new SqlClientInitializer(lazyInstrumentationLoader, pluginManager, tracerSettings);
new SqlClientTracerInitializer(lazyInstrumentationLoader, pluginManager, tracerSettings);
}

#if NET
Expand Down Expand Up @@ -89,5 +89,11 @@ public static void AddHttpClient(LazyInstrumentationLoader lazyInstrumentationLo
{
new HttpClientMetricsInitializer(lazyInstrumentationLoader);
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static void AddSqlClient(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager)
{
new SqlClientMetricsInitializer(lazyInstrumentationLoader, pluginManager);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public static MeterProviderBuilder UseEnvironmentVariables(
.AddMeter("Microsoft.AspNetCore.Diagnostics")
.AddMeter("Microsoft.AspNetCore.RateLimiting"),
#endif
MetricInstrumentation.SqlClient => Wrappers.AddSqlClientInstrumentation(builder, lazyInstrumentationLoader, pluginManager),
_ => null,
};
}
Expand Down Expand Up @@ -115,6 +116,13 @@ public static MeterProviderBuilder AddProcessInstrumentation(MeterProviderBuilde
return builder.AddProcessInstrumentation();
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static MeterProviderBuilder AddSqlClientInstrumentation(MeterProviderBuilder builder, LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager)
{
DelayedInitialization.Metrics.AddSqlClient(lazyInstrumentationLoader, pluginManager);
return builder.AddMeter("OpenTelemetry.Instrumentation.SqlClient");
}

// Exporters

[MethodImpl(MethodImplOptions.NoInlining)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ internal enum MetricInstrumentation
/// <summary>
/// ASP.NET Core instrumentation.
/// </summary>
AspNetCore = 6
AspNetCore = 6,
#endif

/// <summary>
/// SqlClient instrumentation.
/// </summary>
SqlClient = 7
}
3 changes: 3 additions & 0 deletions src/OpenTelemetry.AutoInstrumentation/Instrumentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,9 @@ private static void AddLazilyLoadedMetricInstrumentations(LazyInstrumentationLoa
break;
case MetricInstrumentation.NServiceBus:
break;
case MetricInstrumentation.SqlClient:
DelayedInitialization.Metrics.AddSqlClient(lazyInstrumentationLoader, pluginManager);
break;
default:
Logger.Warning($"Configured metric instrumentation type is not supported: {instrumentation}");
if (FailFastSettings.Value.FailFast)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

using System.Reflection;
using OpenTelemetry.AutoInstrumentation.Configurations;
using OpenTelemetry.AutoInstrumentation.Plugins;

namespace OpenTelemetry.AutoInstrumentation.Loading.Initializers;

internal class SqlClientInitializer
internal abstract class SqlClientInitializer
{
private readonly PluginManager _pluginManager;
private readonly TracerSettings _tracerSettings;

private int _initialized;

public SqlClientInitializer(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager, TracerSettings tracerSettings)
protected SqlClientInitializer(LazyInstrumentationLoader lazyInstrumentationLoader)
{
_pluginManager = pluginManager;
_tracerSettings = tracerSettings;
lazyInstrumentationLoader.Add(new GenericInitializer("System.Data.SqlClient", InitializeOnFirstCall));
lazyInstrumentationLoader.Add(new GenericInitializer("Microsoft.Data.SqlClient", InitializeOnFirstCall));

Expand All @@ -26,30 +15,5 @@ public SqlClientInitializer(LazyInstrumentationLoader lazyInstrumentationLoader,
#endif
}

private void InitializeOnFirstCall(ILifespanManager lifespanManager)
{
if (Interlocked.Exchange(ref _initialized, value: 1) != default)
{
// InitializeOnFirstCall() was already called before
return;
}

var instrumentationType = Type.GetType("OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentation, OpenTelemetry.Instrumentation.SqlClient")!;

var options = new OpenTelemetry.Instrumentation.SqlClient.SqlClientTraceInstrumentationOptions
{
SetDbStatementForText = _tracerSettings.InstrumentationOptions.SqlClientSetDbStatementForText
};
_pluginManager.ConfigureTracesOptions(options);

var propertyInfo = instrumentationType.GetProperty("TracingOptions", BindingFlags.Static | BindingFlags.Public);
propertyInfo?.SetValue(null, options);

var instrumentation = instrumentationType.InvokeMember("AddTracingHandle", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, null, []);

if (instrumentation != null)
{
lifespanManager.Track(instrumentation);
}
}
protected abstract void InitializeOnFirstCall(ILifespanManager lifespanManager);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

using System.Reflection;
using OpenTelemetry.AutoInstrumentation.Plugins;

namespace OpenTelemetry.AutoInstrumentation.Loading.Initializers;

internal sealed class SqlClientMetricsInitializer : SqlClientInitializer
{
private readonly PluginManager _pluginManager;

private int _initialized;

public SqlClientMetricsInitializer(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager)
: base(lazyInstrumentationLoader)
{
_pluginManager = pluginManager;
}

protected override void InitializeOnFirstCall(ILifespanManager lifespanManager)
{
if (Interlocked.Exchange(ref _initialized, value: 1) != default)
{
// InitializeOnFirstCall() was already called before
return;
}

var instrumentationType = Type.GetType("OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentation, OpenTelemetry.Instrumentation.SqlClient")!;
var instrumentation = instrumentationType.InvokeMember("AddMetricHandle", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, null, []);

if (instrumentation != null)
{
lifespanManager.Track(instrumentation);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

using System.Reflection;
using OpenTelemetry.AutoInstrumentation.Configurations;
using OpenTelemetry.AutoInstrumentation.Plugins;

namespace OpenTelemetry.AutoInstrumentation.Loading.Initializers;

internal sealed class SqlClientTracerInitializer : SqlClientInitializer
{
private readonly PluginManager _pluginManager;
private readonly TracerSettings _tracerSettings;

private int _initialized;

public SqlClientTracerInitializer(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager, TracerSettings tracerSettings)
: base(lazyInstrumentationLoader)
{
_pluginManager = pluginManager;
_tracerSettings = tracerSettings;
}

protected override void InitializeOnFirstCall(ILifespanManager lifespanManager)
{
if (Interlocked.Exchange(ref _initialized, value: 1) != default)
{
// InitializeOnFirstCall() was already called before
return;
}

var instrumentationType = Type.GetType("OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentation, OpenTelemetry.Instrumentation.SqlClient")!;

var options = new OpenTelemetry.Instrumentation.SqlClient.SqlClientTraceInstrumentationOptions
{
SetDbStatementForText = _tracerSettings.InstrumentationOptions.SqlClientSetDbStatementForText
};
_pluginManager.ConfigureTracesOptions(options);

var propertyInfo = instrumentationType.GetProperty("TracingOptions", BindingFlags.Static | BindingFlags.Public);
propertyInfo?.SetValue(null, options);

var instrumentation = instrumentationType.InvokeMember("AddTracingHandle", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, null, []);

if (instrumentation != null)
{
lifespanManager.Track(instrumentation);
}
}
}
Loading
Loading