OpenTelemetry.Instrumentation.SqlClient 1.18.0

Prefix Reserved
dotnet add package OpenTelemetry.Instrumentation.SqlClient --version 1.18.0
                    
NuGet\Install-Package OpenTelemetry.Instrumentation.SqlClient -Version 1.18.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="OpenTelemetry.Instrumentation.SqlClient" Version="1.18.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="OpenTelemetry.Instrumentation.SqlClient" Version="1.18.0" />
                    
Directory.Packages.props
<PackageReference Include="OpenTelemetry.Instrumentation.SqlClient" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add OpenTelemetry.Instrumentation.SqlClient --version 1.18.0
                    
#r "nuget: OpenTelemetry.Instrumentation.SqlClient, 1.18.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package OpenTelemetry.Instrumentation.SqlClient@1.18.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=OpenTelemetry.Instrumentation.SqlClient&version=1.18.0
                    
Install as a Cake Addin
#tool nuget:?package=OpenTelemetry.Instrumentation.SqlClient&version=1.18.0
                    
Install as a Cake Tool

SqlClient Instrumentation for OpenTelemetry

Status
Stability Stable
Code Owners @open-telemetry/dotnet-contrib-maintainers

NuGet NuGet codecov.io

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.

Instrumentation is not working with Microsoft.Data.SqlClient v3.* 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.type
  • db.namespace
  • db.operation.name
  • db.query.summary
  • db.query.text
  • db.response.status_code
  • db.stored_procedure.name
  • db.system.name
  • server.address
  • server.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.type
  • db.namespace
  • db.operation.name
  • db.query.summary
  • db.response.status_code
  • db.stored_procedure.name
  • db.system.name
  • server.address
  • server.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

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

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

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

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

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

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.

The attribute is only recorded for commands executed with ExecuteNonQuery() or ExecuteScalar(), including their asynchronous overloads. The connection statistics the value is derived from are only updated as the response from the server is consumed, which for ExecuteReader() and ExecuteXmlReader() 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 TracerProvider has been built, or set StatisticsEnabled to true on such connections yourself.

Trace Context Propagation

Only CommandType.Text commands 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.Text run with the traceparent of 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 overwrites CONTEXT_INFO while 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's traceparent. The reset is deferred until the connection is next used, so an idle pooled connection still reports the previous traceparent in sys.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 the traceparent cleared.
  • Filter does not suppress propagation. It is evaluated after CONTEXT_INFO has been set, so a command excluded from telemetry still writes its traceparent to 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

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 is compatible.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (159)

Showing the top 5 NuGet packages that depend on OpenTelemetry.Instrumentation.SqlClient:

Package 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

Microsoft.ApplicationInsights.WorkerService

Application Insights for .NET Core Worker Service (messaging, background tasks, and any non-HTTP workloads) applications. See https://docs.microsoft.com/azure/azure-monitor/app/worker-service for more information. Privacy statement: https://go.microsoft.com/fwlink/?LinkId=512156

Microsoft.ApplicationInsights.Web

Application Insights for .NET web applications. Privacy statement: https://go.microsoft.com/fwlink/?LinkId=512156

OpenTelemetry.AutoInstrumentation.Runtime.Managed

Managed components used by the OpenTelemetry.AutoInstrumentation project.

Aspire.Microsoft.EntityFrameworkCore.SqlServer

A Microsoft SQL Server provider for Entity Framework Core that integrates with Aspire, including connection pooling, health check, logging, and telemetry.

GitHub repositories (11)

Showing the top 11 popular GitHub repositories that depend on OpenTelemetry.Instrumentation.SqlClient:

Repository Stars
microsoft/aspire
Aspire is the tool for code-first, extensible, observable dev and deploy.
DuendeSoftware/products
The most flexible and standards-compliant OpenID Connect and OAuth 2.x framework for ASP.NET Core
thangchung/clean-architecture-dotnet
🕸 Yet Another .NET Clean Architecture, but for Microservices project. It uses Minimal Clean Architecture with DDD-lite, CQRS-lite, and just enough Cloud-native patterns apply on the simple eCommerce sample and run on Tye with Dapr extension 🍻
CodeMazeBlog/CodeMazeGuides
The main repository for all the Code Maze guides
Aguafrommars/TheIdServer
OpenID/Connect, OAuth2, WS-Federation and SAML 2.0 server based on Duende IdentityServer and ITFoxtec Identity SAML 2.0 with its admin UI
microsoft/ApplicationInsights-dotnet
ApplicationInsights-dotnet
damikun/trouble-training
FullStack DDD/CQRS with GraphQL workshop including distributed tracing and monitoring. This shows the configuration from React frontend to .Net backend.
TanvirArjel/CleanArchitecture
This repository contains the implementation of domain-driven design and clear architecture in ASP.NET Core.
dotnet/systemweb-adapters
Azure/modern-web-app-pattern-dotnet
The Modern Web App Pattern is a set of objectives to help you apply an iterative change to modernize a cloud deployed monolith. This content builds on the Reliable Web App. This repo contains a reference implementation of a Modern Web App for .NET.
marinasundstrom/YourBrand
Prototype enterprise system for e-commerce and consulting services
Version Downloads Last Updated
1.18.0 0 8/21/2026
1.17.0 982,018 7/17/2026
1.16.0 1,375,431 6/24/2026
1.15.2 12,181,581 4/21/2026
1.15.1 2,656,658 3/4/2026
1.15.0 7,228,600 1/28/2026
1.15.0-rc.1 212,568 1/21/2026
1.14.0-rc.1 209,653 1/13/2026
1.14.0-beta.1 2,186,014 11/13/2025
1.13.0-beta.2 288,335 11/3/2025
1.13.0-beta.1 292,359 10/22/2025
1.12.0-beta.3 1,281,335 9/25/2025
1.12.0-beta.2 4,597,787 7/15/2025
1.12.0-beta.1 3,427,436 5/6/2025
1.11.0-beta.2 3,510,132 3/5/2025
1.11.0-beta.1 1,978,633 1/27/2025
1.10.0-beta.1 1,397,552 12/9/2024
1.9.0-beta.1 18,788,256 6/17/2024
1.8.0-beta.1 7,864,707 4/4/2024
1.7.0-beta.1 3,221,678 2/10/2024
Loading failed