Skip to content

Commit ceebd45

Browse files
authored
[Exporter.OpenTelemetry.Protocol.Tests] enable analysis (#6264)
1 parent 13ed63a commit ceebd45

21 files changed

+549
-392
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using Google.Protobuf;
5+
using Google.Protobuf.WellKnownTypes;
6+
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClient.Grpc;
7+
using Xunit;
8+
9+
namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClient.Tests;
10+
11+
#pragma warning disable CA1515 // Consider making public types internal
12+
public class GrpcRetryTestCase
13+
#pragma warning restore CA1515 // Consider making public types internal
14+
{
15+
private readonly string testRunnerName;
16+
17+
private GrpcRetryTestCase(string testRunnerName, GrpcRetryAttempt[] retryAttempts, int expectedRetryAttempts = 1)
18+
{
19+
this.ExpectedRetryAttempts = expectedRetryAttempts;
20+
this.RetryAttempts = retryAttempts;
21+
this.testRunnerName = testRunnerName;
22+
}
23+
24+
public int ExpectedRetryAttempts { get; }
25+
26+
internal GrpcRetryAttempt[] RetryAttempts { get; }
27+
28+
public static TheoryData<GrpcRetryTestCase> GetGrpcTestCases()
29+
{
30+
return
31+
[
32+
new("Cancelled", [new(StatusCode.Cancelled)]),
33+
new("DeadlineExceeded", [new(StatusCode.DeadlineExceeded)]),
34+
new("Aborted", [new(StatusCode.Aborted)]),
35+
new("OutOfRange", [new(StatusCode.OutOfRange)]),
36+
new("DataLoss", [new(StatusCode.DataLoss)]),
37+
new("Unavailable", [new(StatusCode.Unavailable)]),
38+
39+
new("OK", [new(StatusCode.OK, expectedSuccess: false)]),
40+
new("PermissionDenied", [new(StatusCode.PermissionDenied, expectedSuccess: false)]),
41+
new("Unknown", [new(StatusCode.Unknown, expectedSuccess: false)]),
42+
43+
new("ResourceExhausted w/o RetryInfo", [new(StatusCode.ResourceExhausted, expectedSuccess: false)]),
44+
new("ResourceExhausted w/ RetryInfo", [new(StatusCode.ResourceExhausted, throttleDelay: GetThrottleDelayString(new Duration { Seconds = 2 }), expectedNextRetryDelayMilliseconds: 3000)]),
45+
46+
new("Unavailable w/ RetryInfo", [new(StatusCode.Unavailable, throttleDelay: GetThrottleDelayString(Duration.FromTimeSpan(TimeSpan.FromMilliseconds(2000))), expectedNextRetryDelayMilliseconds: 3000)]),
47+
48+
new("Expired deadline", [new(StatusCode.Unavailable, deadlineExceeded: true, expectedSuccess: false)]),
49+
50+
new(
51+
"Exponential backoff",
52+
[
53+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1500),
54+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 2250),
55+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 3375),
56+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000),
57+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000)
58+
],
59+
expectedRetryAttempts: 5),
60+
61+
new(
62+
"Retry until non-retryable status code encountered",
63+
[
64+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1500),
65+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 2250),
66+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 3375),
67+
new(StatusCode.PermissionDenied, expectedSuccess: false),
68+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000)
69+
],
70+
expectedRetryAttempts: 4),
71+
72+
// Test throttling affects exponential backoff.
73+
new(
74+
"Exponential backoff after throttling",
75+
[
76+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1500),
77+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 2250),
78+
new(StatusCode.Unavailable, throttleDelay: GetThrottleDelayString(Duration.FromTimeSpan(TimeSpan.FromMilliseconds(500))), expectedNextRetryDelayMilliseconds: 750),
79+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1125),
80+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 1688),
81+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 2532),
82+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 3798),
83+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000),
84+
new(StatusCode.Unavailable, expectedNextRetryDelayMilliseconds: 5000)
85+
],
86+
expectedRetryAttempts: 9),
87+
];
88+
}
89+
90+
public override string ToString()
91+
{
92+
return this.testRunnerName;
93+
}
94+
95+
private static string GetThrottleDelayString(Duration throttleDelay)
96+
{
97+
var status = new Google.Rpc.Status
98+
{
99+
Code = 4,
100+
Message = "Only nanos",
101+
Details =
102+
{
103+
Any.Pack(new Google.Rpc.RetryInfo
104+
{
105+
RetryDelay = throttleDelay,
106+
}),
107+
},
108+
};
109+
110+
return Convert.ToBase64String(status.ToByteArray());
111+
}
112+
113+
internal struct GrpcRetryAttempt
114+
{
115+
internal GrpcRetryAttempt(
116+
StatusCode statusCode,
117+
bool deadlineExceeded = false,
118+
string? throttleDelay = null,
119+
int expectedNextRetryDelayMilliseconds = 1500,
120+
bool expectedSuccess = true)
121+
{
122+
var status = new Status(statusCode, "Error");
123+
124+
// Using arbitrary +1 hr for deadline for test purposes.
125+
var deadlineUtc = deadlineExceeded ? DateTime.UtcNow.AddSeconds(-1) : DateTime.UtcNow.AddHours(1);
126+
127+
this.ThrottleDelay = throttleDelay;
128+
129+
this.Response = new ExportClientGrpcResponse(expectedSuccess, deadlineUtc, null, status, this.ThrottleDelay);
130+
131+
this.ExpectedNextRetryDelayMilliseconds = expectedNextRetryDelayMilliseconds;
132+
133+
this.ExpectedSuccess = expectedSuccess;
134+
}
135+
136+
public string? ThrottleDelay { get; }
137+
138+
public int? ExpectedNextRetryDelayMilliseconds { get; }
139+
140+
public bool ExpectedSuccess { get; }
141+
142+
internal ExportClientGrpcResponse Response { get; }
143+
}
144+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using System.Net;
5+
#if NETFRAMEWORK
6+
using System.Net.Http;
7+
#endif
8+
using System.Net.Http.Headers;
9+
using Xunit;
10+
11+
namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClient.Tests;
12+
13+
#pragma warning disable CA1515 // Consider making public types internal
14+
public class HttpRetryTestCase
15+
#pragma warning restore CA1515 // Consider making public types internal
16+
{
17+
private readonly string testRunnerName;
18+
19+
private HttpRetryTestCase(string testRunnerName, HttpRetryAttempt[] retryAttempts, int expectedRetryAttempts = 1)
20+
{
21+
this.ExpectedRetryAttempts = expectedRetryAttempts;
22+
this.RetryAttempts = retryAttempts;
23+
this.testRunnerName = testRunnerName;
24+
}
25+
26+
public int ExpectedRetryAttempts { get; }
27+
28+
internal HttpRetryAttempt[] RetryAttempts { get; }
29+
30+
public static TheoryData<HttpRetryTestCase> GetHttpTestCases()
31+
{
32+
return
33+
[
34+
new("NetworkError", [new(statusCode: null)]),
35+
new("GatewayTimeout", [new(statusCode: HttpStatusCode.GatewayTimeout, throttleDelay: TimeSpan.FromSeconds(1))]),
36+
#if NETSTANDARD2_1_OR_GREATER || NET
37+
new("ServiceUnavailable", [new(statusCode: HttpStatusCode.TooManyRequests, throttleDelay: TimeSpan.FromSeconds(1))]),
38+
#endif
39+
40+
new(
41+
"Exponential Backoff",
42+
[
43+
new(statusCode: null, expectedNextRetryDelayMilliseconds: 1500),
44+
new(statusCode: null, expectedNextRetryDelayMilliseconds: 2250),
45+
new(statusCode: null, expectedNextRetryDelayMilliseconds: 3375),
46+
new(statusCode: null, expectedNextRetryDelayMilliseconds: 5000),
47+
new(statusCode: null, expectedNextRetryDelayMilliseconds: 5000)
48+
],
49+
expectedRetryAttempts: 5),
50+
new(
51+
"Retry until non-retryable status code encountered",
52+
[
53+
new(statusCode: HttpStatusCode.ServiceUnavailable, expectedNextRetryDelayMilliseconds: 1500),
54+
new(statusCode: HttpStatusCode.ServiceUnavailable, expectedNextRetryDelayMilliseconds: 2250),
55+
new(statusCode: HttpStatusCode.ServiceUnavailable, expectedNextRetryDelayMilliseconds: 3375),
56+
new(statusCode: HttpStatusCode.BadRequest, expectedSuccess: false),
57+
new(statusCode: HttpStatusCode.ServiceUnavailable, expectedNextRetryDelayMilliseconds: 5000)
58+
],
59+
expectedRetryAttempts: 4),
60+
new(
61+
"Expired deadline",
62+
[
63+
new(statusCode: HttpStatusCode.ServiceUnavailable, isDeadlineExceeded: true, expectedSuccess: false)
64+
]),
65+
];
66+
67+
// TODO: Add more cases.
68+
}
69+
70+
public override string ToString()
71+
{
72+
return this.testRunnerName;
73+
}
74+
75+
internal sealed class HttpRetryAttempt
76+
{
77+
public ExportClientHttpResponse Response;
78+
public TimeSpan? ThrottleDelay;
79+
public int? ExpectedNextRetryDelayMilliseconds;
80+
public bool ExpectedSuccess;
81+
82+
internal HttpRetryAttempt(
83+
HttpStatusCode? statusCode,
84+
TimeSpan? throttleDelay = null,
85+
bool isDeadlineExceeded = false,
86+
int expectedNextRetryDelayMilliseconds = 1500,
87+
bool expectedSuccess = true)
88+
{
89+
this.ThrottleDelay = throttleDelay;
90+
91+
HttpResponseMessage? responseMessage = null;
92+
if (statusCode != null)
93+
{
94+
#pragma warning disable CA2000 // Dispose objects before losing scope
95+
responseMessage = new HttpResponseMessage();
96+
#pragma warning restore CA2000 // Dispose objects before losing scope
97+
98+
if (throttleDelay != null)
99+
{
100+
responseMessage.Headers.RetryAfter = new RetryConditionHeaderValue(throttleDelay.Value);
101+
}
102+
103+
responseMessage.StatusCode = (HttpStatusCode)statusCode;
104+
}
105+
106+
// Using arbitrary +1 hr for deadline for test purposes.
107+
var deadlineUtc = isDeadlineExceeded ? DateTime.UtcNow.AddMilliseconds(-1) : DateTime.UtcNow.AddHours(1);
108+
this.Response = new ExportClientHttpResponse(expectedSuccess, deadlineUtc, responseMessage, new HttpRequestException());
109+
this.ExpectedNextRetryDelayMilliseconds = expectedNextRetryDelayMilliseconds;
110+
this.ExpectedSuccess = expectedSuccess;
111+
}
112+
}
113+
}

test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Implementation/ExportClient/OtlpHttpTraceExportClientTests.cs

+5-3
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ public void SendExportRequest_ExportTraceServiceRequest_SendsCorrectHttpRequest(
9090
Headers = $"{header1.Name}={header1.Value}, {header2.Name} = {header2.Value}",
9191
};
9292

93+
#pragma warning disable CA2000 // Dispose objects before losing scope
9394
var testHttpHandler = new TestHttpMessageHandler();
95+
#pragma warning restore CA2000 // Dispose objects before losing scope
9496

95-
var httpRequestContent = Array.Empty<byte>();
96-
97-
var httpClient = new HttpClient(testHttpHandler);
97+
using var httpClient = new HttpClient(testHttpHandler);
9898

9999
var exportClient = new OtlpHttpExportClient(options, httpClient, string.Empty);
100100

@@ -117,7 +117,9 @@ public void SendExportRequest_ExportTraceServiceRequest_SendsCorrectHttpRequest(
117117
using var openTelemetrySdk = builder.Build();
118118

119119
var exportedItems = new List<Activity>();
120+
#pragma warning disable CA2000 // Dispose objects before losing scope
120121
var processor = new BatchActivityExportProcessor(new InMemoryExporter<Activity>(exportedItems));
122+
#pragma warning restore CA2000 // Dispose objects before losing scope
121123
const int numOfSpans = 10;
122124
bool isEven;
123125
for (var i = 0; i < numOfSpans; i++)

test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Implementation/Serializer/OtlpArrayTagWriterTests.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public void BeginWriteArray_InitializesArrayState()
4343
// Assert
4444
Assert.NotNull(arrayState.Buffer);
4545
Assert.Equal(0, arrayState.WritePosition);
46-
Assert.True(arrayState.Buffer.Length == 2048);
46+
Assert.Equal(2048, arrayState.Buffer.Length);
4747
}
4848

4949
[Fact]
@@ -166,10 +166,11 @@ public void SerializeLargeArrayExceeding2MB_TruncatesInOtlpSpan()
166166
lessthat1MBArray[i] = "1234";
167167
}
168168

169+
string?[] stringArray = ["12345"];
169170
var tags = new ActivityTagsCollection
170171
{
171172
new("lessthat1MBArray", lessthat1MBArray),
172-
new("StringArray", new string?[] { "12345" }),
173+
new("StringArray", stringArray),
173174
new("LargeArray", largeArray),
174175
};
175176

@@ -181,7 +182,7 @@ public void SerializeLargeArrayExceeding2MB_TruncatesInOtlpSpan()
181182
var otlpSpan = ToOtlpSpanWithExtendedBuffer(new SdkLimitOptions(), activity);
182183

183184
Assert.NotNull(otlpSpan);
184-
Assert.True(otlpSpan.Attributes.Count == 3);
185+
Assert.Equal(3, otlpSpan.Attributes.Count);
185186
var keyValue = otlpSpan.Attributes.FirstOrDefault(kvp => kvp.Key == "StringArray");
186187
Assert.NotNull(keyValue);
187188
Assert.Equal("12345", keyValue.Value.ArrayValue.Values[0].StringValue);

test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/Implementation/Serializer/ProtobufSerializerTests.cs

+8
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,14 @@ public void WriteStringWithTag_WritesCorrectly()
102102
[InlineData(268435455, new byte[] { 0xFF, 0xFF, 0xFF, 0x7F })] // Max 4-byte value
103103
public void WriteReservedLength_WritesCorrectly(int length, byte[] expectedBytes)
104104
{
105+
#if NET
106+
Assert.NotNull(expectedBytes);
107+
#else
108+
if (expectedBytes == null)
109+
{
110+
throw new ArgumentNullException(nameof(expectedBytes));
111+
}
112+
#endif
105113
byte[] buffer = new byte[10];
106114
ProtobufSerializer.WriteReservedLength(buffer, 0, length);
107115

test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/IntegrationTest/IntegrationTests.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Diagnostics;
55
using System.Diagnostics.Metrics;
66
using System.Diagnostics.Tracing;
7+
using System.Globalization;
78
using Microsoft.Extensions.Logging;
89
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation;
910
using OpenTelemetry.Logs;
@@ -265,7 +266,7 @@ public void LogExportResultIsSuccess(OtlpExportProtocol protocol, string endpoin
265266
});
266267

267268
var logger = loggerFactory.CreateLogger("OtlpLogExporterTests");
268-
logger.LogInformation("Hello from {name} {price}.", "tomato", 2.99);
269+
logger.HelloFrom("tomato", 2.99);
269270

270271
switch (processorOptions.ExportProcessorType)
271272
{
@@ -307,7 +308,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData)
307308
string? message;
308309
if (eventData.Message != null && eventData.Payload != null && eventData.Payload.Count > 0)
309310
{
310-
message = string.Format(eventData.Message, eventData.Payload.ToArray());
311+
message = string.Format(CultureInfo.InvariantCulture, eventData.Message, eventData.Payload.ToArray());
311312
}
312313
else
313314
{

0 commit comments

Comments
 (0)