public async Task DebugIndividualTestAsync() { var serializer = new JsonSerializer(); var input = serializer.Deserialize <HttpTestData.HttpOutTestCase[]>(new JsonTextReader(new StringReader(@" [ { ""name"": ""Response code: 399"", ""method"": ""GET"", ""url"": ""http://{host}:{port}/"", ""responseCode"": 399, ""spanName"": ""HTTP GET"", ""spanStatus"": ""OK"", ""spanKind"": ""Client"", ""spanAttributes"": { ""http.method"": ""GET"", ""http.host"": ""{host}:{port}"", ""http.status_code"": ""399"", ""http.url"": ""http://{host}:{port}/"" } } ] "))); var t = (Task)this.GetType().InvokeMember(nameof(this.HttpOutCallsAreCollectedSuccessfullyAsync), BindingFlags.InvokeMethod, null, this, HttpTestData.GetArgumentsFromTestCaseObject(input).First()); await t; }
public async Task HttpOutCallsAreCollectedSuccessfullyAsync(HttpTestData.HttpOutTestCase tc) { var serverLifeTime = TestHttpServer.RunServer( (ctx) => { ctx.Response.StatusCode = tc.ResponseCode == 0 ? 200 : tc.ResponseCode; ctx.Response.OutputStream.Close(); }, out var host, out var port); var expectedResource = Resources.Resources.CreateServiceResource("test-service"); var spanProcessor = new Mock <ActivityProcessor>(); tc.Url = HttpTestData.NormalizeValues(tc.Url, host, port); using (serverLifeTime) using (OpenTelemetrySdk.CreateTracerProvider( (builder) => builder.AddHttpClientDependencyInstrumentation((opt) => opt.SetHttpFlavor = tc.SetHttpFlavor) .SetResource(expectedResource) .AddProcessorPipeline(p => p.AddProcessor(n => spanProcessor.Object)))) { try { using var c = new HttpClient(); var request = new HttpRequestMessage { RequestUri = new Uri(tc.Url), Method = new HttpMethod(tc.Method), Version = new Version(2, 0), }; if (tc.Headers != null) { foreach (var header in tc.Headers) { request.Headers.Add(header.Key, header.Value); } } await c.SendAsync(request); } catch (Exception) { // test case can intentionally send request that will result in exception } } Assert.Equal(2, spanProcessor.Invocations.Count); // begin and end was called var span = (Activity)spanProcessor.Invocations[1].Arguments[0]; Assert.Equal(tc.SpanName, span.DisplayName); Assert.Equal(tc.SpanKind, span.Kind.ToString()); var d = new Dictionary <string, string>() { { "Ok", "OK" }, { "Cancelled", "CANCELLED" }, { "Unknown", "UNKNOWN" }, { "InvalidArgument", "INVALID_ARGUMENT" }, { "DeadlineExceeded", "DEADLINE_EXCEEDED" }, { "NotFound", "NOT_FOUND" }, { "AlreadyExists", "ALREADY_EXISTS" }, { "PermissionDenied", "PERMISSION_DENIED" }, { "ResourceExhausted", "RESOURCE_EXHAUSTED" }, { "FailedPrecondition", "FAILED_PRECONDITION" }, { "Aborted", "ABORTED" }, { "OutOfRange", "OUT_OF_RANGE" }, { "Unimplemented", "UNIMPLEMENTED" }, { "Internal", "INTERNAL" }, { "Unavailable", "UNAVAILABLE" }, { "DataLoss", "DATA_LOSS" }, { "Unauthenticated", "UNAUTHENTICATED" }, }; // Assert.Equal(tc.SpanStatus, d[span.Status.CanonicalCode]); Assert.Equal( tc.SpanStatus, d[span.Tags.FirstOrDefault(i => i.Key == SpanAttributeConstants.StatusCodeKey).Value]); if (tc.SpanStatusHasDescription.HasValue) { var desc = span.Tags.FirstOrDefault(i => i.Key == SpanAttributeConstants.StatusDescriptionKey).Value; Assert.Equal(tc.SpanStatusHasDescription.Value, !string.IsNullOrEmpty(desc)); } var normalizedAttributes = span.Tags.Where(kv => !kv.Key.StartsWith("ot")).ToImmutableSortedDictionary(x => x.Key, x => x.Value.ToString()); var normalizedAttributesTestCase = tc.SpanAttributes.ToDictionary(x => x.Key, x => HttpTestData.NormalizeValues(x.Value, host, port)); Assert.Equal(normalizedAttributesTestCase.Count, normalizedAttributes.Count); foreach (var kv in normalizedAttributesTestCase) { // TODO: Fix this test. This is mostly broken because Status is stored in tags. // Assert.Contains(span.Tags, i => i.Key == kv.Key && i.Value.Equals(kv.Value, StringComparison.InvariantCultureIgnoreCase)); } Assert.Equal(expectedResource, span.GetResource()); }
public async Task HttpOutCallsAreCollectedSuccessfullyAsync(HttpTestData.HttpOutTestCase tc) { var serverLifeTime = TestHttpServer.RunServer( (ctx) => { ctx.Response.StatusCode = tc.ResponseCode == 0 ? 200 : tc.ResponseCode; ctx.Response.OutputStream.Close(); }, out var host, out var port); var spanProcessor = new Mock <SpanProcessor>(); var tracer = TracerFactory.Create(b => b .AddProcessorPipeline(p => p.AddProcessor(_ => spanProcessor.Object))) .GetTracer(null); tc.Url = HttpTestData.NormalizeValues(tc.Url, host, port); using (serverLifeTime) using (new HttpClientInstrumentation(tracer, new HttpClientInstrumentationOptions() { SetHttpFlavor = tc.SetHttpFlavor })) { try { using var c = new HttpClient(); var request = new HttpRequestMessage { RequestUri = new Uri(tc.Url), Method = new HttpMethod(tc.Method), Version = new Version(2, 0), }; if (tc.Headers != null) { foreach (var header in tc.Headers) { request.Headers.Add(header.Key, header.Value); } } await c.SendAsync(request); } catch (Exception) { //test case can intentionally send request that will result in exception } } Assert.Equal(2, spanProcessor.Invocations.Count); // begin and end was called var span = (SpanData)spanProcessor.Invocations[1].Arguments[0]; Assert.Equal(tc.SpanName, span.Name); Assert.Equal(tc.SpanKind, span.Kind.ToString()); var d = new Dictionary <StatusCanonicalCode, string>() { { StatusCanonicalCode.Ok, "OK" }, { StatusCanonicalCode.Cancelled, "CANCELLED" }, { StatusCanonicalCode.Unknown, "UNKNOWN" }, { StatusCanonicalCode.InvalidArgument, "INVALID_ARGUMENT" }, { StatusCanonicalCode.DeadlineExceeded, "DEADLINE_EXCEEDED" }, { StatusCanonicalCode.NotFound, "NOT_FOUND" }, { StatusCanonicalCode.AlreadyExists, "ALREADY_EXISTS" }, { StatusCanonicalCode.PermissionDenied, "PERMISSION_DENIED" }, { StatusCanonicalCode.ResourceExhausted, "RESOURCE_EXHAUSTED" }, { StatusCanonicalCode.FailedPrecondition, "FAILED_PRECONDITION" }, { StatusCanonicalCode.Aborted, "ABORTED" }, { StatusCanonicalCode.OutOfRange, "OUT_OF_RANGE" }, { StatusCanonicalCode.Unimplemented, "UNIMPLEMENTED" }, { StatusCanonicalCode.Internal, "INTERNAL" }, { StatusCanonicalCode.Unavailable, "UNAVAILABLE" }, { StatusCanonicalCode.DataLoss, "DATA_LOSS" }, { StatusCanonicalCode.Unauthenticated, "UNAUTHENTICATED" }, }; Assert.Equal(tc.SpanStatus, d[span.Status.CanonicalCode]); if (tc.SpanStatusHasDescription.HasValue) { Assert.Equal(tc.SpanStatusHasDescription.Value, !string.IsNullOrEmpty(span.Status.Description)); } var normalizedAttributes = span.Attributes.ToDictionary(x => x.Key, x => x.Value.ToString()); tc.SpanAttributes = tc.SpanAttributes.ToDictionary(x => x.Key, x => HttpTestData.NormalizeValues(x.Value, host, port)); Assert.Equal(tc.SpanAttributes, normalizedAttributes); }