Skip to content

Commit 3fc3553

Browse files
authored
Add support for SqlClient metrics (open-telemetry#3875)
1 parent 6c299d7 commit 3fc3553

File tree

16 files changed

+269
-50
lines changed

16 files changed

+269
-50
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ This component adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.h
1212
- Support for .NET9.
1313
- Support for [RabbitMQ.Client](https://www.nuget.org/packages/RabbitMQ.Client/)
1414
traces instrumentation for versions `7.0.0`+.
15+
- Support for SqlClient metrics.
1516

1617
### Changed
1718

docs/config.md

+15-8
Original file line numberDiff line numberDiff line change
@@ -181,18 +181,25 @@ due to lack of stable semantic convention.
181181
Metrics are stable, but particular instrumentation are in Experimental status
182182
due to lack of stable semantic convention.
183183

184-
| ID | Instrumented library | Documentation | Supported versions | Instrumentation type | Status |
185-
|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|----------------------|-----------------------------------------------------------------------------------------------------------------------------------|
186-
| `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) |
187-
| `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) |
188-
| `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) |
189-
| `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) |
190-
| `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) |
191-
| `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) |
184+
| ID | Instrumented library | Documentation | Supported versions | Instrumentation type | Status |
185+
|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|----------------------|-----------------------------------------------------------------------------------------------------------------------------------|
186+
| `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) |
187+
| `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) |
188+
| `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) |
189+
| `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) |
190+
| `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) |
191+
| `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) |
192+
| `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) |
192193

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

197+
\[2\]: `System.Data.SqlClient` is [deprecated](https://www.nuget.org/packages/System.Data.SqlClient/4.9.0#readme-body-tab).
198+
199+
\[3\]: `Microsoft.Data.SqlClient` v3.* is not supported on .NET Framework,
200+
due to [issue](https://github.com/open-telemetry/opentelemetry-dotnet/issues/4243).
201+
`System.Data.SqlClient` is supported from version 4.8.5.
202+
196203
### Logs instrumentations
197204

198205
**Status**: [Experimental](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md).

src/OpenTelemetry.AutoInstrumentation/Configurations/DelayedInitialization.cs

+7-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public static void AddGrpcClient(LazyInstrumentationLoader lazyInstrumentationLo
4343
[MethodImpl(MethodImplOptions.NoInlining)]
4444
public static void AddSqlClient(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager, TracerSettings tracerSettings)
4545
{
46-
new SqlClientInitializer(lazyInstrumentationLoader, pluginManager, tracerSettings);
46+
new SqlClientTracerInitializer(lazyInstrumentationLoader, pluginManager, tracerSettings);
4747
}
4848

4949
#if NET
@@ -89,5 +89,11 @@ public static void AddHttpClient(LazyInstrumentationLoader lazyInstrumentationLo
8989
{
9090
new HttpClientMetricsInitializer(lazyInstrumentationLoader);
9191
}
92+
93+
[MethodImpl(MethodImplOptions.NoInlining)]
94+
public static void AddSqlClient(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager)
95+
{
96+
new SqlClientMetricsInitializer(lazyInstrumentationLoader, pluginManager);
97+
}
9298
}
9399
}

src/OpenTelemetry.AutoInstrumentation/Configurations/EnvironmentConfigurationMetricHelper.cs

+8
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public static MeterProviderBuilder UseEnvironmentVariables(
4444
.AddMeter("Microsoft.AspNetCore.Diagnostics")
4545
.AddMeter("Microsoft.AspNetCore.RateLimiting"),
4646
#endif
47+
MetricInstrumentation.SqlClient => Wrappers.AddSqlClientInstrumentation(builder, lazyInstrumentationLoader, pluginManager),
4748
_ => null,
4849
};
4950
}
@@ -115,6 +116,13 @@ public static MeterProviderBuilder AddProcessInstrumentation(MeterProviderBuilde
115116
return builder.AddProcessInstrumentation();
116117
}
117118

119+
[MethodImpl(MethodImplOptions.NoInlining)]
120+
public static MeterProviderBuilder AddSqlClientInstrumentation(MeterProviderBuilder builder, LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager)
121+
{
122+
DelayedInitialization.Metrics.AddSqlClient(lazyInstrumentationLoader, pluginManager);
123+
return builder.AddMeter("OpenTelemetry.Instrumentation.SqlClient");
124+
}
125+
118126
// Exporters
119127

120128
[MethodImpl(MethodImplOptions.NoInlining)]

src/OpenTelemetry.AutoInstrumentation/Configurations/MetricInstrumentation.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ internal enum MetricInstrumentation
3939
/// <summary>
4040
/// ASP.NET Core instrumentation.
4141
/// </summary>
42-
AspNetCore = 6
42+
AspNetCore = 6,
4343
#endif
44+
45+
/// <summary>
46+
/// SqlClient instrumentation.
47+
/// </summary>
48+
SqlClient = 7
4449
}

src/OpenTelemetry.AutoInstrumentation/Instrumentation.cs

+3
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,9 @@ private static void AddLazilyLoadedMetricInstrumentations(LazyInstrumentationLoa
296296
break;
297297
case MetricInstrumentation.NServiceBus:
298298
break;
299+
case MetricInstrumentation.SqlClient:
300+
DelayedInitialization.Metrics.AddSqlClient(lazyInstrumentationLoader, pluginManager);
301+
break;
299302
default:
300303
Logger.Warning($"Configured metric instrumentation type is not supported: {instrumentation}");
301304
if (FailFastSettings.Value.FailFast)
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,12 @@
11
// Copyright The OpenTelemetry Authors
22
// SPDX-License-Identifier: Apache-2.0
33

4-
using System.Reflection;
5-
using OpenTelemetry.AutoInstrumentation.Configurations;
6-
using OpenTelemetry.AutoInstrumentation.Plugins;
7-
84
namespace OpenTelemetry.AutoInstrumentation.Loading.Initializers;
95

10-
internal class SqlClientInitializer
6+
internal abstract class SqlClientInitializer
117
{
12-
private readonly PluginManager _pluginManager;
13-
private readonly TracerSettings _tracerSettings;
14-
15-
private int _initialized;
16-
17-
public SqlClientInitializer(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager, TracerSettings tracerSettings)
8+
protected SqlClientInitializer(LazyInstrumentationLoader lazyInstrumentationLoader)
189
{
19-
_pluginManager = pluginManager;
20-
_tracerSettings = tracerSettings;
2110
lazyInstrumentationLoader.Add(new GenericInitializer("System.Data.SqlClient", InitializeOnFirstCall));
2211
lazyInstrumentationLoader.Add(new GenericInitializer("Microsoft.Data.SqlClient", InitializeOnFirstCall));
2312

@@ -26,30 +15,5 @@ public SqlClientInitializer(LazyInstrumentationLoader lazyInstrumentationLoader,
2615
#endif
2716
}
2817

29-
private void InitializeOnFirstCall(ILifespanManager lifespanManager)
30-
{
31-
if (Interlocked.Exchange(ref _initialized, value: 1) != default)
32-
{
33-
// InitializeOnFirstCall() was already called before
34-
return;
35-
}
36-
37-
var instrumentationType = Type.GetType("OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentation, OpenTelemetry.Instrumentation.SqlClient")!;
38-
39-
var options = new OpenTelemetry.Instrumentation.SqlClient.SqlClientTraceInstrumentationOptions
40-
{
41-
SetDbStatementForText = _tracerSettings.InstrumentationOptions.SqlClientSetDbStatementForText
42-
};
43-
_pluginManager.ConfigureTracesOptions(options);
44-
45-
var propertyInfo = instrumentationType.GetProperty("TracingOptions", BindingFlags.Static | BindingFlags.Public);
46-
propertyInfo?.SetValue(null, options);
47-
48-
var instrumentation = instrumentationType.InvokeMember("AddTracingHandle", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, null, []);
49-
50-
if (instrumentation != null)
51-
{
52-
lifespanManager.Track(instrumentation);
53-
}
54-
}
18+
protected abstract void InitializeOnFirstCall(ILifespanManager lifespanManager);
5519
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using System.Reflection;
5+
using OpenTelemetry.AutoInstrumentation.Plugins;
6+
7+
namespace OpenTelemetry.AutoInstrumentation.Loading.Initializers;
8+
9+
internal sealed class SqlClientMetricsInitializer : SqlClientInitializer
10+
{
11+
private readonly PluginManager _pluginManager;
12+
13+
private int _initialized;
14+
15+
public SqlClientMetricsInitializer(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager)
16+
: base(lazyInstrumentationLoader)
17+
{
18+
_pluginManager = pluginManager;
19+
}
20+
21+
protected override void InitializeOnFirstCall(ILifespanManager lifespanManager)
22+
{
23+
if (Interlocked.Exchange(ref _initialized, value: 1) != default)
24+
{
25+
// InitializeOnFirstCall() was already called before
26+
return;
27+
}
28+
29+
var instrumentationType = Type.GetType("OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentation, OpenTelemetry.Instrumentation.SqlClient")!;
30+
var instrumentation = instrumentationType.InvokeMember("AddMetricHandle", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, null, []);
31+
32+
if (instrumentation != null)
33+
{
34+
lifespanManager.Track(instrumentation);
35+
}
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using System.Reflection;
5+
using OpenTelemetry.AutoInstrumentation.Configurations;
6+
using OpenTelemetry.AutoInstrumentation.Plugins;
7+
8+
namespace OpenTelemetry.AutoInstrumentation.Loading.Initializers;
9+
10+
internal sealed class SqlClientTracerInitializer : SqlClientInitializer
11+
{
12+
private readonly PluginManager _pluginManager;
13+
private readonly TracerSettings _tracerSettings;
14+
15+
private int _initialized;
16+
17+
public SqlClientTracerInitializer(LazyInstrumentationLoader lazyInstrumentationLoader, PluginManager pluginManager, TracerSettings tracerSettings)
18+
: base(lazyInstrumentationLoader)
19+
{
20+
_pluginManager = pluginManager;
21+
_tracerSettings = tracerSettings;
22+
}
23+
24+
protected override void InitializeOnFirstCall(ILifespanManager lifespanManager)
25+
{
26+
if (Interlocked.Exchange(ref _initialized, value: 1) != default)
27+
{
28+
// InitializeOnFirstCall() was already called before
29+
return;
30+
}
31+
32+
var instrumentationType = Type.GetType("OpenTelemetry.Instrumentation.SqlClient.SqlClientInstrumentation, OpenTelemetry.Instrumentation.SqlClient")!;
33+
34+
var options = new OpenTelemetry.Instrumentation.SqlClient.SqlClientTraceInstrumentationOptions
35+
{
36+
SetDbStatementForText = _tracerSettings.InstrumentationOptions.SqlClientSetDbStatementForText
37+
};
38+
_pluginManager.ConfigureTracesOptions(options);
39+
40+
var propertyInfo = instrumentationType.GetProperty("TracingOptions", BindingFlags.Static | BindingFlags.Public);
41+
propertyInfo?.SetValue(null, options);
42+
43+
var instrumentation = instrumentationType.InvokeMember("AddTracingHandle", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, null, []);
44+
45+
if (instrumentation != null)
46+
{
47+
lifespanManager.Track(instrumentation);
48+
}
49+
}
50+
}

0 commit comments

Comments
 (0)