Beispiel #1
0
        public void ExportOnlyWhenPointChanged(MetricReaderTemporalityPreference temporality)
        {
            using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{temporality}");

            var exportedItems = new List <Metric>();

            using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                      .AddMeter(meter.Name)
                                      .AddInMemoryExporter(exportedItems, metricReaderOptions =>
            {
                metricReaderOptions.TemporalityPreference = temporality;
            })
                                      .Build();

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

            counter.Add(10, new KeyValuePair <string, object>("tag1", "value1"));
            meterProvider.ForceFlush();
            Assert.Single(exportedItems);

            exportedItems.Clear();
            meterProvider.ForceFlush();
            if (temporality == MetricReaderTemporalityPreference.Cumulative)
            {
                Assert.Single(exportedItems);
            }
            else
            {
                Assert.Empty(exportedItems);
            }
        }
Beispiel #2
0
        public void SdkSupportsMultipleReaders(MetricReaderTemporalityPreference aggregationTemporality, bool hasViews)
        {
            var exportedItems1 = new List <Metric>();
            var exportedItems2 = new List <Metric>();

            using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{aggregationTemporality}.{hasViews}");

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

            int index  = 0;
            var values = new long[] { 100, 200, 300, 400 };

            long GetValue() => values[index++];

            var gauge = meter.CreateObservableGauge("gauge", () => GetValue());

            int indexSum  = 0;
            var valuesSum = new long[] { 1000, 1200, 1300, 1400 };

            long GetSum() => valuesSum[indexSum++];

            var observableCounter = meter.CreateObservableCounter("obs-counter", () => GetSum());

            var meterProviderBuilder = Sdk.CreateMeterProviderBuilder()
                                       .AddMeter(meter.Name)
                                       .AddInMemoryExporter(exportedItems1, metricReaderOptions =>
            {
                metricReaderOptions.TemporalityPreference = MetricReaderTemporalityPreference.Delta;
            })
                                       .AddInMemoryExporter(exportedItems2, metricReaderOptions =>
            {
                metricReaderOptions.TemporalityPreference = aggregationTemporality;
            });

            if (hasViews)
            {
                meterProviderBuilder.AddView("counter", "renamedCounter");
                meterProviderBuilder.AddView("gauge", "renamedGauge");
                meterProviderBuilder.AddView("obs-counter", "renamedObservableCounter");
            }

            using var meterProvider = meterProviderBuilder.Build();

            counter.Add(10, new KeyValuePair <string, object>("key", "value"));

            meterProvider.ForceFlush();

            Assert.Equal(3, exportedItems1.Count);
            Assert.Equal(3, exportedItems2.Count);

            if (hasViews)
            {
                Assert.Equal("renamedCounter", exportedItems1[0].Name);
                Assert.Equal("renamedCounter", exportedItems2[0].Name);

                Assert.Equal("renamedGauge", exportedItems1[1].Name);
                Assert.Equal("renamedGauge", exportedItems2[1].Name);

                Assert.Equal("renamedObservableCounter", exportedItems1[2].Name);
                Assert.Equal("renamedObservableCounter", exportedItems2[2].Name);
            }
            else
            {
                Assert.Equal("counter", exportedItems1[0].Name);
                Assert.Equal("counter", exportedItems2[0].Name);

                Assert.Equal("gauge", exportedItems1[1].Name);
                Assert.Equal("gauge", exportedItems2[1].Name);

                Assert.Equal("obs-counter", exportedItems1[2].Name);
                Assert.Equal("obs-counter", exportedItems2[2].Name);
            }

            // Check value exported for Counter
            AssertLongSumValueForMetric(exportedItems1[0], 10);
            AssertLongSumValueForMetric(exportedItems2[0], 10);

            // Check value exported for Gauge
            AssertLongSumValueForMetric(exportedItems1[1], 100);
            AssertLongSumValueForMetric(exportedItems2[1], 200);

            // Check value exported for ObservableCounter
            AssertLongSumValueForMetric(exportedItems1[2], 1000);
            if (aggregationTemporality == MetricReaderTemporalityPreference.Delta)
            {
                AssertLongSumValueForMetric(exportedItems2[2], 1200);
            }
            else
            {
                AssertLongSumValueForMetric(exportedItems2[2], 1200);
            }

            exportedItems1.Clear();
            exportedItems2.Clear();

            counter.Add(15, new KeyValuePair <string, object>("key", "value"));

            meterProvider.ForceFlush();

            Assert.Equal(3, exportedItems1.Count);
            Assert.Equal(3, exportedItems2.Count);

            // Check value exported for Counter
            AssertLongSumValueForMetric(exportedItems1[0], 15);
            if (aggregationTemporality == MetricReaderTemporalityPreference.Delta)
            {
                AssertLongSumValueForMetric(exportedItems2[0], 15);
            }
            else
            {
                AssertLongSumValueForMetric(exportedItems2[0], 25);
            }

            // Check value exported for Gauge
            AssertLongSumValueForMetric(exportedItems1[1], 300);
            AssertLongSumValueForMetric(exportedItems2[1], 400);

            // Check value exported for ObservableCounter
            AssertLongSumValueForMetric(exportedItems1[2], 300);
            if (aggregationTemporality == MetricReaderTemporalityPreference.Delta)
            {
                AssertLongSumValueForMetric(exportedItems2[2], 200);
            }
            else
            {
                AssertLongSumValueForMetric(exportedItems2[2], 1400);
            }
        }
        public void TestHistogramToOtlpMetric(string name, string description, string unit, long?longValue, double?doubleValue, MetricReaderTemporalityPreference aggregationTemporality, 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 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 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.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 == MetricReaderTemporalityPreference.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);
        }