public void TestAddOtlpExporter_SetsCorrectMetricReaderDefaults()
        {
            if (Environment.Version.Major == 3)
            {
                // Adding the OtlpExporter creates a GrpcChannel.
                // This switch must be set before creating a GrpcChannel when calling an insecure HTTP/2 endpoint.
                // 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);
            }

            var meterProvider = Sdk.CreateMeterProviderBuilder()
                                .AddOtlpExporter()
                                .Build();

            CheckMetricReaderDefaults();

            meterProvider.Dispose();

            meterProvider = Sdk.CreateMeterProviderBuilder()
                            .AddOtlpExporter((exporterOptions, metricReaderOptions) =>
            {
                metricReaderOptions.PeriodicExportingMetricReaderOptions = null;
            })
                            .Build();

            CheckMetricReaderDefaults();

            meterProvider.Dispose();

            void CheckMetricReaderDefaults()
            {
                var bindingFlags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;

                var metricReader = typeof(MetricReader)
                                   .Assembly
                                   .GetType("OpenTelemetry.Metrics.MeterProviderSdk")
                                   .GetField("reader", bindingFlags)
                                   .GetValue(meterProvider) as PeriodicExportingMetricReader;

                Assert.NotNull(metricReader);

                var exportIntervalMilliseconds = (int)typeof(PeriodicExportingMetricReader)
                                                 .GetField("ExportIntervalMilliseconds", bindingFlags)
                                                 .GetValue(metricReader);

                Assert.Equal(60000, exportIntervalMilliseconds);
            }
        }
        /// <summary>add MagicOnion Telemetry.</summary>
        public static IServiceCollection AddMagicOnionOpenTelemetry(this IServiceCollection services,
                                                                    MagicOnionOpenTelemetryOptions options,
                                                                    Action <MagicOnionOpenTelemetryOptions, MagicOnionOpenTelemetryMeterFactoryOption> configureMeterProvider,
                                                                    Action <MagicOnionOpenTelemetryOptions, IServiceProvider, TracerProviderBuilder> configureTracerProvider)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            services.AddSingleton(options);

            // configure MeterFactory
            if (configureMeterProvider != null)
            {
                var meterFactoryOption = new MagicOnionOpenTelemetryMeterFactoryOption();
                configureMeterProvider(options, meterFactoryOption);

                MeterProvider.SetDefault(Sdk.CreateMeterProviderBuilder()
                                         .SetProcessor(meterFactoryOption.MetricProcessor)
                                         .SetExporter(meterFactoryOption.MetricExporter)
                                         .SetPushInterval(meterFactoryOption.MetricPushInterval)
                                         .Build());

                services.AddSingleton(meterFactoryOption.MetricExporter);
                services.AddSingleton(MeterProvider.Default);
            }

            // configure TracerFactory
            if (configureTracerProvider != null)
            {
                if (string.IsNullOrEmpty(options.ActivitySourceName))
                {
                    throw new NullReferenceException(nameof(options.ActivitySourceName));
                }

                var tracerFactory = services.AddOpenTelemetryTracerProvider((provider, builder) =>
                {
                    // ActivitySourceName must match to TracerName.
                    builder.AddSource(options.ActivitySourceName);
                    configureTracerProvider(options, provider, builder);
                });
                services.AddSingleton(tracerFactory);
                services.AddSingleton(new ActivitySource(options.ActivitySourceName));
            }

            return(services);
        }
예제 #3
0
        public async Task PrometheusExporterMiddlewareIntegration_MeterProvider()
        {
            using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
                                                .AddMeter(MeterName)
                                                .AddPrometheusExporter()
                                                .Build();

            await RunPrometheusExporterMiddlewareIntegrationTest(
                "/metrics",
                app => app.UseOpenTelemetryPrometheusScrapingEndpoint(
                    meterProvider: meterProvider,
                    predicate: null,
                    path: null,
                    configureBranchedPipeline: null),
                registerMeterProvider : false).ConfigureAwait(false);
        }
예제 #4
0
    internal static object Run(int port)
    {
        /* prometheus.yml
         *
         * global:
         * scrape_interval: 1s
         * evaluation_interval: 1s
         *
         * scrape_configs:
         * - job_name: "opentelemetry"
         *  static_configs:
         *    - targets: ["localhost:9184"]
         */

        using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                  .AddMeter(MyMeter.Name)
                                  .AddPrometheusExporter(opt =>
        {
            opt.StartHttpListener    = true;
            opt.HttpListenerPrefixes = new string[] { $"http://localhost:{port}/" };
        })
                                  .Build();

        var process = Process.GetCurrentProcess();

        MyMeter.CreateObservableCounter("thread.cpu_time", () => GetThreadCpuTime(process), "ms");

        using var token = new CancellationTokenSource();

        Task.Run(() =>
        {
            while (!token.IsCancellationRequested)
            {
                Counter.Add(9.9, new("name", "apple"), new("color", "red"));
                Counter.Add(99.9, new("name", "lemon"), new("color", "yellow"));
                MyHistogram.Record(ThreadLocalRandom.Value.Next(1, 1500), new("tag1", "value1"), new("tag2", "value2"));
                Task.Delay(10).Wait();
            }
        });

        System.Console.WriteLine($"PrometheusExporter is listening on http://localhost:{port}/metrics/");
        System.Console.WriteLine($"Press any key to exit...");
        System.Console.ReadKey();
        token.Cancel();

        return(null);
    }
예제 #5
0
        public void MeterProvider_SetDefault()
        {
            var meterProvider = Sdk.CreateMeterProviderBuilder().Build();

            MeterProvider.SetDefault(meterProvider);

            var defaultMeter = MeterProvider.Default.GetMeter(string.Empty);

            Assert.NotNull(defaultMeter);
            Assert.IsType <MeterSdk>(defaultMeter);

            Assert.NotSame(defaultMeter, MeterProvider.Default.GetMeter("named meter"));

            var counter = defaultMeter.CreateDoubleCounter("ctr");

            Assert.IsType <DoubleCounterMetricSdk>(counter);
        }
        public void Setup()
        {
            this.meter = new Meter(Utils.GetCurrentMethodName());

            var exportedItems = new List <Metric>();
            var reader        = new PeriodicExportingMetricReader(new InMemoryExporter <Metric>(exportedItems), 1000)
            {
                Temporality = this.AggregationTemporality,
            };

            this.provider = Sdk.CreateMeterProviderBuilder()
                            .AddMeter(this.meter.Name) // All instruments from this meter are enabled.
                            .AddReader(reader)
                            .Build();

            this.counter = this.meter.CreateCounter <long>("counter");
        }
예제 #7
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")),
            });
예제 #8
0
        public void SetupSdkProviderWithNoReader(bool hasViews)
        {
            // This test ensures that MeterProviderSdk can be set up without any reader
            using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{hasViews}");
            var meterProviderBuilder = Sdk.CreateMeterProviderBuilder()
                                       .AddMeter(meter.Name);

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

            using var meterProvider = meterProviderBuilder.Build();

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

            counter.Add(10, new KeyValuePair <string, object>("key", "value"));
        }
        public void ObserverCallbackExceptionTest()
        {
            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);
            meter.CreateObservableGauge <long>("myBadGauge", observeValues: () => throw new Exception("gauge read error"));

            meterProvider.ForceFlush(MaxTimeToAllowForFlush);
            Assert.Equal(2, exportedItems.Count);
            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);

            metric = exportedItems[1];
            Assert.Equal("myBadGauge", metric.Name);
            metricPoints.Clear();
            foreach (ref var mp in metric.GetMetricPoints())
            {
                metricPoints.Add(mp);
            }

            Assert.Empty(metricPoints);
        }
예제 #10
0
        public void DuplicateInstrumentNamesFromDifferentMetersAreAllowed(AggregationTemporality temporality, bool hasView)
        {
            var metricItems    = new List <Metric>();
            var metricExporter = new InMemoryExporter <Metric>(metricItems);

            var metricReader = new BaseExportingMetricReader(metricExporter)
            {
                PreferredAggregationTemporality = temporality,
            };

            using var meter1 = new Meter($"{Utils.GetCurrentMethodName()}.1.{temporality}");
            using var meter2 = new Meter($"{Utils.GetCurrentMethodName()}.2.{temporality}");
            var meterProviderBuilder = Sdk.CreateMeterProviderBuilder()
                                       .AddMeter(meter1.Name)
                                       .AddMeter(meter2.Name)
                                       .AddReader(metricReader);

            if (hasView)
            {
                meterProviderBuilder.AddView("name1", new MetricStreamConfiguration()
                {
                    Description = "description"
                });
            }

            using var meterProvider = meterProviderBuilder.Build();

            // Expecting one metric stream.
            var counterLong = meter1.CreateCounter <long>("name1");

            counterLong.Add(10);
            metricReader.Collect();
            Assert.Single(metricItems);

            // The following will not be ignored
            // as it is the same metric name but different meter.
            var anotherCounterSameNameDiffMeter = meter2.CreateCounter <long>("name1");

            anotherCounterSameNameDiffMeter.Add(10);
            counterLong.Add(10);
            metricItems.Clear();
            metricReader.Collect();
            Assert.Equal(2, metricItems.Count);
        }
예제 #11
0
        public void ViewToRenameMetricConditionally()
        {
            using var meter1 = new Meter($"{Utils.GetCurrentMethodName()}.1");
            using var meter2 = new Meter($"{Utils.GetCurrentMethodName()}.2");

            var exportedItems = new List <Metric>();

            using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                      .AddMeter(meter1.Name)
                                      .AddMeter(meter2.Name)
                                      .AddView((instrument) =>
            {
                if (instrument.Meter.Name.Equals(meter2.Name, StringComparison.OrdinalIgnoreCase) &&
                    instrument.Name.Equals("name1", StringComparison.OrdinalIgnoreCase))
                {
                    return(new MetricStreamConfiguration()
                    {
                        Name = "name1_Renamed", Description = "new description"
                    });
                }
                else
                {
                    return(null);
                }
            })
                                      .AddInMemoryExporter(exportedItems)
                                      .Build();

            // Without views only 1 stream would be
            // exported (the 2nd one gets dropped due to
            // name conflict). Due to renaming with Views,
            // we expect 2 metric streams here.
            var counter1 = meter1.CreateCounter <long>("name1", "unit", "original_description");
            var counter2 = meter2.CreateCounter <long>("name1", "unit", "original_description");

            counter1.Add(10);
            counter2.Add(10);
            meterProvider.ForceFlush(MaxTimeToAllowForFlush);
            Assert.Equal(2, exportedItems.Count);
            Assert.Equal("name1", exportedItems[0].Name);
            Assert.Equal("name1_Renamed", exportedItems[1].Name);
            Assert.Equal("original_description", exportedItems[0].Description);
            Assert.Equal("new description", exportedItems[1].Description);
        }
        public void FlushMetricExporterTest(ExportModes mode)
        {
            BaseExporter <Metric> exporter = null;

            switch (mode)
            {
            case ExportModes.Push:
                exporter = new PushOnlyMetricExporter();
                break;

            case ExportModes.Pull:
                exporter = new PullOnlyMetricExporter();
                break;

            case ExportModes.Pull | ExportModes.Push:
                exporter = new PushPullMetricExporter();
                break;
            }

            var reader = new BaseExportingMetricReader(exporter);

            using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                      .AddReader(reader)
                                      .Build();

            switch (mode)
            {
            case ExportModes.Push:
                Assert.True(reader.Collect());
                Assert.True(meterProvider.ForceFlush());
                break;

            case ExportModes.Pull:
                Assert.False(reader.Collect());
                Assert.False(meterProvider.ForceFlush());
                Assert.True((exporter as IPullMetricExporter).Collect(-1));
                break;

            case ExportModes.Pull | ExportModes.Push:
                Assert.True(reader.Collect());
                Assert.True(meterProvider.ForceFlush());
                break;
            }
        }
예제 #13
0
        public void DuplicateInstrumentNamesFromSameMeterAreNotAllowed(AggregationTemporality temporality, bool hasView)
        {
            var metricItems    = new List <Metric>();
            var metricExporter = new InMemoryExporter <Metric>(metricItems);

            var metricReader = new BaseExportingMetricReader(metricExporter)
            {
                PreferredAggregationTemporality = temporality,
            };

            using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{temporality}");
            var meterProviderBuilder = Sdk.CreateMeterProviderBuilder()
                                       .AddMeter(meter.Name)
                                       .AddReader(metricReader);

            if (hasView)
            {
                meterProviderBuilder.AddView("name1", new MetricStreamConfiguration()
                {
                    Description = "description"
                });
            }

            using var meterProvider = meterProviderBuilder.Build();

            // Expecting one metric stream.
            var counterLong = meter.CreateCounter <long>("name1");

            counterLong.Add(10);
            metricReader.Collect();
            Assert.Single(metricItems);

            // The following will be ignored as
            // metric of same name exists.
            // Metric stream will remain one.
            var anotherCounterSameName = meter.CreateCounter <long>("name1");

            anotherCounterSameName.Add(10);
            counterLong.Add(10);
            metricItems.Clear();
            metricReader.Collect();
            Assert.Single(metricItems);
        }
예제 #14
0
        public void MeterProvider_UpdateDefault_CachedTracer()
        {
            var defaultMeter = MeterProvider.Default.GetMeter(string.Empty);
            var noOpCounter  = defaultMeter.CreateDoubleCounter("ctr");

            Assert.IsType <NoopCounterMetric <double> >(noOpCounter);

            var meterProvider = Sdk.CreateMeterProviderBuilder().Build();

            MeterProvider.SetDefault(meterProvider);
            var counter = defaultMeter.CreateDoubleCounter("ctr");

            Assert.IsType <DoubleCounterMetricSdk>(counter);

            var newdefaultMeter = MeterProvider.Default.GetMeter(string.Empty);

            Assert.NotSame(defaultMeter, newdefaultMeter);
            Assert.IsType <MeterSdk>(newdefaultMeter);
        }
예제 #15
0
    public static void Main(string[] args)
    {
        using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                  .AddMeter("MyCompany.MyProduct.MyLibrary")
                                  .AddPrometheusExporter(options => { options.StartHttpListener = true; })
                                  .Build();

        Console.WriteLine("Press any key to exit");
        while (!Console.KeyAvailable)
        {
            Thread.Sleep(1000);
            MyFruitCounter.Add(1, new("name", "apple"), new("color", "red"));
            MyFruitCounter.Add(2, new("name", "lemon"), new("color", "yellow"));
            MyFruitCounter.Add(1, new("name", "lemon"), new("color", "yellow"));
            MyFruitCounter.Add(2, new("name", "apple"), new("color", "green"));
            MyFruitCounter.Add(5, new("name", "apple"), new("color", "red"));
            MyFruitCounter.Add(4, new("name", "lemon"), new("color", "yellow"));
        }
    }
        public void UserHttpFactoryCalled()
        {
            OtlpExporterOptions options = new OtlpExporterOptions();

            var defaultFactory = options.HttpClientFactory;

            int invocations = 0;

            options.Protocol          = OtlpExportProtocol.HttpProtobuf;
            options.HttpClientFactory = () =>
            {
                invocations++;
                return(defaultFactory());
            };

            using (var exporter = new OtlpMetricExporter(options))
            {
                Assert.Equal(1, invocations);
            }

            using (var provider = Sdk.CreateMeterProviderBuilder()
                                  .AddOtlpExporter(o =>
            {
                o.Protocol = OtlpExportProtocol.HttpProtobuf;
                o.HttpClientFactory = options.HttpClientFactory;
            })
                                  .Build())
            {
                Assert.Equal(2, invocations);
            }

            options.HttpClientFactory = null;
            Assert.Throws <InvalidOperationException>(() =>
            {
                using var exporter = new OtlpMetricExporter(options);
            });

            options.HttpClientFactory = () => null;
            Assert.Throws <InvalidOperationException>(() =>
            {
                using var exporter = new OtlpMetricExporter(options);
            });
        }
예제 #17
0
    public static void Main()
    {
        for (int i = 0; i < ArraySize; i++)
        {
            DimensionValues[i] = $"DimValue{i}";
        }

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

        Stress(prometheusPort: 9184);
    }
예제 #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);
        }
예제 #19
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);
            }
        }
        public void GlobalSetup()
        {
            this.meter         = new Meter(Utils.GetCurrentMethodName());
            this.meterProvider = Sdk.CreateMeterProviderBuilder()
                                 .AddMeter(this.meter.Name)
                                 .AddInMemoryExporter(this.metrics)
                                 .Build();

            var counter = this.meter.CreateCounter <long>("counter_name_1", "long", "counter_name_1_description");

            counter.Add(18, new("label1", "value1"), new("label2", "value2"));

            var gauge = this.meter.CreateObservableGauge("gauge_name_1", () => 18.0D, "long", "gauge_name_1_description");

            var histogram = this.meter.CreateHistogram <long>("histogram_name_1", "long", "histogram_name_1_description");

            histogram.Record(100, new("label1", "value1"), new("label2", "value2"));

            this.meterProvider.ForceFlush();
        }
예제 #21
0
        public void InstrumentWithInvalidNameIsIgnoredTest(string instrumentName)
        {
            var exportedItems = new List <Metric>();

            using var meter = new Meter("InstrumentWithInvalidNameIsIgnoredTest");

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

            var counterLong = meter.CreateCounter <long>(instrumentName);

            counterLong.Add(10);
            meterProvider.ForceFlush(MaxTimeToAllowForFlush);

            // instrument should have been ignored
            // as its name does not comply with the specification
            Assert.Empty(exportedItems);
        }
예제 #22
0
        public void ViewConflict_TwoInstruments_ConflictAvoidedBecauseSecondInstrumentIsDropped()
        {
            var exportedItems = new List <Metric>();

            using var meter = new Meter($"{Utils.GetCurrentMethodName()}");
            var meterProviderBuilder = Sdk.CreateMeterProviderBuilder()
                                       .AddMeter(meter.Name)
                                       .AddView((instrument) =>
            {
                if (instrument.Name == "name")
                {
                    return(new MetricStreamConfiguration {
                        Name = "othername"
                    });
                }
                else
                {
                    return(MetricStreamConfiguration.Drop);
                }
            })
                                       .AddInMemoryExporter(exportedItems);

            using var meterProvider = meterProviderBuilder.Build();

            var instrument1 = meter.CreateCounter <long>("name");
            var instrument2 = meter.CreateCounter <long>("othername");

            instrument1.Add(10);
            instrument2.Add(20);

            meterProvider.ForceFlush(MaxTimeToAllowForFlush);

            Assert.Single(exportedItems);
            var metric1 = new List <Metric>()
            {
                exportedItems[0]
            };

            Assert.Equal("othername", exportedItems[0].Name);
            Assert.Equal(10, GetLongSum(metric1));
        }
예제 #23
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);
        }
예제 #24
0
        public void ViewToProduceMultipleStreamsFromInstrument()
        {
            using var meter = new Meter(Utils.GetCurrentMethodName());
            var exportedItems = new List <Metric>();

            using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                      .AddMeter(meter.Name)
                                      .AddView("name1", "renamedStream1")
                                      .AddView("name1", "renamedStream2")
                                      .AddInMemoryExporter(exportedItems)
                                      .Build();

            // Expecting two metric stream.
            var counterLong = meter.CreateCounter <long>("name1");

            counterLong.Add(10);
            meterProvider.ForceFlush(MaxTimeToAllowForFlush);
            Assert.Equal(2, exportedItems.Count);
            Assert.Equal("renamedStream1", exportedItems[0].Name);
            Assert.Equal("renamedStream2", exportedItems[1].Name);
        }
예제 #25
0
        public void ViewToRenameMetric()
        {
            using var meter = new Meter(Utils.GetCurrentMethodName());
            var exportedItems = new List <Metric>();

            using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                      .AddMeter(meter.Name)
                                      .AddView("name1", "renamed")
                                      .AddInMemoryExporter(exportedItems)
                                      .Build();

            // Expecting one metric stream.
            var counterLong = meter.CreateCounter <long>("name1");

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

            Assert.Equal("renamed", metric.Name);
        }
        public void ProcessMetricsAreCaptured()
        {
            var exportedItems = new List <Metric>();

            using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                      .AddRuntimeMetrics(options =>
            {
                options.ProcessEnabled = true;
            })
                                      .AddInMemoryExporter(exportedItems)
                                      .Build();

            // simple CPU spinning
            var spinDuration = DateTime.UtcNow.AddMilliseconds(10);

            while (DateTime.UtcNow < spinDuration)
            {
            }

            meterProvider.ForceFlush(MaxTimeToAllowForFlush);

            Assert.Equal(4, exportedItems.Count);

            var cpuTimeMetric = exportedItems.First(i => i.Name == "process.cpu.time");
            var sumReceived   = GetDoubleSum(cpuTimeMetric);

            Assert.True(sumReceived > 0);

            var cpuCountMetric = exportedItems.First(i => i.Name == "process.cpu.count");

            Assert.Equal(Environment.ProcessorCount, (int)GetLongSum(cpuCountMetric));

            var memoryMetric = exportedItems.First(i => i.Name == "process.memory.usage");

            Assert.True(GetLongSum(memoryMetric) > 0);

            var virtualMemoryMetric = exportedItems.First(i => i.Name == "process.memory.virtual");

            Assert.True(GetLongSum(virtualMemoryMetric) > 0);
        }
예제 #27
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);
    }
예제 #28
0
        public void ViewWithNullCustomNameTakesInstrumentName()
        {
            var exportedItems = new List <Metric>();

            using var meter = new Meter("ViewToRenameMetricConditionallyTest");

            using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                      .AddMeter(meter.Name)
                                      .AddView((instrument) =>
            {
                if (instrument.Name.Equals("name1", StringComparison.OrdinalIgnoreCase))
                {
                    // null View name
                    return(new MetricStreamConfiguration()
                    {
                    });
                }
                else
                {
                    return(null);
                }
            })
                                      .AddInMemoryExporter(exportedItems)
                                      .Build();

            // Expecting one metric stream.
            // Since the View name was null, the instrument name was used instead
            var counter1 = meter.CreateCounter <long>("name1", "unit", "original_description");

            counter1.Add(10);

            meterProvider.ForceFlush(MaxTimeToAllowForFlush);

            // Expecting one metric stream.
            Assert.Single(exportedItems);
            var metric = exportedItems[0];

            Assert.Equal(counter1.Name, metric.Name);
        }
예제 #29
0
        public void ViewWithValidNameConditionally(string viewNewName)
        {
            using var meter1 = new Meter("ViewToRenameMetricConditionallyTest");
            var exportedItems = new List <Metric>();

            using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                      .AddMeter(meter1.Name)
                                      .AddView((instrument) =>
            {
                if (instrument.Meter.Name.Equals(meter1.Name, StringComparison.OrdinalIgnoreCase) &&
                    instrument.Name.Equals("name1", StringComparison.OrdinalIgnoreCase))
                {
                    // invalid instrument name as per the spec
                    return(new MetricStreamConfiguration()
                    {
                        Name = viewNewName, Description = "new description"
                    });
                }
                else
                {
                    return(null);
                }
            })
                                      .AddInMemoryExporter(exportedItems)
                                      .Build();

            // Expecting one metric stream.
            var counter1 = meter1.CreateCounter <long>("name1", "unit", "original_description");

            counter1.Add(10);

            meterProvider.ForceFlush(MaxTimeToAllowForFlush);

            // Expecting one metric stream.
            Assert.Single(exportedItems);
            var metric = exportedItems[0];

            Assert.Equal(viewNewName, metric.Name);
        }
예제 #30
0
        public void ViewWithInvalidNameIgnoredConditionally(string viewNewName)
        {
            using var meter1 = new Meter("ViewToRenameMetricConditionallyTest");
            var exportedItems = new List <Metric>();

            using var meterProvider = Sdk.CreateMeterProviderBuilder()
                                      .AddMeter(meter1.Name)

                                      // since here it's a func, we can't validate the name right away
                                      // so the view is allowed to be added, but upon instrument creation it's going to be ignored.
                                      .AddView((instrument) =>
            {
                if (instrument.Meter.Name.Equals(meter1.Name, StringComparison.OrdinalIgnoreCase) &&
                    instrument.Name.Equals("name1", StringComparison.OrdinalIgnoreCase))
                {
                    // invalid instrument name as per the spec
                    return(new MetricStreamConfiguration()
                    {
                        Name = viewNewName, Description = "new description"
                    });
                }
                else
                {
                    return(null);
                }
            })
                                      .AddInMemoryExporter(exportedItems)
                                      .Build();

            // Because the MetricStreamName passed is invalid, the view is ignored,
            // and default aggregation is used.
            var counter1 = meter1.CreateCounter <long>("name1", "unit", "original_description");

            counter1.Add(10);

            meterProvider.ForceFlush(MaxTimeToAllowForFlush);

            Assert.Single(exportedItems);
        }