88using System . Diagnostics . CodeAnalysis ;
99#endif
1010using System . Globalization ;
11+ using System . Text ;
1112using OpenTelemetry . Trace ;
1213
1314namespace OpenTelemetry . Instrumentation . SqlClient . Implementation ;
@@ -26,6 +27,9 @@ internal sealed class SqlClientDiagnosticListener : ListenerHandler
2627 public const string SqlDataWriteCommandError = "System.Data.SqlClient.WriteCommandError" ;
2728 public const string SqlMicrosoftWriteCommandError = "Microsoft.Data.SqlClient.WriteCommandError" ;
2829
30+ private const string ContextInfoParameterName = "@opentelemetry_traceparent" ;
31+ private const string SetContextSql = $ "set context_info { ContextInfoParameterName } ";
32+
2933 private readonly PropertyFetcher < object > commandFetcher = new ( "Command" ) ;
3034 private readonly PropertyFetcher < object > connectionFetcher = new ( "Connection" ) ;
3135 private readonly PropertyFetcher < string > dataSourceFetcher = new ( "DataSource" ) ;
@@ -64,6 +68,13 @@ public override void OnEventWritten(string name, object? payload)
6468 return ;
6569 }
6670
71+ // skip if this is an injected query
72+ if ( options . ContextPropagationLevel == SqlClientTraceInstrumentationOptions . ContextPropagationLevelTrace &&
73+ command is IDbCommand { CommandType : CommandType . Text , CommandText : SetContextSql } )
74+ {
75+ return ;
76+ }
77+
6778 _ = this . connectionFetcher . TryFetch ( command , out var connection ) ;
6879 _ = this . databaseFetcher . TryFetch ( connection , out var databaseName ) ;
6980 _ = this . dataSourceFetcher . TryFetch ( connection , out var dataSource ) ;
@@ -82,6 +93,25 @@ public override void OnEventWritten(string name, object? payload)
8293 return ;
8394 }
8495
96+ if ( options . ContextPropagationLevel == SqlClientTraceInstrumentationOptions . ContextPropagationLevelTrace &&
97+ command is IDbCommand { CommandType : CommandType . Text , Connection . State : ConnectionState . Open } iDbCommand )
98+ {
99+ var setContextCommand = iDbCommand . Connection . CreateCommand ( ) ;
100+ setContextCommand . CommandText = SetContextSql ;
101+ setContextCommand . CommandType = CommandType . Text ;
102+ var parameter = setContextCommand . CreateParameter ( ) ;
103+ parameter . ParameterName = ContextInfoParameterName ;
104+
105+ var tracedflags = ( activity . ActivityTraceFlags & ActivityTraceFlags . Recorded ) != 0 ? "01" : "00" ;
106+ var traceparent = $ "00-{ activity . TraceId . ToHexString ( ) } -{ activity . SpanId . ToHexString ( ) } -{ tracedflags } ";
107+
108+ parameter . DbType = DbType . Binary ;
109+ parameter . Value = Encoding . UTF8 . GetBytes ( traceparent ) ;
110+ setContextCommand . Parameters . Add ( parameter ) ;
111+
112+ setContextCommand . ExecuteNonQuery ( ) ;
113+ }
114+
85115 if ( activity . IsAllDataRequested )
86116 {
87117 try
@@ -168,6 +198,15 @@ public override void OnEventWritten(string name, object? payload)
168198 case SqlDataAfterExecuteCommand :
169199 case SqlMicrosoftAfterExecuteCommand :
170200 {
201+ _ = this . commandFetcher . TryFetch ( payload , out var command ) ;
202+
203+ // skip if this is an injected query
204+ if ( options . ContextPropagationLevel == SqlClientTraceInstrumentationOptions . ContextPropagationLevelTrace &&
205+ command is IDbCommand { CommandType : CommandType . Text , CommandText : SetContextSql } )
206+ {
207+ return ;
208+ }
209+
171210 if ( activity == null )
172211 {
173212 SqlClientInstrumentationEventSource . Log . NullActivity ( name ) ;
@@ -189,6 +228,15 @@ public override void OnEventWritten(string name, object? payload)
189228 case SqlDataWriteCommandError :
190229 case SqlMicrosoftWriteCommandError :
191230 {
231+ _ = this . commandFetcher . TryFetch ( payload , out var command ) ;
232+
233+ // skip if this is an injected query
234+ if ( options . ContextPropagationLevel == SqlClientTraceInstrumentationOptions . ContextPropagationLevelTrace &&
235+ command is IDbCommand { CommandType : CommandType . Text , CommandText : SetContextSql } )
236+ {
237+ return ;
238+ }
239+
192240 if ( activity == null )
193241 {
194242 SqlClientInstrumentationEventSource . Log . NullActivity ( name ) ;
0 commit comments