From d42f171d13391d613b0f21d5798ebbd54419a0da Mon Sep 17 00:00:00 2001 From: Vishwesh Bankwar Date: Wed, 5 Oct 2022 12:49:00 -0700 Subject: [PATCH] [HttpClient] Unit test for retries (#3730) --- .../HttpClientTests.Basic.cs | 37 +++++++------ .../RetryHandler.cs | 52 +++++++++++++++++++ 2 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 test/OpenTelemetry.Instrumentation.Http.Tests/RetryHandler.cs diff --git a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.Basic.cs b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.Basic.cs index 3272e8f5c63..df742c63634 100644 --- a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.Basic.cs +++ b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.Basic.cs @@ -15,6 +15,7 @@ // #if !NETFRAMEWORK using System; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net.Http; @@ -300,30 +301,36 @@ public async Task HttpClientInstrumentation_AddViaFactory_HttpInstrumentation_Co Assert.IsType(processor.Invocations[1].Arguments[0]); } - [Fact] - public async Task HttpClientInstrumentationBacksOffIfAlreadyInstrumented() + [Fact(Skip = "https://github.com/open-telemetry/opentelemetry-dotnet/issues/3729")] + public async Task HttpClientInstrumentationExportsSpansCreatedForRetries() { - // TODO: Investigate why this feature is required. - var processor = new Mock>(); - + var exportedItems = new List(); var request = new HttpRequestMessage { RequestUri = new Uri(this.url), Method = new HttpMethod("GET"), }; - request.Headers.Add("traceparent", "00-0123456789abcdef0123456789abcdef-0123456789abcdef-01"); - - using (Sdk.CreateTracerProviderBuilder() + using var traceprovider = Sdk.CreateTracerProviderBuilder() .AddHttpClientInstrumentation() - .AddProcessor(processor.Object) - .Build()) - { - using var c = new HttpClient(); - await c.SendAsync(request); - } + .AddInMemoryExporter(exportedItems) + .Build(); - Assert.Equal(4, processor.Invocations.Count); // SetParentProvider/OnShutdown/Dispose/OnStart called. + int maxRetries = 3; + using var c = new HttpClient(new RetryHandler(new HttpClientHandler(), maxRetries)); + await c.SendAsync(request); + + // number of exported spans should be 3(maxRetries) + Assert.Equal(3, exportedItems.Count()); + + var spanid1 = exportedItems[0].SpanId; + var spanid2 = exportedItems[1].SpanId; + var spanid3 = exportedItems[2].SpanId; + + // Validate span ids are different + Assert.NotEqual(spanid1, spanid2); + Assert.NotEqual(spanid3, spanid1); + Assert.NotEqual(spanid2, spanid3); } [Fact] diff --git a/test/OpenTelemetry.Instrumentation.Http.Tests/RetryHandler.cs b/test/OpenTelemetry.Instrumentation.Http.Tests/RetryHandler.cs new file mode 100644 index 00000000000..2a2101bad5b --- /dev/null +++ b/test/OpenTelemetry.Instrumentation.Http.Tests/RetryHandler.cs @@ -0,0 +1,52 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace OpenTelemetry.Tests +{ + public class RetryHandler : DelegatingHandler + { + private int maxRetries; + + public RetryHandler(HttpMessageHandler innerHandler, int maxRetries) + : base(innerHandler) + { + this.maxRetries = maxRetries; + } + + protected override async Task SendAsync( + HttpRequestMessage request, + CancellationToken cancellationToken) + { + HttpResponseMessage response = null; + for (int i = 0; i < this.maxRetries; i++) + { + try + { + response = await base.SendAsync(request, cancellationToken); + } + catch + { + } + } + + return response; + } + } +}