OpenTelemetry.Instrumentation.SqlClient 1.18.0
SqlClient Instrumentation for OpenTelemetry
| Status | |
|---|---|
| Stability | Stable |
| Code Owners | @open-telemetry/dotnet-contrib-maintainers |
This is an Instrumentation Library, which instruments Microsoft.Data.SqlClient and System.Data.SqlClient and collects traces about database operations.
This component is based on v1.44 of database semantic conventions. For details on the default set of attributes that are added, check out the Traces and Metrics sections below.
[!WARNING] Instrumentation is not working with
Microsoft.Data.SqlClientv3.* due to the issue. It was fixed in 4.0 and later.
Steps to enable OpenTelemetry.Instrumentation.SqlClient
Step 1: Install Package
Add a reference to the
OpenTelemetry.Instrumentation.SqlClient
package. Also, add any other instrumentations & exporters you will need.
dotnet add package OpenTelemetry.Instrumentation.SqlClient
Step 2: Enable SqlClient Instrumentation at application startup
SqlClient instrumentation must be enabled at application startup.
Traces
The following example demonstrates adding SqlClient traces instrumentation
to a console application. This example also sets up the OpenTelemetry Console
exporter, which requires adding the package
OpenTelemetry.Exporter.Console
to the application.
using OpenTelemetry.Trace;
public class Program
{
public static void Main(string[] args)
{
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSqlClientInstrumentation()
.AddConsoleExporter()
.Build();
}
}
The instrumentation adheres to the semantic conventions for database client spans. An activity emitted by the instrumentation will include the following list of attributes:
error.typedb.namespacedb.operation.namedb.query.summarydb.query.textdb.response.status_codedb.stored_procedure.namedb.system.nameserver.addressserver.port
Metrics
The following example demonstrates adding SqlClient metrics instrumentation
to a console application. This example also sets up the OpenTelemetry Console
exporter, which requires adding the package
OpenTelemetry.Exporter.Console
to the application.
using OpenTelemetry.Metrics;
public class Program
{
public static void Main(string[] args)
{
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddSqlClientInstrumentation()
.AddConsoleExporter()
.Build();
}
}
The instrumentation adheres to the semantic conventions for database client metrics.
Currently, the instrumentation supports the following metric and attributes.
| Name | Instrument Type | Unit | Description |
|---|---|---|---|
db.client.operation.duration |
Histogram | s |
Duration of database client operations. |
error.typedb.namespacedb.operation.namedb.query.summarydb.response.status_codedb.stored_procedure.namedb.system.nameserver.addressserver.port
ASP.NET Core
For an ASP.NET Core application, adding instrumentation is typically done in the
ConfigureServices of your Startup class. Refer to documentation for
OpenTelemetry.Instrumentation.AspNetCore.
ASP.NET
For an ASP.NET application, adding instrumentation is typically done in the
Global.asax.cs. Refer to the documentation for
OpenTelemetry.Instrumentation.AspNet.
Advanced configuration
This instrumentation can be configured to change the default behavior by using
SqlClientTraceInstrumentationOptions.
EnrichWithSqlCommand
[!NOTE] EnrichWithSqlCommand is available on .NET runtimes only.
This option can be used to enrich the activity with additional information from
the raw SqlCommand object. The EnrichWithSqlCommand action is called only
when activity.IsAllDataRequested is true. It contains the activity itself
(which can be enriched), the name of the event, and the actual raw object.
Currently there is only one event name reported, "OnCustom". The actual object
is Microsoft.Data.SqlClient.SqlCommand for Microsoft.Data.SqlClient and
System.Data.SqlClient.SqlCommand for System.Data.SqlClient.
The following code snippet shows how to add additional tags using
EnrichWithSqlCommand.
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSqlClientInstrumentation(opt => opt.EnrichWithSqlCommand
= (activity, obj) =>
{
if (obj is SqlCommand cmd)
{
activity.SetTag("db.commandTimeout", cmd.CommandTimeout);
}
})
.Build();
Processor,
is the general extensibility point to add additional properties to any activity.
The EnrichWithSqlCommand option is specific to this instrumentation, and is
provided to get access to SqlCommand object.
RecordException
[!NOTE] RecordException is available on .NET runtimes only.
This option can be set to instruct the instrumentation to record SqlExceptions as Activity events.
The default value is false and can be changed by the code like below.
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSqlClientInstrumentation(
options => options.RecordException = true)
.AddConsoleExporter()
.Build();
Filter
[!NOTE] Filter is available on .NET runtimes only.
This option can be used to filter out activities based on the properties of the
SqlCommand object being instrumented using a Func<object, bool>. The
function receives an instance of the raw SqlCommand and should return true
if the telemetry is to be collected, and false if it should not. The parameter
of the Func delegate is of type object and needs to be cast to the appropriate
type of SqlCommand, either Microsoft.Data.SqlClient.SqlCommand or
System.Data.SqlClient.SqlCommand. The example below filters out all commands
that are not stored procedures.
using var traceProvider = Sdk.CreateTracerProviderBuilder()
.AddSqlClientInstrumentation(
opt =>
{
opt.Filter = cmd =>
{
if (cmd is SqlCommand command)
{
return command.CommandType == CommandType.StoredProcedure;
}
return false;
};
})
.AddConsoleExporter()
.Build();
Experimental features
[!NOTE] Experimental features are not enabled by default and can only be activated with environment variables. They are subject to change or removal in future releases.
DB query parameters
[!NOTE] This feature is available on .NET runtimes only.
The OTEL_DOTNET_EXPERIMENTAL_SQLCLIENT_ENABLE_TRACE_DB_QUERY_PARAMETERS environment
variable controls whether db.query.parameter.<key> attributes are emitted.
Query parameters may contain sensitive data, so only enable this experimental feature if your queries and/or environment are appropriate for enabling this option.
OTEL_DOTNET_EXPERIMENTAL_SQLCLIENT_ENABLE_TRACE_DB_QUERY_PARAMETERS is implicitly
false by default. When set to true, the instrumentation will set
db.query.parameter.<key>
attributes for each of the query parameters associated with a database command.
Returned rows
[!NOTE] This feature is available on .NET runtimes only.
The OTEL_DOTNET_EXPERIMENTAL_SQLCLIENT_ENABLE_RECORD_RETURNED_ROWS environment
variable controls whether the
db.response.returned_rows
attribute is emitted.
OTEL_DOTNET_EXPERIMENTAL_SQLCLIENT_ENABLE_RECORD_RETURNED_ROWS is implicitly
false by default. When set to true, the instrumentation records the number
of rows the command returned, derived from the SqlClient connection statistics
that are collected automatically while the instrumentation is enabled.
[!NOTE] The attribute is only recorded for commands executed with
ExecuteNonQuery()orExecuteScalar(), including their asynchronous overloads. The connection statistics the value is derived from are only updated as the response from the server is consumed, which forExecuteReader()andExecuteXmlReader()happens after the command has finished executing and the span has already ended. No attribute is emitted for those commands, rather than one whose value does not describe the rows the command returned.SqlClient only starts collecting the statistics that the value is derived from when a connection is opened, so a connection which was already open before the instrumentation was registered does not report a value. Either open connections after the
TracerProviderhas been built, or setStatisticsEnabledtotrueon such connections yourself.
Trace Context Propagation
[!NOTE] Only
CommandType.Textcommands are supported for trace context propagation. Only .NET runtimes are supported.Other command types do not get their own trace context. They observe whatever was last set on the connection. See below.
Database trace context propagation can be enabled by setting
OTEL_DOTNET_EXPERIMENTAL_SQLCLIENT_ENABLE_TRACE_CONTEXT_PROPAGATION
environment variable to true.
This uses the SET CONTEXT_INFO
command to set traceparent
information for the current connection, which results in
an additional round-trip to the database.
CONTEXT_INFO is session state. It is scoped to the connection rather than to
the command that set it, and the instrumentation only ever overwrites it, never
clears it. This has a few consequences worth understanding before enabling the
feature.
- Commands other than
CommandType.Textrun with thetraceparentof the most recent text command on the same connection, if any, which may belong to an unrelated trace. A stored procedure is therefore not merely missing its own trace context, it can be attributed server-side to a different one. - With
MultipleActiveResultSets=true, a command interleaved on the same connection overwritesCONTEXT_INFOwhile an earlier reader is still streaming, so the still-running query is re-attributed server-side to the trace of the interleaved command. - Connection pooling does not carry the value across connections. A pooled
connection is reset before it is reused, and that reset clears
CONTEXT_INFO, so the first command on the reused connection does not observe the previous one'straceparent. The reset is deferred until the connection is next used, so an idle pooled connection still reports the previoustraceparentinsys.dm_exec_sessions. - The additional round-trip is paid for nearly every text command, not only for
the sampled ones. A command whose span is dropped by the sampler generally
still sets
CONTEXT_INFO, with the sampled flag of thetraceparentcleared. Filterdoes not suppress propagation. It is evaluated afterCONTEXT_INFOhas been set, so a command excluded from telemetry still writes itstraceparentto the database, where it refers to a span that is never exported.
Activity Duration calculation
Activity.Duration represents the time the underlying connection takes to
execute the command/query. Completing the operation includes the time up to
determining that the request was successful. It doesn't include the time spent
reading the results from a query set (for example enumerating all the rows
returned by a data reader).
This is illustrated by the code snippet below:
using var connection = new SqlConnection("...");
connection.Open();
using var command = connection.CreateCommand();
command.CommandText = "select top 100000 * from Users";
// Activity duration starts
using var reader = command.ExecuteReader();
// Activity duration ends
// Not included in the Activity duration
while (reader.Read())
{
}
References
Showing the top 20 packages that depend on OpenTelemetry.Instrumentation.SqlClient.
| Packages | Downloads |
|---|---|
|
Microsoft.ApplicationInsights.AspNetCore
Application Insights for ASP.NET Core web applications. See https://azure.microsoft.com/documentation/articles/app-insights-asp-net-five/ for more information. Privacy statement: https://go.microsoft.com/fwlink/?LinkId=512156
|
7 |
|
Microsoft.ApplicationInsights.AspNetCore
Application Insights for ASP.NET Core web applications. See https://azure.microsoft.com/documentation/articles/app-insights-asp-net-five/ for more information. Privacy statement: https://go.microsoft.com/fwlink/?LinkId=512156
|
5 |
|
Microsoft.ApplicationInsights.AspNetCore
Application Insights for ASP.NET Core web applications. See https://azure.microsoft.com/documentation/articles/app-insights-asp-net-five/ for more information. Privacy statement: https://go.microsoft.com/fwlink/?LinkId=512156
|
4 |
.NET 10.0
- Microsoft.Extensions.Configuration (>= 10.0.0)
- OpenTelemetry.Api.ProviderBuilderExtensions (>= 1.18.0 && < 2.0.0)
- Microsoft.Extensions.Options (>= 10.0.0)
.NET Standard 2.0
- OpenTelemetry.Api.ProviderBuilderExtensions (>= 1.18.0 && < 2.0.0)
- Microsoft.Extensions.Options (>= 10.0.0)
- Microsoft.Extensions.Configuration (>= 10.0.0)
.NET 8.0
- Microsoft.Extensions.Options (>= 8.0.0)
- Microsoft.Extensions.Configuration (>= 8.0.0)
- OpenTelemetry.Api.ProviderBuilderExtensions (>= 1.18.0 && < 2.0.0)
.NET Framework 4.6.2
- Microsoft.Extensions.Options (>= 10.0.0)
- Microsoft.Extensions.Configuration (>= 10.0.0)
- OpenTelemetry.Api.ProviderBuilderExtensions (>= 1.18.0 && < 2.0.0)
| Version | Downloads | Last updated |
|---|---|---|
| 1.18.0 | 1 | 24.08.2026 |
| 1.17.0 | 0 | 17.07.2026 |
| 1.16.0 | 3 | 03.07.2026 |
| 1.15.2 | 4 | 28.04.2026 |
| 1.15.1 | 5 | 11.03.2026 |
| 1.15.0 | 4 | 21.02.2026 |
| 1.15.0-rc.1 | 5 | 21.02.2026 |
| 1.14.0-rc.1 | 5 | 15.01.2026 |
| 1.14.0-beta.1 | 6 | 10.12.2025 |
| 1.13.0-beta.2 | 6 | 10.12.2025 |
| 1.13.0-beta.1 | 6 | 10.12.2025 |
| 1.12.0-beta.3 | 4 | 12.12.2025 |
| 1.12.0-beta.2 | 5 | 10.12.2025 |
| 1.12.0-beta.1 | 6 | 10.12.2025 |
| 1.11.0-beta.2 | 6 | 10.12.2025 |
| 1.11.0-beta.1 | 5 | 10.12.2025 |
| 1.10.0-beta.1 | 7 | 10.12.2025 |
| 1.9.0-beta.1 | 5 | 10.12.2025 |
| 1.8.0-beta.1 | 5 | 10.12.2025 |
| 1.7.0-beta.1 | 6 | 10.12.2025 |
| 1.6.0-beta.3 | 6 | 10.12.2025 |
| 1.6.0-beta.2 | 6 | 10.12.2025 |
| 1.5.1-beta.1 | 5 | 10.12.2025 |
| 1.5.0-beta.1 | 5 | 10.12.2025 |
| 1.0.0-rc9.14 | 5 | 10.12.2025 |
| 1.0.0-rc9.13 | 5 | 10.12.2025 |
| 1.0.0-rc9.12 | 5 | 10.12.2025 |
| 1.0.0-rc9.11 | 5 | 10.12.2025 |
| 1.0.0-rc9.10 | 6 | 10.12.2025 |
| 1.0.0-rc9.9 | 7 | 10.12.2025 |
| 1.0.0-rc9.8 | 6 | 10.12.2025 |
| 1.0.0-rc9.7 | 6 | 10.12.2025 |
| 1.0.0-rc9.6 | 5 | 10.12.2025 |
| 1.0.0-rc9.5 | 5 | 10.12.2025 |
| 1.0.0-rc9.4 | 5 | 10.12.2025 |
| 1.0.0-rc9.3 | 5 | 10.12.2025 |
| 1.0.0-rc9.2 | 6 | 10.12.2025 |
| 1.0.0-rc9.1 | 6 | 10.12.2025 |
| 1.0.0-rc9 | 5 | 11.12.2025 |
| 1.0.0-rc8 | 6 | 10.12.2025 |
| 1.0.0-rc7 | 6 | 10.12.2025 |
| 1.0.0-rc6 | 6 | 10.12.2025 |
| 1.0.0-rc5 | 6 | 10.12.2025 |
| 1.0.0-rc4 | 5 | 10.12.2025 |
| 1.0.0-rc3 | 6 | 10.12.2025 |
| 1.0.0-rc2 | 5 | 10.12.2025 |
| 1.0.0-rc10 | 5 | 11.12.2025 |
| 1.0.0-rc1.1 | 6 | 10.12.2025 |
| 0.8.0-beta.1 | 6 | 10.12.2025 |
| 0.7.0-beta.1 | 5 | 10.12.2025 |
| 0.6.0-beta.1 | 6 | 10.12.2025 |
| 0.5.0-beta.2 | 5 | 10.12.2025 |
| 0.4.0-beta.2 | 5 | 10.12.2025 |
| 0.3.0-beta.1 | 6 | 10.12.2025 |