Exemple #1
0
        public void TestHistogramToOltpMetric(string name, string description, string unit, long?longValue, double?doubleValue, AggregationTemporality aggregationTemporality, params object[] keysValues)
        {
            var metrics = new List <Metric>();

            var metricReader = new BaseExportingMetricReader(new InMemoryExporter <Metric>(metrics));

            metricReader.Temporality = aggregationTemporality;

            using var meter    = new Meter(Utils.GetCurrentMethodName());
            using var provider = Sdk.CreateMeterProviderBuilder()
                                 .AddMeter(meter.Name)
                                 .AddReader(metricReader)
                                 .Build();

            var attributes = ToAttributes(keysValues).ToArray();

            if (longValue.HasValue)
            {
                var histogram = meter.CreateHistogram <long>(name, unit, description);
                histogram.Record(longValue.Value, attributes);
            }
            else
            {
                var histogram = meter.CreateHistogram <double>(name, unit, description);
                histogram.Record(doubleValue.Value, attributes);
            }

            provider.ForceFlush();

            var batch = new Batch <Metric>(metrics.ToArray(), metrics.Count);

            var request = new OtlpCollector.ExportMetricsServiceRequest();

            request.AddMetrics(ResourceBuilder.CreateEmpty().Build().ToOtlpResource(), batch);

            var resourceMetric = request.ResourceMetrics.Single();
            var instrumentationLibraryMetrics = resourceMetric.InstrumentationLibraryMetrics.Single();
            var actual = instrumentationLibraryMetrics.Metrics.Single();

            Assert.Equal(name, actual.Name);
            Assert.Equal(description ?? string.Empty, actual.Description);
            Assert.Equal(unit ?? string.Empty, actual.Unit);

            Assert.Equal(OtlpMetrics.Metric.DataOneofCase.Histogram, actual.DataCase);

            Assert.Null(actual.Gauge);
            Assert.Null(actual.Sum);
            Assert.NotNull(actual.Histogram);
            Assert.Null(actual.ExponentialHistogram);
            Assert.Null(actual.Summary);

            var otlpAggregationTemporality = aggregationTemporality == AggregationTemporality.Cumulative
                ? OtlpMetrics.AggregationTemporality.Cumulative
                : OtlpMetrics.AggregationTemporality.Delta;

            Assert.Equal(otlpAggregationTemporality, actual.Histogram.AggregationTemporality);

            Assert.Single(actual.Histogram.DataPoints);
            var dataPoint = actual.Histogram.DataPoints.First();

            Assert.True(dataPoint.StartTimeUnixNano > 0);
            Assert.True(dataPoint.TimeUnixNano > 0);

            Assert.Equal(1UL, dataPoint.Count);

            if (longValue.HasValue)
            {
                Assert.Equal((double)longValue, dataPoint.Sum);
            }
            else
            {
                Assert.Equal(doubleValue, dataPoint.Sum);
            }

            int bucketIndex;

            for (bucketIndex = 0; bucketIndex < dataPoint.ExplicitBounds.Count; ++bucketIndex)
            {
                if (dataPoint.Sum <= dataPoint.ExplicitBounds[bucketIndex])
                {
                    break;
                }

                Assert.Equal(0UL, dataPoint.BucketCounts[bucketIndex]);
            }

            Assert.Equal(1UL, dataPoint.BucketCounts[bucketIndex]);

            if (attributes.Length > 0)
            {
                OtlpTestHelpers.AssertOtlpAttributes(attributes, dataPoint.Attributes);
            }
            else
            {
                Assert.Empty(dataPoint.Attributes);
            }

            Assert.Empty(dataPoint.Exemplars);

#pragma warning disable CS0612 // Type or member is obsolete
            Assert.Null(actual.IntGauge);
            Assert.Null(actual.IntSum);
            Assert.Null(actual.IntHistogram);
            Assert.Empty(dataPoint.Labels);
#pragma warning restore CS0612 // Type or member is obsolete
        }
        public void ToOtlpResourceMetricsTest(bool includeServiceNameInResource)
        {
            using var exporter = new OtlpMetricsExporter(
                      new OtlpExporterOptions(),
                      new NoopMetricsServiceClient());

            var resourceBuilder = ResourceBuilder.CreateEmpty();

            if (includeServiceNameInResource)
            {
                resourceBuilder.AddAttributes(
                    new List <KeyValuePair <string, object> >
                {
                    new KeyValuePair <string, object>(ResourceSemanticConventions.AttributeServiceName, "service-name"),
                    new KeyValuePair <string, object>(ResourceSemanticConventions.AttributeServiceNamespace, "ns1"),
                });
            }

            var tags = new KeyValuePair <string, object>[]
            {
                new KeyValuePair <string, object>("key1", "value1"),
                new KeyValuePair <string, object>("key2", "value2"),
            };

            var processor = new PullMetricProcessor(new TestExporter <MetricItem>(RunTest), true);

            using var provider = Sdk.CreateMeterProviderBuilder()
                                 .SetResourceBuilder(resourceBuilder)
                                 .AddSource("TestMeter")
                                 .AddMetricProcessor(processor)
                                 .Build();

            exporter.ParentProvider = provider;

            using var meter = new Meter("TestMeter", "0.0.1");

            var counter = meter.CreateCounter <int>("counter");

            counter.Add(100, tags);

            var testCompleted = false;

            // Invokes the TestExporter which will invoke RunTest
            processor.PullRequest();

            Assert.True(testCompleted);

            void RunTest(Batch <MetricItem> metricItem)
            {
                var request = new OtlpCollector.ExportMetricsServiceRequest();

                request.AddBatch(exporter.ProcessResource, metricItem);

                Assert.Single(request.ResourceMetrics);
                var resourceMetric = request.ResourceMetrics.First();
                var oltpResource   = resourceMetric.Resource;

                if (includeServiceNameInResource)
                {
                    Assert.Contains(oltpResource.Attributes, (kvp) => kvp.Key == ResourceSemanticConventions.AttributeServiceName && kvp.Value.StringValue == "service-name");
                    Assert.Contains(oltpResource.Attributes, (kvp) => kvp.Key == ResourceSemanticConventions.AttributeServiceNamespace && kvp.Value.StringValue == "ns1");
                }
                else
                {
                    Assert.Contains(oltpResource.Attributes, (kvp) => kvp.Key == ResourceSemanticConventions.AttributeServiceName && kvp.Value.ToString().Contains("unknown_service:"));
                }

                Assert.Single(resourceMetric.InstrumentationLibraryMetrics);
                var instrumentationLibraryMetrics = resourceMetric.InstrumentationLibraryMetrics.First();

                Assert.Equal(string.Empty, instrumentationLibraryMetrics.SchemaUrl);
                Assert.Equal("TestMeter", instrumentationLibraryMetrics.InstrumentationLibrary.Name);
                Assert.Equal("0.0.1", instrumentationLibraryMetrics.InstrumentationLibrary.Version);

                Assert.Single(instrumentationLibraryMetrics.Metrics);

                foreach (var metric in instrumentationLibraryMetrics.Metrics)
                {
                    Assert.Equal(string.Empty, metric.Description);
                    Assert.Equal(string.Empty, metric.Unit);
                    Assert.Equal("counter", metric.Name);

                    Assert.Equal(OtlpMetrics.Metric.DataOneofCase.Sum, metric.DataCase);
                    Assert.True(metric.Sum.IsMonotonic);
                    Assert.Equal(OtlpMetrics.AggregationTemporality.Delta, metric.Sum.AggregationTemporality);

                    Assert.Single(metric.Sum.DataPoints);
                    var dataPoint = metric.Sum.DataPoints.First();
                    Assert.True(dataPoint.StartTimeUnixNano > 0);
                    Assert.True(dataPoint.TimeUnixNano > 0);
                    Assert.Equal(OtlpMetrics.NumberDataPoint.ValueOneofCase.AsInt, dataPoint.ValueCase);
                    Assert.Equal(100, dataPoint.AsInt);

#pragma warning disable CS0612 // Type or member is obsolete
                    Assert.Empty(dataPoint.Labels);
#pragma warning restore CS0612 // Type or member is obsolete
                    OtlpTestHelpers.AssertOtlpAttributes(tags.ToList(), dataPoint.Attributes);

                    Assert.Empty(dataPoint.Exemplars);
                }

                testCompleted = true;
            }
        }
        public void TestCounterToOtlpMetric(string name, string description, string unit, long?longValue, double?doubleValue, MetricReaderTemporalityPreference aggregationTemporality, bool isMonotonic, params object[] keysValues)
        {
            var metrics = new List <Metric>();

            using var meter    = new Meter(Utils.GetCurrentMethodName());
            using var provider = Sdk.CreateMeterProviderBuilder()
                                 .AddMeter(meter.Name)
                                 .AddInMemoryExporter(metrics, metricReaderOptions =>
            {
                metricReaderOptions.TemporalityPreference = aggregationTemporality;
            })
                                 .Build();

            var attributes = ToAttributes(keysValues).ToArray();

            if (longValue.HasValue)
            {
                var counter = meter.CreateCounter <long>(name, unit, description);
                counter.Add(longValue.Value, attributes);
            }
            else
            {
                var counter = meter.CreateCounter <double>(name, unit, description);
                counter.Add(doubleValue.Value, attributes);
            }

            provider.ForceFlush();

            var batch = new Batch <Metric>(metrics.ToArray(), metrics.Count);

            var request = new OtlpCollector.ExportMetricsServiceRequest();

            request.AddMetrics(ResourceBuilder.CreateEmpty().Build().ToOtlpResource(), batch);

            var resourceMetric = request.ResourceMetrics.Single();
            var scopeMetrics   = resourceMetric.ScopeMetrics.Single();
            var actual         = scopeMetrics.Metrics.Single();

            Assert.Equal(name, actual.Name);
            Assert.Equal(description ?? string.Empty, actual.Description);
            Assert.Equal(unit ?? string.Empty, actual.Unit);

            Assert.Equal(OtlpMetrics.Metric.DataOneofCase.Sum, actual.DataCase);

            Assert.Null(actual.Gauge);
            Assert.NotNull(actual.Sum);
            Assert.Null(actual.Histogram);
            Assert.Null(actual.ExponentialHistogram);
            Assert.Null(actual.Summary);

            Assert.Equal(isMonotonic, actual.Sum.IsMonotonic);

            var otlpAggregationTemporality = aggregationTemporality == MetricReaderTemporalityPreference.Cumulative
                ? OtlpMetrics.AggregationTemporality.Cumulative
                : OtlpMetrics.AggregationTemporality.Delta;

            Assert.Equal(otlpAggregationTemporality, actual.Sum.AggregationTemporality);

            Assert.Single(actual.Sum.DataPoints);
            var dataPoint = actual.Sum.DataPoints.First();

            Assert.True(dataPoint.StartTimeUnixNano > 0);
            Assert.True(dataPoint.TimeUnixNano > 0);

            if (longValue.HasValue)
            {
                Assert.Equal(OtlpMetrics.NumberDataPoint.ValueOneofCase.AsInt, dataPoint.ValueCase);
                Assert.Equal(longValue, dataPoint.AsInt);
            }
            else
            {
                Assert.Equal(OtlpMetrics.NumberDataPoint.ValueOneofCase.AsDouble, dataPoint.ValueCase);
                Assert.Equal(doubleValue, dataPoint.AsDouble);
            }

            if (attributes.Length > 0)
            {
                OtlpTestHelpers.AssertOtlpAttributes(attributes, dataPoint.Attributes);
            }
            else
            {
                Assert.Empty(dataPoint.Attributes);
            }

            Assert.Empty(dataPoint.Exemplars);
        }
Exemple #4
0
        public void ToOtlpSpanTest()
        {
            using var activitySource = new ActivitySource(nameof(this.ToOtlpSpanTest));

            using var rootActivity = activitySource.StartActivity("root", ActivityKind.Producer);

            var attributes = new List <KeyValuePair <string, object> >
            {
                new KeyValuePair <string, object>("bool", true),
                new KeyValuePair <string, object>("long", 1L),
                new KeyValuePair <string, object>("string", "text"),
                new KeyValuePair <string, object>("double", 3.14),
                new KeyValuePair <string, object>("int", 1),
                new KeyValuePair <string, object>("datetime", DateTime.UtcNow),
                new KeyValuePair <string, object>("bool_array", new bool[] { true, false }),
                new KeyValuePair <string, object>("int_array", new int[] { 1, 2 }),
                new KeyValuePair <string, object>("double_array", new double[] { 1.0, 2.09 }),
                new KeyValuePair <string, object>("string_array", new string[] { "a", "b" }),
            };

            foreach (var kvp in attributes)
            {
                rootActivity.SetTag(kvp.Key, kvp.Value);
            }

            var startTime = new DateTime(2020, 02, 20, 20, 20, 20, DateTimeKind.Utc);

            DateTimeOffset dateTimeOffset;

            dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(0);

            var expectedUnixTimeTicks = (ulong)(startTime.Ticks - dateTimeOffset.Ticks);
            var duration = TimeSpan.FromMilliseconds(1555);

            rootActivity.SetStartTime(startTime);
            rootActivity.SetEndTime(startTime + duration);

            Span <byte> traceIdSpan = stackalloc byte[16];

            rootActivity.TraceId.CopyTo(traceIdSpan);
            var traceId = traceIdSpan.ToArray();

            var otlpSpan = rootActivity.ToOtlpSpan();

            Assert.NotNull(otlpSpan);
            Assert.Equal("root", otlpSpan.Name);
            Assert.Equal(OtlpTrace.Span.Types.SpanKind.Producer, otlpSpan.Kind);
            Assert.Equal(traceId, otlpSpan.TraceId);
            Assert.Empty(otlpSpan.ParentSpanId);
            Assert.Null(otlpSpan.Status);
            Assert.Empty(otlpSpan.Events);
            Assert.Empty(otlpSpan.Links);
            OtlpTestHelpers.AssertOtlpAttributes(attributes, otlpSpan.Attributes);

            var expectedStartTimeUnixNano = 100 * expectedUnixTimeTicks;

            Assert.Equal(expectedStartTimeUnixNano, otlpSpan.StartTimeUnixNano);
            var expectedEndTimeUnixNano = expectedStartTimeUnixNano + (duration.TotalMilliseconds * 1_000_000);

            Assert.Equal(expectedEndTimeUnixNano, otlpSpan.EndTimeUnixNano);

            var childLinks = new List <ActivityLink> {
                new ActivityLink(rootActivity.Context, new ActivityTagsCollection(attributes))
            };
            var childActivity = activitySource.StartActivity(
                "child",
                ActivityKind.Client,
                rootActivity.Context,
                links: childLinks);

            childActivity.SetStatus(Status.Error);

            var childEvents = new List <ActivityEvent> {
                new ActivityEvent("e0"), new ActivityEvent("e1", default, new ActivityTagsCollection(attributes))
        public void ToOtlpResourceMetricsTest(bool includeServiceNameInResource)
        {
            var resourceBuilder = ResourceBuilder.CreateEmpty();

            if (includeServiceNameInResource)
            {
                resourceBuilder.AddAttributes(
                    new List <KeyValuePair <string, object> >
                {
                    new KeyValuePair <string, object>(ResourceSemanticConventions.AttributeServiceName, "service-name"),
                    new KeyValuePair <string, object>(ResourceSemanticConventions.AttributeServiceNamespace, "ns1"),
                });
            }

            var tags = new KeyValuePair <string, object>[]
            {
                new KeyValuePair <string, object>("key1", "value1"),
                new KeyValuePair <string, object>("key2", "value2"),
            };

            using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{includeServiceNameInResource}", "0.0.1");

            var exportedItems = new List <Metric>();

            using var provider = Sdk.CreateMeterProviderBuilder()
                                 .SetResourceBuilder(resourceBuilder)
                                 .AddMeter(meter.Name)
                                 .AddReader(new BaseExportingMetricReader(new InMemoryExporter <Metric>(exportedItems))
            {
                PreferredAggregationTemporality = AggregationTemporality.Delta
            })
                                 .Build();

            var counter = meter.CreateCounter <int>("counter");

            counter.Add(100, tags);

            var testCompleted = false;

            provider.ForceFlush();

            var batch = new Batch <Metric>(exportedItems.ToArray(), exportedItems.Count);

            RunTest(batch);

            Assert.True(testCompleted);

            void RunTest(Batch <Metric> metrics)
            {
                var request = new OtlpCollector.ExportMetricsServiceRequest();

                request.AddMetrics(resourceBuilder.Build().ToOtlpResource(), metrics);

                Assert.Single(request.ResourceMetrics);
                var resourceMetric = request.ResourceMetrics.First();
                var oltpResource   = resourceMetric.Resource;

                if (includeServiceNameInResource)
                {
                    Assert.Contains(oltpResource.Attributes, (kvp) => kvp.Key == ResourceSemanticConventions.AttributeServiceName && kvp.Value.StringValue == "service-name");
                    Assert.Contains(oltpResource.Attributes, (kvp) => kvp.Key == ResourceSemanticConventions.AttributeServiceNamespace && kvp.Value.StringValue == "ns1");
                }
                else
                {
                    Assert.Contains(oltpResource.Attributes, (kvp) => kvp.Key == ResourceSemanticConventions.AttributeServiceName && kvp.Value.ToString().Contains("unknown_service:"));
                }

                Assert.Single(resourceMetric.InstrumentationLibraryMetrics);
                var instrumentationLibraryMetrics = resourceMetric.InstrumentationLibraryMetrics.First();

                Assert.Equal(string.Empty, instrumentationLibraryMetrics.SchemaUrl);
                Assert.Equal(meter.Name, instrumentationLibraryMetrics.InstrumentationLibrary.Name);
                Assert.Equal("0.0.1", instrumentationLibraryMetrics.InstrumentationLibrary.Version);

                Assert.Single(instrumentationLibraryMetrics.Metrics);

                foreach (var metric in instrumentationLibraryMetrics.Metrics)
                {
                    Assert.Equal(string.Empty, metric.Description);
                    Assert.Equal(string.Empty, metric.Unit);
                    Assert.Equal("counter", metric.Name);

                    Assert.Equal(OtlpMetrics.Metric.DataOneofCase.Sum, metric.DataCase);
                    Assert.True(metric.Sum.IsMonotonic);
                    Assert.Equal(OtlpMetrics.AggregationTemporality.Delta, metric.Sum.AggregationTemporality);

                    Assert.Single(metric.Sum.DataPoints);
                    var dataPoint = metric.Sum.DataPoints.First();
                    Assert.True(dataPoint.StartTimeUnixNano > 0);
                    Assert.True(dataPoint.TimeUnixNano > 0);
                    Assert.Equal(OtlpMetrics.NumberDataPoint.ValueOneofCase.AsInt, dataPoint.ValueCase);
                    Assert.Equal(100, dataPoint.AsInt);

#pragma warning disable CS0612 // Type or member is obsolete
                    Assert.Empty(dataPoint.Labels);
#pragma warning restore CS0612 // Type or member is obsolete
                    OtlpTestHelpers.AssertOtlpAttributes(tags.ToList(), dataPoint.Attributes);

                    Assert.Empty(dataPoint.Exemplars);
                }

                testCompleted = true;
            }
        }