This is an Instrumentation Library, which instruments Microsoft.Data.SqlClient and System.Data.SqlClient and collects traces about database operations.
Warning
Instrumentation is not working with Microsoft.Data.SqlClient
v3.* due to
the issue. It was fixed in 4.0
and later.
Caution
This component is based on the OpenTelemetry semantic conventions for traces. These conventions are Experimental, and hence, this package is a pre-release. Until a stable version is released, there can be breaking changes. You can track the progress from milestones.
Add a reference to the
OpenTelemetry.Instrumentation.SqlClient
package. Also, add any other instrumentations & exporters you will need.
dotnet add package --prerelease OpenTelemetry.Instrumentation.SqlClient
SqlClient instrumentation must be enabled at application startup.
The following example demonstrates adding SqlClient 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();
}
}
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.
For an ASP.NET application, adding instrumentation is typically done in the
Global.asax.cs
. Refer to the documentation for
OpenTelemetry.Instrumentation.AspNet.
This instrumentation can be configured to change the default behavior by using
SqlClientTraceInstrumentationOptions
.
The SqlClientTraceInstrumentationOptions
class exposes two properties that can
be used to configure how the
db.statement
attribute is captured upon execution of a query but the behavior depends on the
runtime used.
On .NET and .NET Core, two properties are available:
SetDbStatementForStoredProcedure
and SetDbStatementForText
. These properties
control capturing of CommandType.StoredProcedure
and CommandType.Text
respectively.
SetDbStatementForStoredProcedure
is true by default and will set
db.statement
attribute to the stored procedure command name.
SetDbStatementForText
is false by default (to prevent accidental capture of
sensitive data that might be part of the SQL statement text). When set to
true
, the instrumentation will set
db.statement
attribute to the text of the SQL command being executed.
To disable capturing stored procedure commands use configuration like below.
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSqlClientInstrumentation(
options => options.SetDbStatementForStoredProcedure = false)
.AddConsoleExporter()
.Build();
To enable capturing of sqlCommand.CommandText
for CommandType.Text
use the
following configuration.
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSqlClientInstrumentation(
options => options.SetDbStatementForText = true)
.AddConsoleExporter()
.Build();
On .NET Framework, the SetDbStatementForText
property controls whether or not
this instrumentation will set the
db.statement
attribute to the text of the SqlCommand
being executed. This could either be
the name of a stored procedure (when CommandType.StoredProcedure
is used) or
the full text of a CommandType.Text
query. SetDbStatementForStoredProcedure
is ignored because on .NET Framework there is no way to determine the type of
command being executed.
Since CommandType.Text
might contain sensitive data, all SQL capturing is
disabled by default to protect against accidentally sending full query text to
a telemetry backend. If you are only using stored procedures or have no
sensitive data in your sqlCommand.CommandText
, you can enable SQL capturing
using the options like below:
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSqlClientInstrumentation(
options => options.SetDbStatementForText = true)
.AddConsoleExporter()
.Build();
Note
When using the built-in System.Data.SqlClient
only stored procedure
command names will ever be captured. When using the Microsoft.Data.SqlClient
NuGet package (v1.1+) stored procedure command names, full query text, and other
command text will be captured.
Note
EnableConnectionLevelAttributes is supported on all runtimes.
By default, EnabledConnectionLevelAttributes
is disabled and this
instrumentation sets the peer.service
attribute to the
DataSource
property of the connection. If EnabledConnectionLevelAttributes
is enabled,
the DataSource
will be parsed and the server name will be sent as the
net.peer.name
or net.peer.ip
attribute, the instance name will be sent as
the db.mssql.instance_name
attribute, and the port will be sent as the
net.peer.port
attribute if it is not 1433 (the default port).
The following example shows how to use EnableConnectionLevelAttributes
.
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSqlClientInstrumentation(
options => options.EnableConnectionLevelAttributes = true)
.AddConsoleExporter()
.Build();
Note
Enrich is supported on .NET and .NET Core runtimes only.
This option can be used to enrich the activity with additional information from
the raw SqlCommand
object. The Enrich
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 Enrich
.
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSqlClientInstrumentation(opt => opt.Enrich
= (activity, eventName, rawObject) =>
{
if (eventName.Equals("OnCustom"))
{
if (rawObject is SqlCommand cmd)
{
activity.SetTag("db.commandTimeout", cmd.CommandTimeout);
}
};
})
.Build();
Processor, is the
general extensibility point to add additional properties to any activity. The
Enrich
option is specific to this instrumentation, and is provided to get
access to SqlCommand
object.
Note
RecordException is supported on .NET and .NET Core 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();
Note
Filter is supported on .NET and .NET Core 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();
{