Exemplo n.º 1
0
        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;
            }
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 5
0
        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);
                }
            }
        }