Skip to content

Commit 932ec01

Browse files
Add tests
1 parent 7d328b2 commit 932ec01

25 files changed

Lines changed: 4699 additions & 29 deletions

File tree

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// <copyright file="OpenTelemetryAspNetMvc5Tests.cs" company="Datadog">
2+
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
3+
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
4+
// </copyright>
5+
6+
#if NETFRAMEWORK
7+
#pragma warning disable SA1402 // File may only contain a single class
8+
#pragma warning disable SA1649 // File name must match first type name
9+
10+
using System.Threading.Tasks;
11+
using Datadog.Trace.ClrProfiler.IntegrationTests.Helpers;
12+
using Datadog.Trace.TestHelpers;
13+
using Xunit;
14+
using Xunit.Abstractions;
15+
16+
namespace Datadog.Trace.ClrProfiler.IntegrationTests
17+
{
18+
[Collection(nameof(TestAgentOtlpCollection))]
19+
public class OpenTelemetryAspNetMvc5TestsDatadogSemantics : OpenTelemetryAspNetMvc5Tests
20+
{
21+
public OpenTelemetryAspNetMvc5TestsDatadogSemantics(IisFixture iisFixture, ITestOutputHelper output)
22+
: base(iisFixture, output, openTelemetrySemanticsEnabled: false)
23+
{
24+
}
25+
}
26+
27+
[Collection(nameof(TestAgentOtlpCollection))]
28+
public class OpenTelemetryAspNetMvc5TestsOtelSemantics : OpenTelemetryAspNetMvc5Tests
29+
{
30+
public OpenTelemetryAspNetMvc5TestsOtelSemantics(IisFixture iisFixture, ITestOutputHelper output)
31+
: base(iisFixture, output, openTelemetrySemanticsEnabled: true)
32+
{
33+
}
34+
}
35+
36+
/// <summary>
37+
/// Covers the HTTP server coverage for the OpenTelemetry HTTP Semantic Conventions
38+
/// implementation, using the ASP.NET MVC 5 sample hosted in IIS Express. One test case per
39+
/// endpoint, each exercising a different requirement from
40+
/// <see href="https://opentelemetry.io/docs/specs/semconv/http/http-spans/#http-server">the HTTP
41+
/// server conventions</see>: standard vs. unknown request methods, route templates as
42+
/// <c>http.route</c>, status-to-error mapping (which for server spans differs from client spans
43+
/// in the 4xx range), and <c>url.query</c> obfuscation.
44+
/// </summary>
45+
public abstract class OpenTelemetryAspNetMvc5Tests : OpenTelemetryAspNetTestBase
46+
{
47+
protected OpenTelemetryAspNetMvc5Tests(IisFixture iisFixture, ITestOutputHelper output, bool openTelemetrySemanticsEnabled)
48+
: base(iisFixture, output, nameof(OpenTelemetryAspNetMvc5Tests), openTelemetrySemanticsEnabled)
49+
{
50+
}
51+
52+
/// <summary>
53+
/// One endpoint per OpenTelemetry HTTP server requirement, as (method, path, status code,
54+
/// Datadog-semantics span count, OpenTelemetry-semantics span count). With Datadog semantics
55+
/// the count is 2 for a request that reaches an MVC action (the <c>aspnet.request</c> span
56+
/// plus the <c>aspnet-mvc.request</c> span nested inside it) and 1 when no action runs,
57+
/// because the MVC span is created by the action invoker. With OpenTelemetry semantics the
58+
/// <c>aspnet-mvc.request</c> span is not created, because the conventions describe a single
59+
/// HTTP server span per request.
60+
/// </summary>
61+
public static TheoryData<string, string, int, int, int> Data => new()
62+
{
63+
// Baseline: a conventionally-routed request that exercises every required and recommended
64+
// server attribute (http.request.method, url.path, url.scheme, http.route,
65+
// http.response.status_code, server.address, server.port, user_agent.original) and the
66+
// "{method} {http.route}" span name.
67+
{ "GET", "/home/index", 200, 2, 1 },
68+
69+
// A route with a parameter: http.route must stay low-cardinality, so it carries the
70+
// template ("delay/{seconds}") rather than the substituted value.
71+
{ "GET", "/delay/0", 200, 2, 1 },
72+
73+
// A standard method other than GET, to show http.request.method follows the request.
74+
{ "POST", "/home/index", 200, 2, 1 },
75+
76+
// Unknown/non-standard method: http.request.method must be _OTHER, the raw verb must move
77+
// to http.request.method_original, and the span name must fall back to "HTTP" for the
78+
// method part instead of the raw verb.
79+
{ "FOO", "/home/index", 200, 2, 1 },
80+
81+
// Sensitive query string: url.query must be captured and obfuscated with the same
82+
// DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP that http.url uses. Note that the two keys here
83+
// are treated differently, which the paired snapshots pin: "token" is matched by the
84+
// default pattern, but the bare key "sig" is not, even though the OpenTelemetry
85+
// conventions name it as one of the values to redact in a URL.
86+
{ "GET", "/statuscode/201?token=SUPER-SECRET-TOKEN-VALUE&sig=SUPER-SECRET-SIGNATURE", 201, 2, 1 },
87+
88+
// 2xx and 3xx responses: not an error under either Datadog or OpenTelemetry semantics.
89+
{ "GET", "/statuscode/302", 302, 2, 1 },
90+
91+
// 4xx response: for *server* spans the status stays unset, which is the opposite of the
92+
// client-span rule where 4xx is an error.
93+
{ "GET", "/statuscode/404", 404, 2, 1 },
94+
95+
// 5xx response: an error under both Datadog and OpenTelemetry semantics.
96+
{ "GET", "/statuscode/503", 503, 2, 1 },
97+
98+
// An unhandled exception rather than a status code: the exception is recorded on the span
99+
// and error.type carries the status code.
100+
{ "GET", "/badrequest", 500, 2, 1 },
101+
102+
// No controller for the matched route, so no MVC span is created and the server span is
103+
// the only record of the request. With OpenTelemetry semantics there is also no
104+
// http.route, so the span name must be just the method rather than the URI path.
105+
{ "GET", "/not-a-registered-route/1", 404, 1, 1 },
106+
};
107+
108+
[SkippableTheory]
109+
[Trait("Category", "EndToEnd")]
110+
[Trait("RunOnWindows", "True")]
111+
[Trait("LoadFromGAC", "True")]
112+
[Trait("RequiresDockerDependency", "true")]
113+
[MemberData(nameof(Data))]
114+
public Task SubmitsOtlpTraces(string httpMethod, string path, int statusCode, int datadogSpanCount, int otelSpanCount)
115+
=> RunTestCaseAsync(httpMethod, path, statusCode, OpenTelemetrySemanticsEnabled ? otelSpanCount : datadogSpanCount);
116+
}
117+
}
118+
#endif

0 commit comments

Comments
 (0)