-
Notifications
You must be signed in to change notification settings - Fork 166
Expand file tree
/
Copy pathSystemDataSqlClientTests.cs
More file actions
166 lines (144 loc) · 7.9 KB
/
Copy pathSystemDataSqlClientTests.cs
File metadata and controls
166 lines (144 loc) · 7.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// <copyright file="SystemDataSqlClientTests.cs" company="Datadog">
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Datadog.Trace.ClrProfiler.IntegrationTests.Helpers;
using Datadog.Trace.Configuration;
using Datadog.Trace.ExtensionMethods;
using Datadog.Trace.TestHelpers;
using Datadog.Trace.TestHelpers.AutoInstrumentation.Containers;
using FluentAssertions;
using VerifyXunit;
using Xunit;
using Xunit.Abstractions;
namespace Datadog.Trace.ClrProfiler.IntegrationTests.AdoNet
{
[Trait("RequiresDockerDependency", "true")]
[Trait("DockerGroup", "1")]
[UsesVerify]
[Collection(SqlServerCollection.Name)]
public class SystemDataSqlClientTests : TracingIntegrationTest
{
private readonly SqlServerFixture _sqlServerFixture;
public SystemDataSqlClientTests(ITestOutputHelper output, SqlServerFixture sqlServerFixture)
: base("SqlServer", output)
{
_sqlServerFixture = sqlServerFixture;
SetServiceVersion("1.0.0");
ConfigureContainers(sqlServerFixture);
}
public override Result ValidateIntegrationSpan(MockSpan span, string metadataSchemaVersion) => span.IsSqlClient(metadataSchemaVersion);
[SkippableTheory]
[CombinatorialOrPairwiseData]
[Trait("Category", "EndToEnd")]
[Trait("RunOnWindows", "True")]
public async Task SubmitsTraces(
[PackageVersionData(nameof(PackageVersions.SystemDataSqlClient))] string packageVersion,
[MetadataSchemaVersionData] string metadataSchemaVersion,
[DbmPropagationModesData] string dbmPropagation,
bool injectStoredProc)
{
SetEnvironmentVariable("DD_DBM_PROPAGATION_MODE", dbmPropagation);
SetEnvironmentVariable("DD_TRACE_INJECT_CONTEXT_INTO_STORED_PROCEDURES_ENABLED", injectStoredProc.ToString());
// ALWAYS: 98 spans
// - SqlCommand: 21 spans (3 groups * 7 spans)
// - DbCommand: 42 spans (6 groups * 7 spans)
// - IDbCommand: 14 spans (2 groups * 7 spans)
// - SqlCommandVb: 21 spans (3 groups * 7 spans)
// - StoredProcedures: 10 spans (1 group * 10 spans)
//
// NETSTANDARD: +56 spans
// - DbCommand-netstandard: 42 spans (6 groups * 7 spans)
// - IDbCommand-netstandard: 14 spans (2 groups * 7 spans)
//
// CALLSITE + NETSTANDARD + NETCORE: +4 spans
// - IDbCommandGenericConstrant<SqlCommand>: 4 spans (2 group * 2 spans)
//
// CALLTARGET: +7 spans
// - IDbCommandGenericConstrant<SqlCommand>: 7 spans (1 group * 7 spans)
//
// NETSTANDARD + CALLTARGET: +7 spans
// - IDbCommandGenericConstrant<SqlCommand>-netstandard: 7 spans (1 group * 7 spans)
const int expectedSpanCount = 178;
const string dbType = "sql-server";
const string expectedOperationName = dbType + ".query";
SetEnvironmentVariable("DD_TRACE_SPAN_ATTRIBUTE_SCHEMA", metadataSchemaVersion);
var isExternalSpan = metadataSchemaVersion == "v0";
var clientSpanServiceName = isExternalSpan ? $"{EnvironmentHelper.FullSampleName}-{dbType}" : EnvironmentHelper.FullSampleName;
using var telemetry = this.ConfigureTelemetry();
using var agent = EnvironmentHelper.GetMockAgent();
using var process = await RunSampleAndWaitForExit(agent, packageVersion: packageVersion);
var spans = await agent.WaitForSpansAsync(expectedSpanCount, operationName: expectedOperationName);
spans.Count.Should().Be(expectedSpanCount);
ValidateIntegrationSpans(spans, metadataSchemaVersion, expectedServiceName: clientSpanServiceName, isExternalSpan);
await telemetry.AssertIntegrationEnabledAsync(IntegrationId.SqlClient);
// Testing that spans yield the expected output when using DBM
var settings = VerifyHelper.GetSpanVerifierSettings();
settings.AddRegexScrubber(new Regex("System-Data-SqlClient-Test-[a-zA-Z0-9]{32}"), "System-Data-SqlClient-Test-GUID");
settings.AddScrubber(builder =>
{
// Windows runs typically fall back to LocalDB with Integrated Security,
// which has no explicit user in the connection string. Docker runs use SQL auth
// with `User=sa`, so `db.user` is present there.
var lines = builder.ToString().Split(new[] { '\r', '\n' }, StringSplitOptions.None);
var filtered = string.Join(Environment.NewLine, lines.Where(line => !line.Contains("db.user:")));
builder.Clear();
builder.Append(filtered);
});
if (_sqlServerFixture.HostAndPort is { } hostAndPort)
{
settings.AddSimpleScrubber($"out.host: {hostAndPort}", "out.host: sqlserver");
settings.AddSimpleScrubber($"peer.service: {hostAndPort}", "peer.service: sqlserver");
}
settings.AddSimpleScrubber("out.host: localhost", "out.host: sqlserver");
settings.AddSimpleScrubber("out.host: (localdb)\\MSSQLLocalDB", "out.host: sqlserver");
settings.AddSimpleScrubber("out.host: sqledge_arm64", "out.host: sqlserver");
settings.AddSimpleScrubber("peer.service: localhost", "peer.service: sqlserver");
settings.AddSimpleScrubber("peer.service: (localdb)\\MSSQLLocalDB", "peer.service: sqlserver");
settings.AddSimpleScrubber("peer.service: sqledge_arm64", "peer.service: sqlserver");
settings.AddRegexScrubber(new Regex("dd.instrumentation.time_ms: \\d+.\\d+"), "dd.instrumentation.time_ms: 123.456");
var fileName = nameof(SystemDataSqlClientTests);
fileName = fileName + (dbmPropagation switch
{
"full" => ".tagged",
_ => ".untagged",
});
if (injectStoredProc)
{
// we inject comment into the stored procedures by changing them to EXEC statements
// only works for SQL Server, not for other databases
// only works for stored procedures that do not have: Output, Return, InputOutput
fileName += ".storedproc";
}
else
{
fileName += ".nostoredproc";
}
await VerifyHelper.VerifySpans(spans, settings)
.DisableRequireUniquePrefix()
.UseFileName($"{fileName}.Schema{metadataSchemaVersion.ToUpper()}");
}
[SkippableFact]
[Trait("Category", "EndToEnd")]
[Trait("RunOnWindows", "True")]
public async Task IntegrationDisabled()
{
const int totalSpanCount = 21;
const string expectedOperationName = "sql-server.query";
SetEnvironmentVariable($"DD_TRACE_{nameof(IntegrationId.SqlClient)}_ENABLED", "false");
string packageVersion = PackageVersions.SystemDataSqlClient.First()[0] as string;
using var telemetry = this.ConfigureTelemetry();
using var agent = EnvironmentHelper.GetMockAgent();
using var process = await RunSampleAndWaitForExit(agent, packageVersion: packageVersion);
var spans = await agent.WaitForSpansAsync(totalSpanCount, returnAllOperations: true);
Assert.NotEmpty(spans);
spans.Where(s => s.Name.Equals(expectedOperationName)).Should().BeEmpty();
await telemetry.AssertIntegrationDisabledAsync(IntegrationId.SqlClient);
}
}
}