Skip to content

Commit a48ff18

Browse files
Added instrumentation for netfx SqlClient. (#761)
* Added instrumentation for netfx SqlClient. * Code review. * Send "db.statement_type" instead of "db.statementType". * Added integration tests for SqlEventSource. * Adding .github folder to solution. * Added a couple missing files into the solution. * Added FakeSqlEventSource tests. * Fixed up GrpcClientDiagnosticListener for EventSource changes. * Removed extra ActivityListener from unit tests. Co-authored-by: Cijo Thomas <[email protected]>
1 parent cdf0cbe commit a48ff18

File tree

17 files changed

+565
-68
lines changed

17 files changed

+565
-68
lines changed

OpenTelemetry.sln

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,38 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentati
101101
EndProject
102102
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests", "test\OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests\OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests.csproj", "{7C4026CA-6434-4762-8B77-D657EAEE1325}"
103103
EndProject
104+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{F1D0972B-38CF-49C2-9F4B-4C5DE02FB71D}"
105+
ProjectSection(SolutionItems) = preProject
106+
.github\CODEOWNERS = .github\CODEOWNERS
107+
.github\PULL_REQUEST_TEMPLATE.md = .github\PULL_REQUEST_TEMPLATE.md
108+
EndProjectSection
109+
EndProject
110+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEMPLATE", "{A533C800-3DC3-4D04-90A7-0CE7A1E6BDB3}"
111+
ProjectSection(SolutionItems) = preProject
112+
.github\ISSUE_TEMPLATE\bug_report.md = .github\ISSUE_TEMPLATE\bug_report.md
113+
.github\ISSUE_TEMPLATE\feature_request.md = .github\ISSUE_TEMPLATE\feature_request.md
114+
.github\ISSUE_TEMPLATE\question.md = .github\ISSUE_TEMPLATE\question.md
115+
EndProjectSection
116+
EndProject
117+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{E69578EB-B456-4062-A645-877CD964528B}"
118+
ProjectSection(SolutionItems) = preProject
119+
.github\workflows\dotnet-core-linux.yml = .github\workflows\dotnet-core-linux.yml
120+
.github\workflows\dotnet-core-win.yml = .github\workflows\dotnet-core-win.yml
121+
.github\workflows\dotnet-core.yml = .github\workflows\dotnet-core.yml
122+
EndProjectSection
123+
EndProject
124+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C1542297-8763-4DF4-957C-489ED771C21D}"
125+
ProjectSection(SolutionItems) = preProject
126+
src\Directory.Build.props = src\Directory.Build.props
127+
src\Directory.Build.targets = src\Directory.Build.targets
128+
EndProjectSection
129+
EndProject
130+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{D2E73927-5966-445C-94E9-EFE6F269C8D5}"
131+
ProjectSection(SolutionItems) = preProject
132+
test\Directory.Build.props = test\Directory.Build.props
133+
test\Directory.Build.targets = test\Directory.Build.targets
134+
EndProjectSection
135+
EndProject
104136
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.GrpcClient.Tests", "test\OpenTelemetry.Instrumentation.GrpcClient.Tests\OpenTelemetry.Instrumentation.GrpcClient.Tests.csproj", "{305E9DFD-E73B-4A28-8769-795C25551020}"
105137
EndProject
106138
Global
@@ -243,6 +275,10 @@ Global
243275
{47318988-CA8B-4C81-B55D-2FA11D295A49} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E}
244276
{25C06046-C7D0-46B4-AAAC-90C50C43DE7A} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E}
245277
{9A4E3A68-904B-4835-A3C8-F664B73098DB} = {E359BB2B-9AEC-497D-B321-7DF2450C3B8E}
278+
{A533C800-3DC3-4D04-90A7-0CE7A1E6BDB3} = {F1D0972B-38CF-49C2-9F4B-4C5DE02FB71D}
279+
{E69578EB-B456-4062-A645-877CD964528B} = {F1D0972B-38CF-49C2-9F4B-4C5DE02FB71D}
280+
{C1542297-8763-4DF4-957C-489ED771C21D} = {7CB2F02E-03FA-4FFF-89A5-C51F107623FD}
281+
{D2E73927-5966-445C-94E9-EFE6F269C8D5} = {7CB2F02E-03FA-4FFF-89A5-C51F107623FD}
246282
EndGlobalSection
247283
GlobalSection(ExtensibilityGlobals) = postSolution
248284
SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521}

src/OpenTelemetry.Api/Trace/SpanAttributeConstants.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ public static class SpanAttributeConstants
4040
public const string HttpRouteKey = "http.route";
4141
public const string HttpFlavorKey = "http.flavor";
4242

43-
public const string DatabaseTypeKey = "db.type";
44-
public const string DatabaseInstanceKey = "db.instance";
43+
public const string DatabaseSystemKey = "db.system";
44+
public const string DatabaseNameKey = "db.name";
4545
public const string DatabaseStatementKey = "db.statement";
46+
public const string DatabaseStatementTypeKey = "db.statement_type";
4647

4748
public const string RpcSystem = "rpc.system";
4849
public const string RpcService = "rpc.service";

src/OpenTelemetry.Api/Trace/SpanExtensions.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -207,34 +207,34 @@ public static TelemetrySpan PutHttpFlavorAttribute(this TelemetrySpan span, stri
207207
}
208208

209209
/// <summary>
210-
/// Helper method that populates database type
211-
/// to https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-database.md.
210+
/// Helper method that populates database system
211+
/// to https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/database.md.
212212
/// </summary>
213213
/// <param name="span">Span to fill out.</param>
214-
/// <param name="type">Database type.</param>
214+
/// <param name="system">Database system.</param>
215215
/// <returns>Span with populated properties.</returns>
216-
public static TelemetrySpan PutDatabaseTypeAttribute(this TelemetrySpan span, string type)
216+
public static TelemetrySpan PutDatabaseSystemAttribute(this TelemetrySpan span, string system)
217217
{
218-
span.SetAttribute(SpanAttributeConstants.DatabaseTypeKey, type);
218+
span.SetAttribute(SpanAttributeConstants.DatabaseSystemKey, system);
219219
return span;
220220
}
221221

222222
/// <summary>
223-
/// Helper method that populates database instance
224-
/// to https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-database.md.
223+
/// Helper method that populates database name
224+
/// to https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/database.md.
225225
/// </summary>
226226
/// <param name="span">Span to fill out.</param>
227-
/// <param name="instance">Database instance.</param>
227+
/// <param name="name">Database name.</param>
228228
/// <returns>Span with populated properties.</returns>
229-
public static TelemetrySpan PutDatabaseInstanceAttribute(this TelemetrySpan span, string instance)
229+
public static TelemetrySpan PutDatabaseNameAttribute(this TelemetrySpan span, string name)
230230
{
231-
span.SetAttribute(SpanAttributeConstants.DatabaseInstanceKey, instance);
231+
span.SetAttribute(SpanAttributeConstants.DatabaseNameKey, name);
232232
return span;
233233
}
234234

235235
/// <summary>
236236
/// Helper method that populates database statement
237-
/// to https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/data-database.md.
237+
/// to https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/database.md.
238238
/// </summary>
239239
/// <param name="span">Span to fill out.</param>
240240
/// <param name="statement">Database statement.</param>

src/OpenTelemetry.Exporter.Jaeger/Implementation/JaegerActivityExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public static JaegerSpan ToJaegerSpan(this Activity activity)
9898
PooledList<JaegerTag>.Add(ref jaegerTags.Tags, new JaegerTag("library.name", JaegerTagType.STRING, vStr: activitySource.Name));
9999
if (!string.IsNullOrEmpty(activitySource.Version))
100100
{
101-
PooledList<JaegerTag>.Add(ref jaegerTags.Tags, new JaegerTag("library.version", JaegerTagType.STRING, vStr: activitySource.Name));
101+
PooledList<JaegerTag>.Add(ref jaegerTags.Tags, new JaegerTag("library.version", JaegerTagType.STRING, vStr: activitySource.Version));
102102
}
103103
}
104104

src/OpenTelemetry.Instrumentation.AspNet.Win/Implementation/HttpInListener.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,10 @@ public HttpInListener(string name, AspNetInstrumentationOptions options, Activit
4040

4141
public override void OnStartActivity(Activity activity, object payload)
4242
{
43-
const string EventNameSuffix = ".OnStartActivity";
44-
4543
var context = HttpContext.Current;
4644
if (context == null)
4745
{
48-
InstrumentationEventSource.Log.NullPayload(nameof(HttpInListener) + EventNameSuffix);
46+
InstrumentationEventSource.Log.NullPayload(nameof(HttpInListener), nameof(this.OnStartActivity));
4947
return;
5048
}
5149

@@ -114,8 +112,6 @@ public override void OnStartActivity(Activity activity, object payload)
114112

115113
public override void OnStopActivity(Activity activity, object payload)
116114
{
117-
const string EventNameSuffix = ".OnStopActivity";
118-
119115
Activity activityToEnrich = activity;
120116

121117
if (!(this.options.TextFormat is TraceContextFormatActivity))
@@ -139,7 +135,7 @@ public override void OnStopActivity(Activity activity, object payload)
139135
var context = HttpContext.Current;
140136
if (context == null)
141137
{
142-
InstrumentationEventSource.Log.NullPayload(nameof(HttpInListener) + EventNameSuffix);
138+
InstrumentationEventSource.Log.NullPayload(nameof(HttpInListener), nameof(this.OnStopActivity));
143139
return;
144140
}
145141

src/OpenTelemetry.Instrumentation.AspNetCore/Implementation/HttpInListener.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,11 @@ public HttpInListener(string name, AspNetCoreInstrumentationOptions options, Act
4848

4949
public override void OnStartActivity(Activity activity, object payload)
5050
{
51-
const string EventNameSuffix = ".OnStartActivity";
5251
var context = this.startContextFetcher.Fetch(payload) as HttpContext;
5352

5453
if (context == null)
5554
{
56-
InstrumentationEventSource.Log.NullPayload(nameof(HttpInListener) + EventNameSuffix);
55+
InstrumentationEventSource.Log.NullPayload(nameof(HttpInListener), nameof(this.OnStartActivity));
5756
return;
5857
}
5958

@@ -120,13 +119,11 @@ public override void OnStartActivity(Activity activity, object payload)
120119

121120
public override void OnStopActivity(Activity activity, object payload)
122121
{
123-
const string EventNameSuffix = ".OnStopActivity";
124-
125122
if (activity.IsAllDataRequested)
126123
{
127124
if (!(this.stopContextFetcher.Fetch(payload) is HttpContext context))
128125
{
129-
InstrumentationEventSource.Log.NullPayload(nameof(HttpInListener) + EventNameSuffix);
126+
InstrumentationEventSource.Log.NullPayload(nameof(HttpInListener), nameof(this.OnStopActivity));
130127
return;
131128
}
132129

src/OpenTelemetry.Instrumentation.Dependencies/Implementation/GrpcClientDiagnosticListener.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,9 @@ public GrpcClientDiagnosticListener(ActivitySourceAdapter activitySource)
4141

4242
public override void OnStartActivity(Activity activity, object payload)
4343
{
44-
const string EventNameSuffix = ".OnStartActivity";
4544
if (!(this.startRequestFetcher.Fetch(payload) is HttpRequestMessage request))
4645
{
47-
InstrumentationEventSource.Log.NullPayload(nameof(GrpcClientDiagnosticListener) + EventNameSuffix);
46+
InstrumentationEventSource.Log.NullPayload(nameof(GrpcClientDiagnosticListener), nameof(this.OnStartActivity));
4847
return;
4948
}
5049

src/OpenTelemetry.Instrumentation.Dependencies/Implementation/HttpHandlerDiagnosticListener.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,9 @@ public HttpHandlerDiagnosticListener(HttpClientInstrumentationOptions options, A
6262

6363
public override void OnStartActivity(Activity activity, object payload)
6464
{
65-
const string EventNameSuffix = ".OnStartActivity";
6665
if (!(this.startRequestFetcher.Fetch(payload) is HttpRequestMessage request))
6766
{
68-
InstrumentationEventSource.Log.NullPayload(nameof(HttpHandlerDiagnosticListener) + EventNameSuffix);
67+
InstrumentationEventSource.Log.NullPayload(nameof(HttpHandlerDiagnosticListener), nameof(this.OnStartActivity));
6968
return;
7069
}
7170

@@ -141,13 +140,11 @@ public override void OnStopActivity(Activity activity, object payload)
141140

142141
public override void OnException(Activity activity, object payload)
143142
{
144-
const string EventNameSuffix = ".OnException";
145-
146143
if (activity.IsAllDataRequested)
147144
{
148145
if (!(this.stopExceptionFetcher.Fetch(payload) is Exception exc))
149146
{
150-
InstrumentationEventSource.Log.NullPayload(nameof(HttpHandlerDiagnosticListener) + EventNameSuffix);
147+
InstrumentationEventSource.Log.NullPayload(nameof(HttpHandlerDiagnosticListener), nameof(this.OnException));
151148
return;
152149
}
153150

src/OpenTelemetry.Instrumentation.Dependencies/Implementation/SqlClientDiagnosticListener.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
using System.Data;
1818
using System.Diagnostics;
1919
using OpenTelemetry.Trace;
20-
using OpenTelemetry.Trace.Samplers;
2120

2221
namespace OpenTelemetry.Instrumentation.Dependencies.Implementation
2322
{
@@ -32,7 +31,7 @@ internal class SqlClientDiagnosticListener : ListenerHandler
3231
internal const string SqlDataWriteCommandError = "System.Data.SqlClient.WriteCommandError";
3332
internal const string SqlMicrosoftWriteCommandError = "Microsoft.Data.SqlClient.WriteCommandError";
3433

35-
private const string DatabaseStatementTypeSpanAttributeKey = "db.statementType";
34+
internal const string MicrosoftSqlServerDatabaseSystemName = "mssql";
3635

3736
private readonly PropertyFetcher commandFetcher = new PropertyFetcher("Command");
3837
private readonly PropertyFetcher connectionFetcher = new PropertyFetcher("Connection");
@@ -66,7 +65,7 @@ public override void OnCustom(string name, Activity activity, object payload)
6665

6766
if (command == null)
6867
{
69-
InstrumentationEventSource.Log.NullPayload($"{nameof(SqlClientDiagnosticListener)}-{name}");
68+
InstrumentationEventSource.Log.NullPayload(nameof(SqlClientDiagnosticListener), name);
7069
return;
7170
}
7271

@@ -85,17 +84,16 @@ public override void OnCustom(string name, Activity activity, object payload)
8584
var commandText = this.commandTextFetcher.Fetch(command);
8685

8786
activity.AddTag(SpanAttributeConstants.ComponentKey, "sql");
88-
activity.AddTag(SpanAttributeConstants.DatabaseTypeKey, "sql");
87+
activity.AddTag(SpanAttributeConstants.DatabaseSystemKey, MicrosoftSqlServerDatabaseSystemName);
8988
activity.AddTag(SpanAttributeConstants.PeerServiceKey, (string)dataSource);
90-
activity.AddTag(SpanAttributeConstants.DatabaseInstanceKey, (string)database);
89+
activity.AddTag(SpanAttributeConstants.DatabaseNameKey, (string)database);
9190

9291
if (this.commandTypeFetcher.Fetch(command) is CommandType commandType)
9392
{
94-
activity.AddTag(DatabaseStatementTypeSpanAttributeKey, commandType.ToString());
95-
9693
switch (commandType)
9794
{
9895
case CommandType.StoredProcedure:
96+
activity.AddTag(SpanAttributeConstants.DatabaseStatementTypeKey, nameof(CommandType.StoredProcedure));
9997
if (this.options.CaptureStoredProcedureCommandName)
10098
{
10199
activity.AddTag(SpanAttributeConstants.DatabaseStatementKey, (string)commandText);
@@ -104,12 +102,17 @@ public override void OnCustom(string name, Activity activity, object payload)
104102
break;
105103

106104
case CommandType.Text:
105+
activity.AddTag(SpanAttributeConstants.DatabaseStatementTypeKey, nameof(CommandType.Text));
107106
if (this.options.CaptureTextCommandContent)
108107
{
109108
activity.AddTag(SpanAttributeConstants.DatabaseStatementKey, (string)commandText);
110109
}
111110

112111
break;
112+
113+
case CommandType.TableDirect:
114+
activity.AddTag(SpanAttributeConstants.DatabaseStatementTypeKey, nameof(CommandType.TableDirect));
115+
break;
113116
}
114117
}
115118
}
@@ -136,7 +139,7 @@ public override void OnCustom(string name, Activity activity, object payload)
136139
}
137140
else
138141
{
139-
InstrumentationEventSource.Log.NullPayload($"{nameof(SqlClientDiagnosticListener)}-{name}");
142+
InstrumentationEventSource.Log.NullPayload(nameof(SqlClientDiagnosticListener), name);
140143
}
141144
}
142145

0 commit comments

Comments
 (0)