Example #1
0
        public void ObserverCallbackExceptionTest()
        {
            using var meter = new Meter(Utils.GetCurrentMethodName());
            var exportedItems = new List <Metric>();

            using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                      .AddMeter(meter.Name)
                                      .AddInMemoryExporter(exportedItems)
                                      .Build();

            var measurement = new Measurement <int>(100, new("name", "apple"), new("color", "red"));

            meter.CreateObservableGauge("myGauge", () => measurement);
            meter.CreateObservableGauge <long>("myBadGauge", observeValues: () => throw new Exception("gauge read error"));

            meterProvider.ForceFlush(MaxTimeToAllowForFlush);
            Assert.Single(exportedItems);
            var metric = exportedItems[0];

            Assert.Equal("myGauge", metric.Name);
            List <MetricPoint> metricPoints = new List <MetricPoint>();

            foreach (ref readonly var mp in metric.GetMetricPoints())
            {
                metricPoints.Add(mp);
            }

            Assert.Single(metricPoints);
            var metricPoint = metricPoints[0];

            Assert.Equal(100, metricPoint.GetGaugeLastValueLong());
            Assert.True(metricPoint.Tags.Count > 0);
        }
    static Program()
    {
        var process = Process.GetCurrentProcess();

        StressMeter.CreateObservableGauge("Process.NonpagedSystemMemorySize64", () => process.NonpagedSystemMemorySize64);
        StressMeter.CreateObservableGauge("Process.PagedSystemMemorySize64", () => process.PagedSystemMemorySize64);
        StressMeter.CreateObservableGauge("Process.PagedMemorySize64", () => process.PagedMemorySize64);
        StressMeter.CreateObservableGauge("Process.WorkingSet64", () => process.WorkingSet64);
        StressMeter.CreateObservableGauge("Process.VirtualMemorySize64", () => process.VirtualMemorySize64);
    }
Example #3
0
        public void ValidateOneDimension(MetricType metricType)
        {
            var metrics = new List <Metric>();

            using var meter    = new Meter(nameof(ValidateOneDimension));
            using var provider = Sdk.CreateMeterProviderBuilder()
                                 .AddMeter(meter.Name)
                                 .AddInMemoryExporter(metrics)
                                 .Build();

            var    dataPointType = DataPointType.Aggregation;
            string name          = null;

            if (metricType == MetricType.DoubleSum)
            {
                name = "TestDoubleCounter";
                var doubleCounter = meter.CreateCounter <double>(name);
                doubleCounter.Add(123.45, new KeyValuePair <string, object>("tag", "value"));
            }
            else if (metricType == MetricType.DoubleGauge)
            {
                name = "TestGauge";
                meter.CreateObservableGauge(
                    name,
                    () => new List <Measurement <double> >()
                {
                    new(123.45, new KeyValuePair <string, object>("tag", "value")),
                });
        public void MeterSourcesWildcardSupportMatchTest(bool hasView)
        {
            var meterNames = new[]
            {
                "AbcCompany.XyzProduct.ComponentA",
                "abcCompany.xYzProduct.componentC", // Wildcard match is case insensitive.
                "DefCompany.AbcProduct.ComponentC",
                "DefCompany.XyzProduct.ComponentC", // Wildcard match supports matching multiple patterns.
                "GhiCompany.qweProduct.ComponentN",
                "SomeCompany.SomeProduct.SomeComponent",
            };

            using var meter1 = new Meter(meterNames[0]);
            using var meter2 = new Meter(meterNames[1]);
            using var meter3 = new Meter(meterNames[2]);
            using var meter4 = new Meter(meterNames[3]);
            using var meter5 = new Meter(meterNames[4]);
            using var meter6 = new Meter(meterNames[5]);

            var exportedItems        = new List <Metric>();
            var meterProviderBuilder = Sdk.CreateMeterProviderBuilder()
                                       .AddMeter("AbcCompany.XyzProduct.*")
                                       .AddMeter("DefCompany.*.ComponentC")
                                       .AddMeter("GhiCompany.qweProduct.ComponentN") // Mixing of non-wildcard meter name and wildcard meter name.
                                       .AddInMemoryExporter(exportedItems);

            if (hasView)
            {
                meterProviderBuilder.AddView("myGauge1", "newName");
            }

            using var meterProvider = meterProviderBuilder.Build();

            var measurement = new Measurement <int>(100, new("name", "apple"), new("color", "red"));

            meter1.CreateObservableGauge("myGauge1", () => measurement);
            meter2.CreateObservableGauge("myGauge2", () => measurement);
            meter3.CreateObservableGauge("myGauge3", () => measurement);
            meter4.CreateObservableGauge("myGauge4", () => measurement);
            meter5.CreateObservableGauge("myGauge5", () => measurement);
            meter6.CreateObservableGauge("myGauge6", () => measurement);

            meterProvider.ForceFlush(MaxTimeToAllowForFlush);

            Assert.True(exportedItems.Count == 5); // "SomeCompany.SomeProduct.SomeComponent" will not be subscribed.

            if (hasView)
            {
                Assert.Equal("newName", exportedItems[0].Name);
            }
            else
            {
                Assert.Equal("myGauge1", exportedItems[0].Name);
            }

            Assert.Equal("myGauge2", exportedItems[1].Name);
            Assert.Equal("myGauge3", exportedItems[2].Name);
            Assert.Equal("myGauge4", exportedItems[3].Name);
            Assert.Equal("myGauge5", exportedItems[4].Name);
        }
        public void ObserverCallbackTest()
        {
            using var meter = new Meter("ObserverCallbackErrorTest");
            var exportedItems = new List <Metric>();

            using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                      .AddMeter(meter.Name)
                                      .AddInMemoryExporter(exportedItems)
                                      .Build();

            var measurement = new Measurement <int>(100, new("name", "apple"), new("color", "red"));

            meter.CreateObservableGauge("myGauge", () => measurement);

            meterProvider.ForceFlush(MaxTimeToAllowForFlush);
            Assert.Single(exportedItems);
            var metric = exportedItems[0];

            Assert.Equal("myGauge", metric.Name);
            List <MetricPoint> metricPoints = new List <MetricPoint>();

            foreach (ref var mp in metric.GetMetricPoints())
            {
                metricPoints.Add(mp);
            }

            Assert.Single(metricPoints);
            var metricPoint = metricPoints[0];

            Assert.Equal(100, metricPoint.LongValue);
            Assert.NotNull(metricPoint.Keys);
            Assert.NotNull(metricPoint.Values);
        }
Example #6
0
        public void GaugeZeroDimensionWithDescription()
        {
            var buffer  = new byte[85000];
            var metrics = new List <Metric>();

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

            meter.CreateObservableGauge("test_gauge", () => 123, description: "Hello, world!");

            provider.ForceFlush();

            var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]);

            Assert.Matches(
                ("^"
                 + "# HELP test_gauge Hello, world!\n"
                 + "# TYPE test_gauge gauge\n"
                 + "test_gauge 123 \\d+\n"
                 + "$").Replace('\'', '"'),
                Encoding.UTF8.GetString(buffer, 0, cursor));
        }
Example #7
0
        public void GaugeOneDimension()
        {
            var buffer  = new byte[85000];
            var metrics = new List <Metric>();

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

            meter.CreateObservableGauge(
                "test_gauge",
                () => new Measurement <long>(123, new KeyValuePair <string, object>("tagKey", "tagValue")));

            provider.ForceFlush();

            var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]);

            Assert.Matches(
                ("^"
                 + "# TYPE test_gauge gauge\n"
                 + "test_gauge{tagKey='tagValue'} 123 \\d+\n"
                 + "$").Replace('\'', '"'),
                Encoding.UTF8.GetString(buffer, 0, cursor));
        }
        public void MeterSourcesWildcardSupportNegativeTestNoMeterAdded(bool hasView)
        {
            var meterNames = new[]
            {
                "AbcCompany.XyzProduct.ComponentA",
                "abcCompany.xYzProduct.componentC",
            };

            using var meter1 = new Meter(meterNames[0]);
            using var meter2 = new Meter(meterNames[1]);

            var exportedItems        = new List <Metric>();
            var meterProviderBuilder = Sdk.CreateMeterProviderBuilder()
                                       .AddInMemoryExporter(exportedItems);

            if (hasView)
            {
                meterProviderBuilder.AddView("gauge1", "renamed");
            }

            using var meterProvider = meterProviderBuilder.Build();
            var measurement = new Measurement <int>(100, new("name", "apple"), new("color", "red"));

            meter1.CreateObservableGauge("myGauge1", () => measurement);
            meter2.CreateObservableGauge("myGauge2", () => measurement);

            meterProvider.ForceFlush(MaxTimeToAllowForFlush);
            Assert.True(exportedItems.Count == 0);
        }
Example #9
0
    static Program()
    {
        var process = Process.GetCurrentProcess();

        MyMeter.CreateObservableCounter("Thread.CpuTime", () => GetThreadCpuTime(process), "ms");

        MyMeter.CreateObservableGauge("Thread.State", () => GetThreadState(process));
    }
Example #10
0
        private static string WriteLongGauge(Meter meter, KeyValuePair <string, object>[] tags, string tagsExpected)
        {
            var gauge = meter.CreateObservableGauge(
                "gauge_long",
                () => new Measurement <long>[] { new Measurement <long>(18, tags) });

            return($"# TYPE gauge_long gauge\ngauge_long{tagsExpected} 18 1633041000000\n");
        }
Example #11
0
        private void InitializeNewMetric(string metricName, string metricDescription)
        {
            var gauge = azureMonitorMeter.CreateObservableGauge <double>(metricName, description: metricDescription, observeValues: () => ReportMeasurementsForMetric(metricName));

            _gauges.TryAdd(metricName, gauge);

            _measurements.TryAdd(metricName, new HashSet <Measurement <double> >());
        }
Example #12
0
    static Program()
    {
        var process = Process.GetCurrentProcess();

        MyMeter.CreateObservableGauge <long>(
            "MyProcessWorkingSetGauge",
            () => new List <Measurement <long> >()
        {
            new(process.WorkingSet64, new("process.id", process.Id), new("process.bitness", IntPtr.Size << 3)),
        });
Example #13
0
        private static string WriteDoubleGauge(Meter meter, KeyValuePair <string, object>[] tags, string tagsExpected)
        {
            var value = 0.18F;

            var gauge = meter.CreateObservableGauge(
                "gauge_double",
                () => new Measurement <float>[] { new Measurement <float>(99F, tags), new Measurement <float>(value, tags) });

            return($"# TYPE gauge_double gauge\ngauge_double{tagsExpected} {(double)value} 1633041000000\n");
        }
Example #14
0
        public void ViewToDropSingleInstrumentObservableGauge()
        {
            using var meter = new Meter(Utils.GetCurrentMethodName());
            var exportedItems = new List <Metric>();

            using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                      .AddMeter(meter.Name)
                                      .AddView("observableGaugeNotInteresting", MetricStreamConfiguration.Drop)
                                      .AddInMemoryExporter(exportedItems)
                                      .Build();

            // Expecting one metric stream.
            meter.CreateObservableGauge("observableGaugeNotInteresting", () => { return(10); }, "ms");
            meter.CreateObservableGauge("observableGaugeInteresting", () => { return(10); }, "ms");

            meterProvider.ForceFlush(MaxTimeToAllowForFlush);
            Assert.Single(exportedItems);
            var metric = exportedItems[0];

            Assert.Equal("observableGaugeInteresting", metric.Name);
        }
Example #15
0
        public void GaugeDoubleSubnormal()
        {
            var buffer  = new byte[85000];
            var metrics = new List <Metric>();

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

            meter.CreateObservableGauge("test_gauge", () => new List <Measurement <double> >
            {
                new(double.NegativeInfinity, new("x", "1"), new("y", "2")),
                new(double.PositiveInfinity, new("x", "3"), new("y", "4")),
                new(double.NaN, new("x", "5"), new("y", "6")),
            });
        public async void When_ObservableGauge_Is_Recorded_Should_Export_To_Prometheus()
        {
            // arrange
            var observeValue = new Mock <Func <Measurement <int> > >();
            var stationEui   = new StationEui(1);
            var measurement  = new Measurement <int>(1, KeyValuePair.Create(MetricRegistry.ConcentratorIdTagName, (object?)stationEui));

            observeValue.Setup(ov => ov.Invoke()).Returns(measurement);
            using var meter = new Meter("LoRaWan", "1.0");
            _ = meter.CreateObservableGauge(ObservableGauge.Name, observeValue.Object);

            // act
            this.prometheusMetricExporter.Start();

            // assert
            await observeValue.RetryVerifyAsync(ov => ov.Invoke(), Times.Once);

            this.recordObservableGaugeMock.Verify(r => r.Invoke(ObservableGauge.Name, new[] { stationEui.ToString() }, measurement.Value), Times.Once);
        }
Example #17
0
        public void ObservableInstrumentCallbacksInvokedForEachReaders(bool hasViews)
        {
            var exportedItems1 = new List <Metric>();
            var exportedItems2 = new List <Metric>();

            using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{hasViews}");
            int callbackInvocationCount = 0;
            var gauge = meter.CreateObservableGauge("gauge", () =>
            {
                callbackInvocationCount++;
                return(10 * callbackInvocationCount);
            });

            var meterProviderBuilder = Sdk.CreateMeterProviderBuilder()
                                       .AddMeter(meter.Name)
                                       .AddInMemoryExporter(exportedItems1)
                                       .AddInMemoryExporter(exportedItems2);

            if (hasViews)
            {
                meterProviderBuilder.AddView("gauge", "renamedGauge");
            }

            using var meterProvider = meterProviderBuilder.Build();
            meterProvider.ForceFlush();

            // VALIDATE
            Assert.Equal(2, callbackInvocationCount);
            Assert.Single(exportedItems1);
            Assert.Single(exportedItems2);

            if (hasViews)
            {
                Assert.Equal("renamedGauge", exportedItems1[0].Name);
                Assert.Equal("renamedGauge", exportedItems2[0].Name);
            }
            else
            {
                Assert.Equal("gauge", exportedItems1[0].Name);
                Assert.Equal("gauge", exportedItems2[0].Name);
            }
        }
Example #18
0
        public void ValidateZeroDimension(MetricType metricType)
        {
            var metrics = new List <Metric>();

            using var meter    = new Meter(nameof(ValidateZeroDimension));
            using var provider = Sdk.CreateMeterProviderBuilder()
                                 .AddMeter(meter.Name)
                                 .AddInMemoryExporter(metrics)
                                 .Build();

            var    dataPointType = DataPointType.Aggregation;
            string name          = null;

            if (metricType == MetricType.DoubleSum)
            {
                name = "TestDoubleCounter";
                var doubleCounter = meter.CreateCounter <double>(name);
                doubleCounter.Add(123.45);
            }
            else if (metricType == MetricType.DoubleGauge)
            {
                name = "TestGauge";
                meter.CreateObservableGauge(name, () => 123.45);
                dataPointType = DataPointType.Measurement;
            }

            provider.ForceFlush();

            var enumerator = metrics[0].GetMetricPoints().GetEnumerator();

            enumerator.MoveNext();
            var metricPoint = enumerator.Current;

            var metricData = new MetricsData(Version, metrics[0], ref metricPoint);

            Assert.Equal(2, metricData.Version);
            Assert.Equal(name, metricData.Metrics.First().Name);
            Assert.Equal(123.45, metricData.Metrics.First().Value);
            Assert.Equal(dataPointType, metricData.Metrics.First().DataPointType);
            // Properties will contain _MS.AggregationIntervalMs
            Assert.Equal(1, metricData.Properties.Count);
        }
Example #19
0
        public async void When_ObservableGauge_Is_Recorded_Should_Export_To_ApplicationInsights()
        {
            // arrange
            var observeValue = new Mock <Func <Measurement <int> > >();
            var stationEui   = new StationEui(1);
            var measurement  = new Measurement <int>(1, KeyValuePair.Create(MetricRegistry.ConcentratorIdTagName, (object)stationEui));

            _ = observeValue.Setup(ov => ov.Invoke()).Returns(measurement);
            using var meter = new Meter("LoRaWan", "1.0");
            _ = meter.CreateObservableGauge(ObservableGaugeMetric.Name, observeValue.Object);

            // act
            this.applicationInsightsMetricExporter.Start();

            // assert
            await this.trackValueMock.RetryVerifyAsync(me => me.Invoke(It.Is <Metric>(m => m.Identifier.MetricNamespace == MetricRegistry.Namespace &&
                                                                                      m.Identifier.MetricId == ObservableGaugeMetric.Name),
                                                                       measurement.Value,
                                                                       new[] { stationEui.ToString() }),
                                                       Times.Once);
        }
Example #20
0
    public static async Task Main(string[] args)
    {
        using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                  .AddSource("TestMeter")
                                  .AddConsoleExporter()
                                  .Build();

        ObservableGauge <long> gauge = MyMeter.CreateObservableGauge <long>(
            "Gauge",
            () =>
        {
            var tag1 = new KeyValuePair <string, object>("tag1", "value1");
            var tag2 = new KeyValuePair <string, object>("tag2", "value2");

            return(new List <Measurement <long> >()
            {
                new Measurement <long>(RandomGenerator.Next(1, 1000), tag1, tag2),
            });
        });

        await Task.Delay(10000);
    }
Example #21
0
    public static void Stress(int concurrency = 0, int prometheusPort = 0)
    {
#if DEBUG
        Console.WriteLine("***WARNING*** The current build is DEBUG which may affect timing!");
        Console.WriteLine();
#endif

        if (concurrency < 0)
        {
            throw new ArgumentOutOfRangeException(nameof(concurrency), "concurrency level should be a non-negative number.");
        }

        if (concurrency == 0)
        {
            concurrency = Environment.ProcessorCount;
        }

        using var meter = new Meter("OpenTelemetry.Tests.Stress." + Guid.NewGuid().ToString("D"));
        var cntLoopsTotal = 0UL;
        meter.CreateObservableCounter(
            "OpenTelemetry.Tests.Stress.Loops",
            () => unchecked ((long)cntLoopsTotal),
            description: "The total number of `Run()` invocations that are completed.");
        var dLoopsPerSecond = 0D;
        meter.CreateObservableGauge(
            "OpenTelemetry.Tests.Stress.LoopsPerSecond",
            () => dLoopsPerSecond,
            description: "The rate of `Run()` invocations based on a small sliding window of few hundreds of milliseconds.");
        var dCpuCyclesPerLoop = 0D;
#if NET462
        if (Environment.OSVersion.Platform == PlatformID.Win32NT)
#else
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
#endif
        {
            meter.CreateObservableGauge(
                "OpenTelemetry.Tests.Stress.CpuCyclesPerLoop",
                () => dCpuCyclesPerLoop,
                description: "The average CPU cycles for each `Run()` invocation, based on a small sliding window of few hundreds of milliseconds.");
        }

        using var meterProvider = prometheusPort != 0 ? Sdk.CreateMeterProviderBuilder()
                                  .AddMeter(StressMeter.Name)
                                  .AddMeter(meter.Name)
                                  .AddPrometheusExporter(options =>
        {
            options.StartHttpListener    = true;
            options.HttpListenerPrefixes = new string[] { $"http://localhost:{prometheusPort}/" };
            options.ScrapeResponseCacheDurationMilliseconds = 0;
        })
                                  .Build() : null;

        var statistics    = new long[concurrency];
        var watchForTotal = new Stopwatch();
        watchForTotal.Start();

        Parallel.Invoke(
            () =>
        {
            Console.Write($"Running (concurrency = {concurrency}");

            if (prometheusPort != 0)
            {
                Console.Write($", prometheusEndpoint = http://localhost:{prometheusPort}/metrics/");
            }

            Console.WriteLine("), press <Esc> to stop...");

            var bOutput = false;
            var watch   = new Stopwatch();
            while (true)
            {
                if (Console.KeyAvailable)
                {
                    var key = Console.ReadKey(true).Key;

                    switch (key)
                    {
                    case ConsoleKey.Enter:
                        Console.WriteLine(string.Format("{0} {1}", DateTime.UtcNow.ToString("O"), output));
                        break;

                    case ConsoleKey.Escape:
                        bContinue = false;
                        return;

                    case ConsoleKey.Spacebar:
                        bOutput = !bOutput;
                        break;
                    }

                    continue;
                }

                if (bOutput)
                {
                    Console.WriteLine(string.Format("{0} {1}", DateTime.UtcNow.ToString("O"), output));
                }

                var cntLoopsOld     = (ulong)statistics.Sum();
                var cntCpuCyclesOld = GetCpuCycles();

                watch.Restart();
                Thread.Sleep(200);
                watch.Stop();

                cntLoopsTotal       = (ulong)statistics.Sum();
                var cntCpuCyclesNew = GetCpuCycles();

                var nLoops     = cntLoopsTotal - cntLoopsOld;
                var nCpuCycles = cntCpuCyclesNew - cntCpuCyclesOld;

                dLoopsPerSecond   = (double)nLoops / ((double)watch.ElapsedMilliseconds / 1000.0);
                dCpuCyclesPerLoop = nLoops == 0 ? 0 : nCpuCycles / nLoops;

                output        = $"Loops: {cntLoopsTotal:n0}, Loops/Second: {dLoopsPerSecond:n0}, CPU Cycles/Loop: {dCpuCyclesPerLoop:n0}";
                Console.Title = output;
            }
        },
            () =>
        {
            Parallel.For(0, concurrency, (i) =>
            {
                statistics[i] = 0;
                while (bContinue)
                {
                    Run();
                    statistics[i]++;
                }
            });
        });

        watchForTotal.Stop();
        cntLoopsTotal = (ulong)statistics.Sum();
        var totalLoopsPerSecond   = (double)cntLoopsTotal / ((double)watchForTotal.ElapsedMilliseconds / 1000.0);
        var cntCpuCyclesTotal     = GetCpuCycles();
        var cpuCyclesPerLoopTotal = cntLoopsTotal == 0 ? 0 : cntCpuCyclesTotal / cntLoopsTotal;
        Console.WriteLine("Stopping the stress test...");
        Console.WriteLine($"* Total Loops: {cntLoopsTotal:n0}");
        Console.WriteLine($"* Average Loops/Second: {totalLoopsPerSecond:n0}");
        Console.WriteLine($"* Average CPU Cycles/Loop: {cpuCyclesPerLoopTotal:n0}");
    }
Example #22
0
        public void TestGaugeToOtlpMetric(string name, string description, string unit, long?longValue, double?doubleValue)
        {
            var metrics = new List <Metric>();

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

            if (longValue.HasValue)
            {
                meter.CreateObservableGauge(name, () => longValue.Value, unit, description);
            }
            else
            {
                meter.CreateObservableGauge(name, () => doubleValue.Value, unit, description);
            }

            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.Gauge, actual.DataCase);

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

            Assert.Single(actual.Gauge.DataPoints);
            var dataPoint = actual.Gauge.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);
            }

            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
        }
Example #23
0
        private static void Main()
        {
            // Uncomment this to suppress the default sample metrics.
            //Metrics.SuppressDefaultMetrics();

            // Replace the first line with an appropriate type of tester to run different manual tests.
            //var tester = new MetricPusherTester();
            //var tester = new KestrelMetricServerTester();
            var tester = new AspNetCoreMiddlewareTester();

            //var tester = new GrpcMiddlewareTester();
            //var tester = new MetricServerTester();

            // For testing Kestrel metric server with HTTPS, you need at least a self-signed certificate (one included here)
            // and the matching domain pointed to 127.0.0.1 (e.g. hardcoded in the PCs hosts file) and you also need to
            // import this certificate into your Trusted Root Certification Authorities certificate store to trust it.
            //var certificate = new X509Certificate2("prometheus-net.test.pfx", "prometheus-net.test");
            //var tester = new KestrelMetricServerTester("prometheus-net.test", certificate);

            tester.OnStart();

            var metricServer = tester.InitializeMetricServer();

            metricServer?.Start();

            var counter = Metrics.CreateCounter("myCounter", "help text", new CounterConfiguration
            {
                LabelNames = new[] { "method", "endpoint" }
            });

            counter.WithLabels("GET", "/").Inc();
            counter.WithLabels("POST", "/cancel").Inc();

            Metrics.CreateCounter("always_zero", "This counter is always zero but still needs to be present in the output!");

            var gauge = Metrics.CreateGauge("gauge", "help text");

            gauge.Inc(3.4);
            gauge.Dec(2.1);
            gauge.Set(5.3);

            // As the initial value is suppressed and a new one never assigned, this one never shows up in the export.
            Metrics.CreateGauge("should_not_show_up", "", new GaugeConfiguration
            {
                SuppressInitialValue = true
            });

            var hist = Metrics.CreateHistogram("myHistogram", "help text", new HistogramConfiguration
            {
                Buckets = new[] { 0, 0.2, 0.4, 0.6, 0.8, 0.9 }
            });

            hist.Observe(0.4);

            var timedHistogram = Metrics.CreateHistogram("myTimedHistogram", "help text", new HistogramConfiguration
            {
                Buckets = new[] { 0, 0.2, 0.4, 0.6, 0.8, 0.9 }
            });

            var latestGauge = Metrics.CreateGauge("latestGauge", "Reports the latest cycle time");

            var summary = Metrics.CreateSummary("mySummary", "help text");

            summary.Observe(5.3);

            // Example implementation of updating values before every collection.
            var collectionCount = Metrics.CreateCounter("beforecollect_example", "This counter is incremented before every data collection.");

            // Synchronous callbacks should be instantaneous, to avoid causing delays in the pipeline.
            Metrics.DefaultRegistry.AddBeforeCollectCallback(() => collectionCount.Inc());

            var googlePageBytes = Metrics.CreateCounter("beforecollect_async_example", "This counter is incremented before every data collection, but asynchronously.");

            // Callbacks can also be asynchronous. It is fine for these to take a bit more time.
            // For example, you can make an asynchronous HTTP request to a remote system in such a callback.
            var httpClient = new HttpClient();

            Metrics.DefaultRegistry.AddBeforeCollectCallback(async(cancel) =>
            {
                // Probe a remote system.
                var response = await httpClient.GetAsync("https://google.com", cancel);

                // Increase a counter by however many bytes we loaded.
                googlePageBytes.Inc(response.Content.Headers.ContentLength ?? 0);
            });

            // Uncomment this to test deliberately causing collections to fail. This should result in 503 responses.
            // With MetricPusherTester you might get a 1st push already before it fails but after that it should stop pushing.
            //Metrics.DefaultRegistry.AddBeforeCollectCallback(() => throw new ScrapeFailedException());

#if NETCOREAPP
            var diagnosticSourceRegistration = DiagnosticSourceAdapter.StartListening();
            var eventCounterRegistration     = EventCounterAdapter.StartListening();
#endif

#if NET6_0_OR_GREATER
            var meter        = new Meter("sample.dotnet.meter", "1.2.3");
            var meterCounter = meter.CreateCounter <double>("sample_counter");
            var meterGauge   = meter.CreateObservableGauge <byte>("sample_gauge", () => 92, "Buckets", "How much cheese is loaded");

            var meterRegistration = MeterAdapter.StartListening();
#endif

            var cts = new CancellationTokenSource();

            var random = new Random();

            // Update metrics on a regular interval until told to stop.
            var updateInterval = TimeSpan.FromSeconds(0.5);
            var updateTask     = Task.Factory.StartNew(async delegate
            {
                while (!cts.IsCancellationRequested)
                {
                    using (latestGauge.NewTimer())
                        using (timedHistogram.NewTimer())
                        {
                            var duration = Stopwatch.StartNew();


                            counter.Inc();
                            counter.Labels("GET", "/").Inc(2);
                            gauge.Set(random.NextDouble() + 2);
                            hist.Observe(random.NextDouble());
                            summary.Observe(random.NextDouble());

#if NET6_0_OR_GREATER
                            meterCounter.Add(1);
#endif
                            try
                            {
                                tester.OnTimeToObserveMetrics();
                            }
                            catch (Exception ex)
                            {
                                Console.Error.WriteLine(ex);
                            }

                            var sleepTime = updateInterval - duration.Elapsed;

                            if (sleepTime > TimeSpan.Zero)
                            {
                                await Task.Delay(sleepTime, cts.Token);
                            }
                        }
                }
            }).Result;

            Console.WriteLine("Press enter to stop metricServer");
            Console.ReadLine();

            cts.Cancel();
            try
            {
                updateTask.GetAwaiter().GetResult();
            }
            catch (OperationCanceledException)
            {
            }

            metricServer?.StopAsync().GetAwaiter().GetResult();

            tester.OnEnd();

            Console.WriteLine("Press enter to stop tester");
            Console.ReadLine();
        }
Example #24
0
        public void SdkSupportsMultipleReaders(AggregationTemporality aggregationTemporality, bool hasViews)
        {
            var exportedItems1 = new List <Metric>();

            using var deltaExporter1 = new InMemoryExporter <Metric>(exportedItems1);
            using var deltaReader1   = new BaseExportingMetricReader(deltaExporter1)
                  {
                      Temporality = AggregationTemporality.Delta,
                  };

            var exportedItems2 = new List <Metric>();

            using var deltaExporter2 = new InMemoryExporter <Metric>(exportedItems2);
            using var deltaReader2   = new BaseExportingMetricReader(deltaExporter2)
                  {
                      Temporality = aggregationTemporality,
                  };
            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());

            var meterProviderBuilder = Sdk.CreateMeterProviderBuilder()
                                       .AddMeter(meter.Name)
                                       .AddReader(deltaReader1)
                                       .AddReader(deltaReader2);

            if (hasViews)
            {
                meterProviderBuilder.AddView("counter", "renamedCounter");
            }

            using var meterProvider = meterProviderBuilder.Build();

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

            meterProvider.ForceFlush();

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

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

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

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

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

            meterProvider.ForceFlush();

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

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

            // Check value exported for Gauge
            this.AssertLongSumValueForMetric(exportedItems1[1], 300);
            this.AssertLongSumValueForMetric(exportedItems2[1], 400);
        }
Example #25
0
        internal static object Run(MetricsOptions options)
        {
            using var meter = new Meter("TestMeter");

            var providerBuilder = Sdk.CreateMeterProviderBuilder()
                                  .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("myservice"))
                                  .AddMeter(meter.Name); // All instruments from this meter are enabled.

            if (options.UseExporter.Equals("otlp", StringComparison.OrdinalIgnoreCase))
            {
                /*
                 * Prerequisite to run this example:
                 * Set up an OpenTelemetry Collector to run on local docker.
                 *
                 * Open a terminal window at the examples/Console/ directory and
                 * launch the OpenTelemetry Collector with an OTLP receiver, by running:
                 *
                 *  - On Unix based systems use:
                 *     docker run --rm -it -p 4317:4317 -v $(pwd):/cfg otel/opentelemetry-collector:0.33.0 --config=/cfg/otlp-collector-example/config.yaml
                 *
                 *  - On Windows use:
                 *     docker run --rm -it -p 4317:4317 -v "%cd%":/cfg otel/opentelemetry-collector:0.33.0 --config=/cfg/otlp-collector-example/config.yaml
                 *
                 * Open another terminal window at the examples/Console/ directory and
                 * launch the OTLP example by running:
                 *
                 *     dotnet run metrics --useExporter otlp
                 *
                 * The OpenTelemetry Collector will output all received metrics to the stdout of its terminal.
                 *
                 */

                // Adding the OtlpExporter creates a GrpcChannel.
                // This switch must be set before creating a GrpcChannel when calling an insecure gRPC service.
                // See: https://docs.microsoft.com/aspnet/core/grpc/troubleshoot#call-insecure-grpc-services-with-net-core-client
                AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

                providerBuilder
                .AddOtlpExporter((exporterOptions, metricReaderOptions) =>
                {
                    exporterOptions.Protocol = options.UseGrpc ? OtlpExportProtocol.Grpc : OtlpExportProtocol.HttpProtobuf;

                    metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = options.DefaultCollectionPeriodMilliseconds;
                    metricReaderOptions.TemporalityPreference = options.IsDelta ? MetricReaderTemporalityPreference.Delta : MetricReaderTemporalityPreference.Cumulative;
                });
            }
            else
            {
                providerBuilder
                .AddConsoleExporter((exporterOptions, metricReaderOptions) =>
                {
                    exporterOptions.Targets = ConsoleExporterOutputTargets.Console;

                    metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = options.DefaultCollectionPeriodMilliseconds;
                    metricReaderOptions.TemporalityPreference = options.IsDelta ? MetricReaderTemporalityPreference.Delta : MetricReaderTemporalityPreference.Cumulative;
                });
            }

            using var provider = providerBuilder.Build();

            Counter <int> counter = null;

            if (options.FlagCounter ?? true)
            {
                counter = meter.CreateCounter <int>("counter", "things", "A count of things");
            }

            Histogram <int> histogram = null;

            if (options.FlagHistogram ?? false)
            {
                histogram = meter.CreateHistogram <int>("histogram");
            }

            if (options.FlagGauge ?? false)
            {
                var observableCounter = meter.CreateObservableGauge("gauge", () =>
                {
                    return(new List <Measurement <int> >()
                    {
                        new Measurement <int>(
                            (int)Process.GetCurrentProcess().PrivateMemorySize64,
                            new KeyValuePair <string, object>("tag1", "value1")),
                    });
                });
            }

            System.Console.WriteLine("Press any key to exit.");
            while (!System.Console.KeyAvailable)
            {
                histogram?.Record(10);

                histogram?.Record(
                    100,
                    new KeyValuePair <string, object>("tag1", "value1"));

                histogram?.Record(
                    200,
                    new KeyValuePair <string, object>("tag1", "value2"),
                    new KeyValuePair <string, object>("tag2", "value2"));

                histogram?.Record(
                    100,
                    new KeyValuePair <string, object>("tag1", "value1"));

                histogram?.Record(
                    200,
                    new KeyValuePair <string, object>("tag2", "value2"),
                    new KeyValuePair <string, object>("tag1", "value2"));

                counter?.Add(10);

                counter?.Add(
                    100,
                    new KeyValuePair <string, object>("tag1", "value1"));

                counter?.Add(
                    200,
                    new KeyValuePair <string, object>("tag1", "value2"),
                    new KeyValuePair <string, object>("tag2", "value2"));

                counter?.Add(
                    100,
                    new KeyValuePair <string, object>("tag1", "value1"));

                counter?.Add(
                    200,
                    new KeyValuePair <string, object>("tag2", "value2"),
                    new KeyValuePair <string, object>("tag1", "value2"));

                Task.Delay(500).Wait();
            }

            return(null);
        }
Example #26
0
        internal static object Run(int port, int totalDurationInMins)
        {
            /*
             * Following is sample prometheus.yml config. Adjust port,interval as needed.
             *
             * scrape_configs:
             # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
             # - job_name: 'OpenTelemetryTest'
             #
             # metrics_path defaults to '/metrics'
             # scheme defaults to 'http'.
             #
             #  static_configs:
             #  - targets: ['localhost:9184']
             */
            using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                      .AddSource("TestMeter")
                                      .AddPrometheusExporter(opt => opt.Url = $"http://localhost:{port}/metrics/")
                                      .Build();

            ObservableGauge <long> gauge = MyMeter.CreateObservableGauge <long>(
                "Gauge",
                () =>
            {
                var tag1 = new KeyValuePair <string, object>("tag1", "value1");
                var tag2 = new KeyValuePair <string, object>("tag2", "value2");

                return(new List <Measurement <long> >()
                {
                    new Measurement <long>(RandomGenerator.Next(1, 1000), tag1, tag2),
                });
            });

            using var token = new CancellationTokenSource();
            Task writeMetricTask = new Task(() =>
            {
                while (!token.IsCancellationRequested)
                {
                    Counter.Add(
                        10,
                        new KeyValuePair <string, object>("tag1", "value1"),
                        new KeyValuePair <string, object>("tag2", "value2"));

                    Counter.Add(
                        100,
                        new KeyValuePair <string, object>("tag1", "anothervalue"),
                        new KeyValuePair <string, object>("tag2", "somethingelse"));

                    MyHistogram.Record(
                        RandomGenerator.Next(1, 1500),
                        new KeyValuePair <string, object>("tag1", "value1"),
                        new KeyValuePair <string, object>("tag2", "value2"));

                    Task.Delay(10).Wait();
                }
            });

            writeMetricTask.Start();

            token.CancelAfter(totalDurationInMins * 60 * 1000);

            System.Console.WriteLine($"OpenTelemetry Prometheus Exporter is making metrics available at http://localhost:{port}/metrics/");
            System.Console.WriteLine($"Press Enter key to exit now or will exit automatically after {totalDurationInMins} minutes.");
            System.Console.ReadLine();
            token.Cancel();
            System.Console.WriteLine("Exiting...");
            return(null);
        }
Example #27
0
        internal static object Run(MetricsOptions options)
        {
            using var meter = new Meter("TestMeter");

            var providerBuilder = Sdk.CreateMeterProviderBuilder()
                                  .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("myservice"))
                                  .AddMeter(meter.Name); // All instruments from this meter are enabled.

            if (options.UseExporter.ToLower() == "otlp")
            {
                /*
                 * Prerequisite to run this example:
                 * Set up an OpenTelemetry Collector to run on local docker.
                 *
                 * Open a terminal window at the examples/Console/ directory and
                 * launch the OpenTelemetry Collector with an OTLP receiver, by running:
                 *
                 *  - On Unix based systems use:
                 *     docker run --rm -it -p 4317:4317 -v $(pwd):/cfg otel/opentelemetry-collector:0.33.0 --config=/cfg/otlp-collector-example/config.yaml
                 *
                 *  - On Windows use:
                 *     docker run --rm -it -p 4317:4317 -v "%cd%":/cfg otel/opentelemetry-collector:0.33.0 --config=/cfg/otlp-collector-example/config.yaml
                 *
                 * Open another terminal window at the examples/Console/ directory and
                 * launch the OTLP example by running:
                 *
                 *     dotnet run metrics --useExporter otlp
                 *
                 * The OpenTelemetry Collector will output all received metrics to the stdout of its terminal.
                 *
                 */

                // Adding the OtlpExporter creates a GrpcChannel.
                // This switch must be set before creating a GrpcChannel/HttpClient when calling an insecure gRPC service.
                // See: https://docs.microsoft.com/aspnet/core/grpc/troubleshoot#call-insecure-grpc-services-with-net-core-client
                AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

                providerBuilder
                .AddOtlpExporter(o =>
                {
                    o.MetricExportIntervalMilliseconds = options.DefaultCollectionPeriodMilliseconds;
                    o.AggregationTemporality           = options.IsDelta ? AggregationTemporality.Delta : AggregationTemporality.Cumulative;
                });
            }
            else
            {
                providerBuilder
                .AddConsoleExporter(o =>
                {
                    o.MetricExportIntervalMilliseconds = options.DefaultCollectionPeriodMilliseconds;
                    o.AggregationTemporality           = options.IsDelta ? AggregationTemporality.Delta : AggregationTemporality.Cumulative;
                });
            }

            using var provider = providerBuilder.Build();

            Counter <int> counter = null;

            if (options.FlagCounter ?? true)
            {
                counter = meter.CreateCounter <int>("counter", "things", "A count of things");
            }

            Histogram <int> histogram = null;

            if (options.FlagHistogram ?? false)
            {
                histogram = meter.CreateHistogram <int>("histogram");
            }

            if (options.FlagGauge ?? false)
            {
                var observableCounter = meter.CreateObservableGauge("gauge", () =>
                {
                    return(new List <Measurement <int> >()
                    {
                        new Measurement <int>(
                            (int)Process.GetCurrentProcess().PrivateMemorySize64,
                            new KeyValuePair <string, object>("tag1", "value1")),
                    });
                });
            }

            var cts = new CancellationTokenSource();

            var tasks = new List <Task>();

            for (int i = 0; i < options.NumTasks; i++)
            {
                var taskno = i;

                tasks.Add(Task.Run(() =>
                {
                    System.Console.WriteLine($"Task started {taskno + 1}/{options.NumTasks}.");

                    var loops = 0;

                    while (!cts.IsCancellationRequested)
                    {
                        if (options.MaxLoops > 0 && loops >= options.MaxLoops)
                        {
                            break;
                        }

                        histogram?.Record(10);

                        histogram?.Record(
                            100,
                            new KeyValuePair <string, object>("tag1", "value1"));

                        histogram?.Record(
                            200,
                            new KeyValuePair <string, object>("tag1", "value2"),
                            new KeyValuePair <string, object>("tag2", "value2"));

                        histogram?.Record(
                            100,
                            new KeyValuePair <string, object>("tag1", "value1"));

                        histogram?.Record(
                            200,
                            new KeyValuePair <string, object>("tag2", "value2"),
                            new KeyValuePair <string, object>("tag1", "value2"));

                        counter?.Add(10);

                        counter?.Add(
                            100,
                            new KeyValuePair <string, object>("tag1", "value1"));

                        counter?.Add(
                            200,
                            new KeyValuePair <string, object>("tag1", "value2"),
                            new KeyValuePair <string, object>("tag2", "value2"));

                        counter?.Add(
                            100,
                            new KeyValuePair <string, object>("tag1", "value1"));

                        counter?.Add(
                            200,
                            new KeyValuePair <string, object>("tag2", "value2"),
                            new KeyValuePair <string, object>("tag1", "value2"));

                        loops++;
                    }
                }));
            }

            cts.CancelAfter(options.RunTime);
            System.Console.WriteLine($"Wait for {options.RunTime} milliseconds.");
            while (!cts.IsCancellationRequested)
            {
                Task.Delay(1000).Wait();
            }

            Task.WaitAll(tasks.ToArray());

            return(null);
        }
Example #28
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);
            }
        }