private static void AssertOtlpAttributeValue(object originalValue, OtlpCommon.KeyValue akv) { switch (originalValue) { case string s: Assert.Equal(s, akv.Value.StringValue); break; case bool b: Assert.Equal(b, akv.Value.BoolValue); break; case long l: Assert.Equal(l, akv.Value.IntValue); break; case double d: Assert.Equal(d, akv.Value.DoubleValue); break; default: Assert.Equal(originalValue.ToString(), akv.Value.StringValue); break; } }
private static void AssertOtlpAttributeValue(object expected, OtlpCommon.KeyValue actual) { switch (expected) { case string s: Assert.Equal(s, actual.Value.StringValue); break; case bool b: Assert.Equal(b, actual.Value.BoolValue); break; case long l: Assert.Equal(l, actual.Value.IntValue); break; case double d: Assert.Equal(d, actual.Value.DoubleValue); break; case int i: Assert.Equal(i, actual.Value.IntValue); break; default: Assert.Equal(expected.ToString(), actual.Value.StringValue); break; } }
private static OtlpCommon.KeyValue ToOtlpAttribute(KeyValuePair <string, string> kvp) { // TODO: enforce no duplicate keys? // TODO: reverse? // To maintain full fidelity to downstream receivers convert to the proper attribute types if (kvp.Value == null) { return(null); } var attrib = new OtlpCommon.KeyValue { Key = kvp.Key, Value = new OtlpCommon.AnyValue { } }; if (long.TryParse(kvp.Value, out var longValue)) { attrib.Value.IntValue = longValue; } else if (double.TryParse(kvp.Value, out var doubleValue)) { attrib.Value.DoubleValue = doubleValue; } else if (bool.TryParse(kvp.Value, out var boolValue)) { attrib.Value.BoolValue = boolValue; } else { attrib.Value.StringValue = kvp.Value; } return(attrib); }
private static OtlpCommon.KeyValue ToOtlpAttribute(KeyValuePair <string, object> kvp) { if (kvp.Value == null) { return(null); } var attrib = new OtlpCommon.KeyValue { Key = kvp.Key, Value = new OtlpCommon.AnyValue { } }; switch (kvp.Value) { case string s: attrib.Value.StringValue = s; break; case bool b: attrib.Value.BoolValue = b; break; case int i: attrib.Value.IntValue = i; break; case long l: attrib.Value.IntValue = l; break; case double d: attrib.Value.DoubleValue = d; break; default: attrib.Value.StringValue = kvp.Value.ToString(); break; } return(attrib); }
public void ToOtlpResourceSpansTest() { var evenTags = new[] { new KeyValuePair <string, object>("k0", "v0") }; var oddTags = new[] { new KeyValuePair <string, object>("k1", "v1") }; var sources = new[] { new ActivitySource("even", "2.4.6"), new ActivitySource("odd", "1.3.5"), }; var resource = new Resources.Resource( new List <KeyValuePair <string, object> > { new KeyValuePair <string, object>(Resources.Resource.ServiceNamespaceKey, "ns1"), }); // This following is done just to set Resource to Activity. using var openTelemetrySdk = Sdk.CreateTracerProviderBuilder() .AddSource(sources[0].Name) .AddSource(sources[1].Name) .SetResource(resource) .Build(); var activities = new List <Activity>(); Activity activity = null; const int numOfSpans = 10; bool isEven; for (var i = 0; i < numOfSpans; i++) { isEven = i % 2 == 0; var source = sources[i % 2]; var activityKind = isEven ? ActivityKind.Client : ActivityKind.Server; var activityTags = isEven ? evenTags : oddTags; activity = source.StartActivity($"span-{i}", activityKind, activity?.Context ?? default, activityTags); activities.Add(activity); } activities.Reverse(); var otlpResourceSpans = activities.ToOtlpResourceSpans(); Assert.Single(otlpResourceSpans); var oltpResource = otlpResourceSpans.First().Resource; Assert.Equal(resource.Attributes.First().Key, oltpResource.Attributes.First().Key); Assert.Equal(resource.Attributes.First().Value, oltpResource.Attributes.First().Value.StringValue); foreach (var instrumentationLibrarySpans in otlpResourceSpans.First().InstrumentationLibrarySpans) { Assert.Equal(numOfSpans / 2, instrumentationLibrarySpans.Spans.Count); Assert.NotNull(instrumentationLibrarySpans.InstrumentationLibrary); var expectedSpanNames = new List <string>(); var start = instrumentationLibrarySpans.InstrumentationLibrary.Name == "even" ? 0 : 1; for (var i = start; i < numOfSpans; i += 2) { expectedSpanNames.Add($"span-{i}"); } var otlpSpans = instrumentationLibrarySpans.Spans; Assert.Equal(expectedSpanNames.Count, otlpSpans.Count); var kv0 = new OtlpCommon.KeyValue { Key = "k0", Value = new AnyValue { StringValue = "v0" } }; var kv1 = new OtlpCommon.KeyValue { Key = "k1", Value = new AnyValue { StringValue = "v1" } }; var expectedTag = instrumentationLibrarySpans.InstrumentationLibrary.Name == "even" ? kv0 : kv1; foreach (var otlpSpan in otlpSpans) { Assert.Contains(otlpSpan.Name, expectedSpanNames); Assert.Contains(expectedTag, otlpSpan.Attributes); } } }
private static List <OtlpCommon.KeyValue> ToOtlpAttributes(KeyValuePair <string, object> kvp) { if (kvp.Value == null) { return(null); } var attributes = new List <OtlpCommon.KeyValue>(); var attrib = new OtlpCommon.KeyValue { Key = kvp.Key, Value = new OtlpCommon.AnyValue { } }; switch (kvp.Value) { case string s: attrib.Value.StringValue = s; attributes.Add(attrib); break; case bool b: attrib.Value.BoolValue = b; attributes.Add(attrib); break; case int i: attrib.Value.IntValue = i; attributes.Add(attrib); break; case long l: attrib.Value.IntValue = l; attributes.Add(attrib); break; case double d: attrib.Value.DoubleValue = d; attributes.Add(attrib); break; case int[] intArray: foreach (var item in intArray) { attrib = new OtlpCommon.KeyValue { Key = kvp.Key, Value = new OtlpCommon.AnyValue { } }; attrib.Value.IntValue = item; attributes.Add(attrib); } break; case double[] doubleArray: foreach (var item in doubleArray) { attrib = new OtlpCommon.KeyValue { Key = kvp.Key, Value = new OtlpCommon.AnyValue { } }; attrib.Value.DoubleValue = item; attributes.Add(attrib); } break; case bool[] boolArray: foreach (var item in boolArray) { attrib = new OtlpCommon.KeyValue { Key = kvp.Key, Value = new OtlpCommon.AnyValue { } }; attrib.Value.BoolValue = item; attributes.Add(attrib); } break; case string[] stringArray: foreach (var item in stringArray) { attrib = new OtlpCommon.KeyValue { Key = kvp.Key, Value = new OtlpCommon.AnyValue { } }; attrib.Value.StringValue = item; attributes.Add(attrib); } break; default: attrib.Value.StringValue = kvp.Value.ToString(); attributes.Add(attrib); break; } return(attributes); }
public void ToOtlpResourceSpansTest(bool addResource) { var evenTags = new[] { new KeyValuePair <string, object>("k0", "v0") }; var oddTags = new[] { new KeyValuePair <string, object>("k1", "v1") }; var sources = new[] { new ActivitySource("even", "2.4.6"), new ActivitySource("odd", "1.3.5"), }; using var exporter = new OtlpTraceExporter( new OtlpExporterOptions(), new NoopTraceServiceClient()); if (addResource) { exporter.SetResource( ResourceBuilder.CreateEmpty().AddAttributes( new List <KeyValuePair <string, object> > { new KeyValuePair <string, object>(Resources.ResourceSemanticConventions.AttributeServiceName, "service-name"), new KeyValuePair <string, object>(Resources.ResourceSemanticConventions.AttributeServiceNamespace, "ns1"), }).Build()); } else { exporter.SetResource(Resources.Resource.Empty); } var builder = Sdk.CreateTracerProviderBuilder() .AddSource(sources[0].Name) .AddSource(sources[1].Name); using var openTelemetrySdk = builder.Build(); var processor = new BatchActivityExportProcessor(new TestExporter <Activity>(RunTest)); const int numOfSpans = 10; bool isEven; for (var i = 0; i < numOfSpans; i++) { isEven = i % 2 == 0; var source = sources[i % 2]; var activityKind = isEven ? ActivityKind.Client : ActivityKind.Server; var activityTags = isEven ? evenTags : oddTags; using Activity activity = source.StartActivity($"span-{i}", activityKind, parentContext: default, activityTags); processor.OnEnd(activity); } processor.Shutdown(); void RunTest(Batch <Activity> batch) { var request = new OtlpCollector.ExportTraceServiceRequest(); request.AddBatch(exporter.ProcessResource, batch); Assert.Single(request.ResourceSpans); var oltpResource = request.ResourceSpans.First().Resource; if (addResource) { Assert.Contains(oltpResource.Attributes, (kvp) => kvp.Key == Resources.ResourceSemanticConventions.AttributeServiceName && kvp.Value.StringValue == "service-name"); Assert.Contains(oltpResource.Attributes, (kvp) => kvp.Key == Resources.ResourceSemanticConventions.AttributeServiceNamespace && kvp.Value.StringValue == "ns1"); } else { Assert.Contains(oltpResource.Attributes, (kvp) => kvp.Key == Resources.ResourceSemanticConventions.AttributeServiceName && kvp.Value.ToString().Contains("unknown_service:")); } foreach (var instrumentationLibrarySpans in request.ResourceSpans.First().InstrumentationLibrarySpans) { Assert.Equal(numOfSpans / 2, instrumentationLibrarySpans.Spans.Count); Assert.NotNull(instrumentationLibrarySpans.InstrumentationLibrary); var expectedSpanNames = new List <string>(); var start = instrumentationLibrarySpans.InstrumentationLibrary.Name == "even" ? 0 : 1; for (var i = start; i < numOfSpans; i += 2) { expectedSpanNames.Add($"span-{i}"); } var otlpSpans = instrumentationLibrarySpans.Spans; Assert.Equal(expectedSpanNames.Count, otlpSpans.Count); var kv0 = new OtlpCommon.KeyValue { Key = "k0", Value = new OtlpCommon.AnyValue { StringValue = "v0" } }; var kv1 = new OtlpCommon.KeyValue { Key = "k1", Value = new OtlpCommon.AnyValue { StringValue = "v1" } }; var expectedTag = instrumentationLibrarySpans.InstrumentationLibrary.Name == "even" ? kv0 : kv1; foreach (var otlpSpan in otlpSpans) { Assert.Contains(otlpSpan.Name, expectedSpanNames); Assert.Contains(expectedTag, otlpSpan.Attributes); } } } }
public void ToOtlpResourceSpansTest() { var spanProcessor = new Mock <SpanProcessor>(); var evenResource = new Resource(new[] { new KeyValuePair <string, object>("k0", "v0") }); var oddResource = new Resource(new[] { new KeyValuePair <string, object>("k1", "v1") }); var tracers = new[] { TracerFactory.Create(b => b.SetResource(evenResource) .AddProcessorPipeline(p => p.AddProcessor(_ => spanProcessor.Object))) .GetTracer("even", "2.4.6"), TracerFactory.Create(b => b.SetResource(oddResource) .AddProcessorPipeline(p => p.AddProcessor(_ => spanProcessor.Object))) .GetTracer("odd", "1.3.5"), }; TelemetrySpan span = null; const int numOfSpans = 10; for (var i = 0; i < numOfSpans; i++) { var isEven = i % 2 == 0; var tracer = tracers[i % 2]; var spanKind = isEven ? SpanKind.Client : SpanKind.Server; if (span == null) { span = tracer.StartRootSpan("span-0", spanKind, null); } else { span = tracer.StartSpan($"span-{i}", span.Context, spanKind, null); } span.End(); } var spanDataList = new List <SpanData>(); var invocations = spanProcessor.Invocations; for (var i = 0; i < invocations.Count; i += 2 /* Just want one of the OnStart/OnEnd pair. */) { spanDataList.Add((SpanData)invocations[i].Arguments[0]); } spanDataList.Reverse(); var otlpResourceSpans = spanDataList.ToOtlpResourceSpans(); Assert.Equal(2, otlpResourceSpans.Count()); var evenAttribKeyValue = new OtlpCommon.KeyValue { Key = "k0", Value = new OtlpCommon.AnyValue { } }; evenAttribKeyValue.Value.StringValue = "v0"; foreach (var resourceSpans in otlpResourceSpans) { Assert.Single(resourceSpans.InstrumentationLibrarySpans); Assert.Equal(numOfSpans / 2, resourceSpans.InstrumentationLibrarySpans[0].Spans.Count); Assert.NotNull(resourceSpans.Resource); var expectedSpanNames = new List <string>(); var start = resourceSpans.Resource.Attributes.Contains(evenAttribKeyValue) ? 0 : 1; for (var i = start; i < numOfSpans; i += 2) { expectedSpanNames.Add($"span-{i}"); } var otlpSpans = resourceSpans.InstrumentationLibrarySpans[0].Spans; Assert.Equal(expectedSpanNames.Count, otlpSpans.Count); foreach (var otlpSpan in otlpSpans) { Assert.Contains(otlpSpan.Name, expectedSpanNames); } } }