Skip to content
Open
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
3 changes: 3 additions & 0 deletions src/OpenTelemetry.Instrumentation.SqlClient/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
* Updated OpenTelemetry core component version(s) to `1.15.1`.
([#4020](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4020))

* Add support for native AoT on .NET 8+.
([#4062](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/4062))

## 1.15.1

Released 2026-Mar-04
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@

#if !NETFRAMEWORK
using System.Data;
using System.Data.Common;
using System.Diagnostics;
#if NET
using System.Diagnostics.CodeAnalysis;
#endif
using System.Globalization;
#if NET
using System.Text;
Expand All @@ -16,9 +15,6 @@

namespace OpenTelemetry.Instrumentation.SqlClient.Implementation;

#if NET
[RequiresUnreferencedCode(SqlClientInstrumentation.SqlClientTrimmingUnsupportedMessage)]
#endif
internal sealed class SqlClientDiagnosticListener : ListenerHandler
{
public const string SqlDataBeforeExecuteCommand = "System.Data.SqlClient.WriteCommandBefore";
Expand All @@ -35,12 +31,7 @@ internal sealed class SqlClientDiagnosticListener : ListenerHandler
private const string SetContextSql = $"set context_info {ContextInfoParameterName}";
#endif

private readonly PropertyFetcher<object> commandFetcher = new("Command");
private readonly PropertyFetcher<object> connectionFetcher = new("Connection");
private readonly PropertyFetcher<string> dataSourceFetcher = new("DataSource");
private readonly PropertyFetcher<string> databaseFetcher = new("Database");
private readonly PropertyFetcher<CommandType> commandTypeFetcher = new("CommandType");
private readonly PropertyFetcher<string> commandTextFetcher = new("CommandText");
private readonly PropertyFetcher<IDbCommand> commandFetcher = new("Command");
private readonly PropertyFetcher<Exception> exceptionFetcher = new("Exception");
private readonly PropertyFetcher<int> exceptionNumberFetcher = new("Number");
private readonly AsyncLocal<long> beginTimestamp = new();
Expand All @@ -67,8 +58,7 @@ public override void OnEventWritten(string name, object? payload)
case SqlDataBeforeExecuteCommand:
case SqlMicrosoftBeforeExecuteCommand:
{
_ = this.commandFetcher.TryFetch(payload, out var command);
if (command == null)
if (!TryFetchCommand(this.commandFetcher, payload, out var command))
{
SqlClientInstrumentationEventSource.Log.NullPayload(nameof(SqlClientDiagnosticListener), name);
return;
Expand All @@ -77,41 +67,40 @@ public override void OnEventWritten(string name, object? payload)
#if NET
// skip if this is an injected query
if (options.EnableTraceContextPropagation &&
command is IDbCommand { CommandType: CommandType.Text, CommandText: SetContextSql })
command.CommandType is CommandType.Text && command.CommandText == SetContextSql)
{
return;
}
#endif

_ = this.connectionFetcher.TryFetch(command, out var connection);
_ = this.databaseFetcher.TryFetch(connection, out var databaseName);
_ = this.dataSourceFetcher.TryFetch(connection, out var dataSource);
var connection = command.Connection;
var databaseName = connection?.Database;
var dataSource = (connection as DbConnection)?.DataSource;

var startTags = SqlTelemetryHelper.GetTagListFromConnectionInfo(dataSource, databaseName, out var activityName);

if (this.commandTypeFetcher.TryFetch(command, out var commandType) &&
this.commandTextFetcher.TryFetch(command, out var commandText))
var commandType = command.CommandType;
var commandText = command.CommandText;

switch (commandType)
{
switch (commandType)
{
case CommandType.StoredProcedure:
DatabaseSemanticConventionHelper.AddTagsForSamplingAndUpdateActivityNameForStoredProcedure(
ref startTags,
commandText,
ref activityName);
break;

case CommandType.Text:
DatabaseSemanticConventionHelper.AddTagsForSamplingAndUpdateActivityNameForQueryText(
ref startTags,
commandText,
ref activityName);
break;

case CommandType.TableDirect:
default:
break;
}
case CommandType.StoredProcedure:
DatabaseSemanticConventionHelper.AddTagsForSamplingAndUpdateActivityNameForStoredProcedure(
ref startTags,
commandText,
ref activityName);
break;

case CommandType.Text:
DatabaseSemanticConventionHelper.AddTagsForSamplingAndUpdateActivityNameForQueryText(
ref startTags,
commandText,
ref activityName);
break;

case CommandType.TableDirect:
default:
break;
}

activity = SqlTelemetryHelper.ActivitySource.StartActivity(
Expand All @@ -129,10 +118,10 @@ public override void OnEventWritten(string name, object? payload)

#if NET
if (options.EnableTraceContextPropagation &&
command is IDbCommand { CommandType: CommandType.Text, Connection.State: ConnectionState.Open } iDbCommand)
command.CommandType is CommandType.Text && connection is { State: ConnectionState.Open })
{
var setContextCommand = iDbCommand.Connection.CreateCommand();
setContextCommand.Transaction = iDbCommand.Transaction;
using var setContextCommand = connection.CreateCommand();
setContextCommand.Transaction = command.Transaction;
setContextCommand.CommandText = SetContextSql;
setContextCommand.CommandType = CommandType.Text;
var parameter = setContextCommand.CreateParameter();
Expand Down Expand Up @@ -189,12 +178,12 @@ public override void OnEventWritten(string name, object? payload)
case SqlDataAfterExecuteCommand:
case SqlMicrosoftAfterExecuteCommand:
{
_ = this.commandFetcher.TryFetch(payload, out var command);
_ = TryFetchCommand(this.commandFetcher, payload, out var command);

#if NET
// skip if this is an injected query
if (options.EnableTraceContextPropagation &&
command is IDbCommand { CommandType: CommandType.Text, CommandText: SetContextSql })
if (options.EnableTraceContextPropagation && command != null &&
command.CommandType is CommandType.Text && command.CommandText == SetContextSql)
{
return;
}
Expand All @@ -221,12 +210,12 @@ public override void OnEventWritten(string name, object? payload)
case SqlDataWriteCommandError:
case SqlMicrosoftWriteCommandError:
{
_ = this.commandFetcher.TryFetch(payload, out var command);
_ = TryFetchCommand(this.commandFetcher, payload, out var command);

#if NET
// skip if this is an injected query
if (options.EnableTraceContextPropagation &&
command is IDbCommand { CommandType: CommandType.Text, CommandText: SetContextSql })
if (options.EnableTraceContextPropagation && command != null &&
command.CommandType is CommandType.Text && command.CommandText == SetContextSql)
{
return;
}
Expand All @@ -249,11 +238,11 @@ public override void OnEventWritten(string name, object? payload)
{
if (activity.IsAllDataRequested)
{
if (this.exceptionFetcher.TryFetch(payload, out var exception) && exception != null)
if (TryFetchException(this.exceptionFetcher, payload, out var exception))
{
activity.AddTag(SemanticConventions.AttributeErrorType, exception.GetType().FullName);

if (this.exceptionNumberFetcher.TryFetch(exception, out var exceptionNumber))
if (TryFetchExceptionNumber(this.exceptionNumberFetcher, exception, out var exceptionNumber))
{
activity.AddTag(SemanticConventions.AttributeDbResponseStatusCode, exceptionNumber.ToString(CultureInfo.InvariantCulture));
}
Expand Down Expand Up @@ -284,6 +273,33 @@ public override void OnEventWritten(string name, object? payload)
}
}

#if NET
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Client application usage will ensure that core types from usage are preserved.")]
#endif
private static bool TryFetchCommand(
PropertyFetcher<IDbCommand> fetcher,
object? payload,
[NotNullWhen(true)] out IDbCommand? command)
=> fetcher.TryFetch(payload, out command);

#if NET
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Client application usage will ensure that core types from usage are preserved.")]
#endif
private static bool TryFetchException(
PropertyFetcher<Exception> fetcher,
object? payload,
[NotNullWhen(true)] out Exception? exception)
=> fetcher.TryFetch(payload, out exception);

#if NET
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Client application usage will ensure that core types from usage are preserved.")]
#endif
private static bool TryFetchExceptionNumber(
PropertyFetcher<int> fetcher,
Exception exception,
out int number)
=> fetcher.TryFetch(exception, out number);

private void RecordDuration(Activity? activity, object? payload, bool hasError = false)
{
if (SqlClientInstrumentation.Instance.HandleManager.MetricHandles == 0)
Expand All @@ -306,11 +322,11 @@ private void RecordDuration(Activity? activity, object? payload, bool hasError =
}
else if (payload != null)
{
if (this.commandFetcher.TryFetch(payload, out var command) && command != null &&
this.connectionFetcher.TryFetch(command, out var connection))
if (TryFetchCommand(this.commandFetcher, payload, out var command))
{
this.databaseFetcher.TryFetch(connection, out var databaseName);
this.dataSourceFetcher.TryFetch(connection, out var dataSource);
var connection = command.Connection;
var databaseName = connection?.Database;
var dataSource = (connection as DbConnection)?.DataSource;

var connectionTags = SqlTelemetryHelper.GetTagListFromConnectionInfo(
dataSource,
Expand All @@ -322,23 +338,19 @@ private void RecordDuration(Activity? activity, object? payload, bool hasError =
tags.Add(tag.Key, tag.Value);
}

if (this.commandTypeFetcher.TryFetch(command, out var commandType) &&
commandType == CommandType.StoredProcedure)
if (command.CommandType is CommandType.StoredProcedure)
{
if (this.commandTextFetcher.TryFetch(command, out var commandText))
{
tags.Add(SemanticConventions.AttributeDbStoredProcedureName, commandText);
}
tags.Add(SemanticConventions.AttributeDbStoredProcedureName, command.CommandText);
}
}

if (hasError)
{
if (this.exceptionFetcher.TryFetch(payload, out var exception) && exception != null)
if (TryFetchException(this.exceptionFetcher, payload, out var exception))
{
tags.Add(SemanticConventions.AttributeErrorType, exception.GetType().FullName);

if (this.exceptionNumberFetcher.TryFetch(exception, out var exceptionNumber))
if (TryFetchExceptionNumber(this.exceptionNumberFetcher, exception, out var exceptionNumber))
{
tags.Add(SemanticConventions.AttributeDbResponseStatusCode, exceptionNumber.ToString(CultureInfo.InvariantCulture));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
<PackageValidationBaselineVersion>1.15.1</PackageValidationBaselineVersion>
</PropertyGroup>

<!-- We cannot support native AoT yet, but we can enable the trim analyzer -->
<PropertyGroup Condition="'$([MSBuild]::GetTargetFrameworkIdentifier(`$(TargetFramework)`))' == '.NETCoreApp'">
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
<IsAotCompatible>false</IsAotCompatible>
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,20 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#if NET
using System.Diagnostics.CodeAnalysis;
#endif
using OpenTelemetry.Instrumentation.SqlClient.Implementation;

namespace OpenTelemetry.Instrumentation.SqlClient;

/// <summary>
/// SqlClient instrumentation.
/// </summary>
#if NET
[RequiresUnreferencedCode(SqlClientTrimmingUnsupportedMessage)]
#endif
internal sealed class SqlClientInstrumentation : IDisposable
{
public static readonly SqlClientInstrumentation Instance = new();

public readonly InstrumentationHandleManager HandleManager = new();

internal const string SqlClientDiagnosticListenerName = "SqlClientDiagnosticListener";
#if NET
internal const string SqlClientTrimmingUnsupportedMessage = "Trimming is not yet supported with SqlClient instrumentation.";
#endif
#if NETFRAMEWORK
private readonly SqlEventSourceListener sqlEventSourceListener;
#else
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#if NET
using System.Diagnostics.CodeAnalysis;
#endif
using OpenTelemetry.Instrumentation.SqlClient;
using OpenTelemetry.Instrumentation.SqlClient.Implementation;
using OpenTelemetry.Internal;
Expand All @@ -20,9 +17,6 @@ public static class SqlClientMeterProviderBuilderExtensions
/// </summary>
/// <param name="builder"><see cref="MeterProviderBuilder"/> being configured.</param>
/// <returns>The instance of <see cref="MeterProviderBuilder"/> to chain the calls.</returns>
#if NET
[RequiresUnreferencedCode(SqlClientInstrumentation.SqlClientTrimmingUnsupportedMessage)]
#endif
public static MeterProviderBuilder AddSqlClientInstrumentation(this MeterProviderBuilder builder)
{
Guard.ThrowIfNull(builder);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#if NET
using System.Diagnostics.CodeAnalysis;
#endif
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using OpenTelemetry.Instrumentation.SqlClient;
Expand All @@ -22,9 +19,6 @@ public static class TracerProviderBuilderExtensions
/// </summary>
/// <param name="builder"><see cref="TracerProviderBuilder"/> being configured.</param>
/// <returns>The instance of <see cref="TracerProviderBuilder"/> to chain the calls.</returns>
#if NET
[RequiresUnreferencedCode(SqlClientInstrumentation.SqlClientTrimmingUnsupportedMessage)]
#endif
public static TracerProviderBuilder AddSqlClientInstrumentation(this TracerProviderBuilder builder)
=> AddSqlClientInstrumentation(builder, name: null, configureSqlClientTraceInstrumentationOptions: null);

Expand All @@ -34,9 +28,6 @@ public static TracerProviderBuilder AddSqlClientInstrumentation(this TracerProvi
/// <param name="builder"><see cref="TracerProviderBuilder"/> being configured.</param>
/// <param name="configureSqlClientTraceInstrumentationOptions">Callback action for configuring <see cref="SqlClientTraceInstrumentationOptions"/>.</param>
/// <returns>The instance of <see cref="TracerProviderBuilder"/> to chain the calls.</returns>
#if NET
[RequiresUnreferencedCode(SqlClientInstrumentation.SqlClientTrimmingUnsupportedMessage)]
#endif
public static TracerProviderBuilder AddSqlClientInstrumentation(
this TracerProviderBuilder builder,
Action<SqlClientTraceInstrumentationOptions> configureSqlClientTraceInstrumentationOptions)
Expand All @@ -49,9 +40,6 @@ public static TracerProviderBuilder AddSqlClientInstrumentation(
/// <param name="name">Name which is used when retrieving options.</param>
/// <param name="configureSqlClientTraceInstrumentationOptions">Callback action for configuring <see cref="SqlClientTraceInstrumentationOptions"/>.</param>
/// <returns>The instance of <see cref="TracerProviderBuilder"/> to chain the calls.</returns>
#if NET
[RequiresUnreferencedCode(SqlClientInstrumentation.SqlClientTrimmingUnsupportedMessage)]
#endif
public static TracerProviderBuilder AddSqlClientInstrumentation(
this TracerProviderBuilder builder,
string? name,
Expand Down
Loading