Пример #1
0
        public void MeterProvider_SetDefaultTwice_Throws()
        {
            var meterProvider = Sdk.CreateMeterProviderBuilder().Build();

            MeterProvider.SetDefault(meterProvider);
            Assert.Throws <InvalidOperationException>(() => MeterProvider.SetDefault(meterProvider));
        }
Пример #2
0
        public void GlobalSetup()
        {
            this.meter          = new Meter("TestMeter", "1.0.0");
            this.responseStream = new MemoryStream(1024 * 1024);

            this.meterProvider = Sdk.CreateMeterProviderBuilder()
                                 .AddMeter("TestMeter")
                                 .AddPrometheusExporter()
                                 .Build();

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

            counter.Add(18, new KeyValuePair <string, object>("label1", "value1"), new KeyValuePair <string, object>("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 KeyValuePair <string, object>("label1", "value1"), new KeyValuePair <string, object>("label2", "value2"));

            this.context = new DefaultHttpContext();
            this.context.Response.Body = this.responseStream;

            if (!this.meterProvider.TryFindExporter(out this.exporter))
            {
                throw new InvalidOperationException("PrometheusExporter could not be found on MeterProvider.");
            }

            this.exporter.Collect(Timeout.Infinite);
        }
Пример #3
0
        public MetricPointTests()
        {
            this.meter     = new Meter(Utils.GetCurrentMethodName());
            this.histogram = this.meter.CreateHistogram <long>("histogram");

            // Evenly distribute the bound values over the range [0, MaxValue)
            this.bounds = new double[10];
            for (int i = 0; i < this.bounds.Length; i++)
            {
                this.bounds[i] = i * 1000 / this.bounds.Length;
            }

            var exportedItems = new List <Metric>();

            this.provider = Sdk.CreateMeterProviderBuilder()
                            .AddMeter(this.meter.Name)
                            .AddInMemoryExporter(exportedItems)
                            .AddView(this.histogram.Name, new ExplicitBucketHistogramConfiguration()
            {
                Boundaries = this.bounds
            })
                            .Build();

            this.histogram.Record(500);

            this.provider.ForceFlush();

            this.metric = exportedItems[0];
            var metricPointsEnumerator = this.metric.GetMetricPoints().GetEnumerator();

            metricPointsEnumerator.MoveNext();
            this.metricPoint = metricPointsEnumerator.Current;
        }
        public void Setup()
        {
            this.meter   = new Meter(Utils.GetCurrentMethodName());
            this.counter = this.meter.CreateCounter <long>("counter");

            if (this.ViewConfig == ViewConfiguration.NoView)
            {
                this.provider = Sdk.CreateMeterProviderBuilder()
                                .AddMeter(this.meter.Name)
                                .Build();
            }
            else if (this.ViewConfig == ViewConfiguration.ViewNoInstrSelect)
            {
                this.provider = Sdk.CreateMeterProviderBuilder()
                                .AddMeter(this.meter.Name)
                                .AddView("nomatch", new MetricStreamConfiguration()
                {
                    TagKeys = new string[] { "DimName1", "DimName2", "DimName3" }
                })
                                .Build();
            }
            else if (this.ViewConfig == ViewConfiguration.ViewSelectsInstr)
            {
                this.provider = Sdk.CreateMeterProviderBuilder()
                                .AddMeter(this.meter.Name)
                                .AddView(this.counter.Name, new MetricStreamConfiguration()
                {
                    TagKeys = new string[] { "DimName1", "DimName2", "DimName3" }
                })
                                .Build();
            }
        }
Пример #5
0
 public void ServerEndpointSanityCheckPositiveTest(params string[] uris)
 {
     using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
                                         .AddPrometheusExporter(opt =>
     {
         opt.HttpListenerPrefixes = uris;
     })
                                         .Build();
 }
        public async Task RequestMetricIsCaptured()
        {
            var metricItems    = new List <MetricItem>();
            var metricExporter = new TestExporter <MetricItem>(ProcessExport);

            void ProcessExport(Batch <MetricItem> batch)
            {
                foreach (var metricItem in batch)
                {
                    metricItems.Add(metricItem);
                }
            }

            var processor = new PullMetricProcessor(metricExporter, true);

            this.meterProvider = Sdk.CreateMeterProviderBuilder()
                                 .AddAspNetCoreInstrumentation()
                                 .AddMetricProcessor(processor)
                                 .Build();

            using (var client = this.factory.CreateClient())
            {
                var response = await client.GetAsync("/api/values");

                response.EnsureSuccessStatusCode();
            }

            // We need to let End callback execute as it is executed AFTER response was returned.
            // In unit tests environment there may be a lot of parallel unit tests executed, so
            // giving some breezing room for the End callback to complete
            await Task.Delay(TimeSpan.FromSeconds(1));

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

            this.meterProvider.Dispose();

            var requestMetrics = metricItems
                                 .SelectMany(item => item.Metrics.Where(metric => metric.Name == "http.server.duration"))
                                 .ToArray();

            Assert.True(requestMetrics.Length == 1);

            var metric = requestMetrics[0] as IHistogramMetric;

            Assert.NotNull(metric);
            Assert.Equal(1L, metric.PopulationCount);
            Assert.True(metric.PopulationSum > 0);

            var bucket = metric.Buckets
                         .Where(b =>
                                metric.PopulationSum > b.LowBoundary &&
                                metric.PopulationSum <= b.HighBoundary)
                         .FirstOrDefault();

            Assert.NotEqual(default, bucket);
        public void Setup()
        {
            var metricExporter = new TestExporter <Metric>(ProcessExport);

            void ProcessExport(Batch <Metric> batch)
            {
                double sum = 0;

                foreach (var metric in batch)
                {
                    if (this.UseWithRef)
                    {
                        // The performant way of iterating.
                        foreach (ref var metricPoint in metric.GetMetricPoints())
                        {
                            sum += metricPoint.GetCounterSumDouble();
                        }
                    }
                    else
                    {
                        // The non-performant way of iterating.
                        // This is still "correct", but less performant.
                        foreach (var metricPoint in metric.GetMetricPoints())
                        {
                            sum += metricPoint.GetCounterSumDouble();
                        }
                    }
                }
            }

            this.reader = new BaseExportingMetricReader(metricExporter)
            {
                Temporality = AggregationTemporality.Cumulative,
            };

            this.meter = new Meter(Utils.GetCurrentMethodName());

            this.provider = Sdk.CreateMeterProviderBuilder()
                            .AddMeter(this.meter.Name)
                            .AddReader(this.reader)
                            .Build();

            this.counter         = this.meter.CreateCounter <double>("counter");
            this.token           = new CancellationTokenSource();
            this.writeMetricTask = new Task(() =>
            {
                while (!this.token.IsCancellationRequested)
                {
                    var tag1 = new KeyValuePair <string, object>("DimName1", this.dimensionValues[this.random.Next(0, 10)]);
                    var tag2 = new KeyValuePair <string, object>("DimName2", this.dimensionValues[this.random.Next(0, 10)]);
                    var tag3 = new KeyValuePair <string, object>("DimName3", this.dimensionValues[this.random.Next(0, 10)]);
                    this.counter.Add(100.00, tag1, tag2, tag3);
                }
            });
            this.writeMetricTask.Start();
        }
        /// <summary>add MagicOnion Telemetry.</summary>
        public static IMagicOnionServerBuilder AddOpenTelemetry(this IMagicOnionServerBuilder builder,
                                                                MagicOnionOpenTelemetryOptions options,
                                                                Action <MagicOnionOpenTelemetryOptions, MagicOnionOpenTelemetryMeterFactoryOption> configureMeterProvider,
                                                                Action <MagicOnionOpenTelemetryOptions, IServiceProvider, TracerProviderBuilder> configureTracerProvider)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            builder.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());

                builder.Services.AddSingleton(meterFactoryOption.MetricExporter);
                if (meterFactoryOption.MeterLogger != null)
                {
                    builder.Services.AddSingleton <IMagicOnionLogger>(meterFactoryOption.MeterLogger.Invoke(MeterProvider.Default));
                }
            }

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

                builder.Services.AddOpenTelemetryTracing((provider, builder) =>
                {
                    // ActivitySourceName must match to TracerName.
                    builder.AddSource(options.MagicOnionActivityName);
                    configureTracerProvider?.Invoke(options, provider, builder);
                });

                // Avoid directly register ActivitySource to Singleton for easier identification.
                var activitySource            = new ActivitySource(options.MagicOnionActivityName);
                var magicOnionActivitySources = new MagicOnionActivitySources(activitySource);
                builder.Services.AddSingleton(magicOnionActivitySources);
            }

            return(builder);
        }
Пример #9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PrometheusExporterMiddleware"/> class.
        /// </summary>
        /// <param name="meterProvider"><see cref="MeterProvider"/>.</param>
        /// <param name="next"><see cref="RequestDelegate"/>.</param>
        public PrometheusExporterMiddleware(MeterProvider meterProvider, RequestDelegate next)
        {
            Guard.ThrowIfNull(meterProvider, nameof(meterProvider));

            if (!meterProvider.TryFindExporter(out PrometheusExporter exporter))
            {
                throw new ArgumentException("A PrometheusExporter could not be found configured on the provided MeterProvider.");
            }

            this.exporter = exporter;
        }
        public void Setup()
        {
            if (this.WithSDK)
            {
                this.provider = Sdk.CreateMeterProviderBuilder()
                                .AddSource("TestMeter") // All instruments from this meter are enabled.
                                .Build();
            }

            this.meter   = new Meter("TestMeter");
            this.counter = this.meter.CreateCounter <long>("counter");
        }
        public OpenTelemetryCollectorLogger(MeterProvider meterProvider, string metricsPrefix = "magiconion", string version = null, IEnumerable <KeyValuePair <string, string> > defaultLabels = null)
        {
            if (meterProvider == null)
            {
                throw new ArgumentNullException(nameof(meterProvider));
            }

            // configure defaultTags included as default tag
            this.defaultLabels = defaultLabels ?? Array.Empty <KeyValuePair <string, string> >();

            // todo: how to description?
            var meter = meterProvider.GetMeter("MagicOnion", version);

            // Service build time. ms
            buildServiceDefinitionMeasure = meter.CreateDoubleMeasure($"{metricsPrefix}_buildservicedefinition_duration_milliseconds"); // sum

            // Unary request count. num
            unaryRequestCounter = meter.CreateInt64Counter($"{metricsPrefix}_unary_requests_count");        // sum
            // Unary API request size. bytes
            unaryRequestSizeMeasure = meter.CreateInt64Measure($"{metricsPrefix}_unary_request_size");      // sum
            // Unary API response size. bytes
            unaryResponseSizeMeasure = meter.CreateInt64Measure($"{metricsPrefix}_unary_response_size");    // sum
            // Unary API error Count. num
            unaryErrorCounter = meter.CreateInt64Counter($"{metricsPrefix}_unary_error_count");             // sum
            // Unary API elapsed time. ms
            unaryElapsedMeasure = meter.CreateDoubleMeasure($"{metricsPrefix}_unary_elapsed_milliseconds"); // sum

            // StreamingHub error Count. num
            streamingHubErrorCounter = meter.CreateInt64Counter($"{metricsPrefix}_streaminghub_error_count");             // sum
            // StreamingHub elapsed time. ms
            streamingHubElapsedMeasure = meter.CreateDoubleMeasure($"{metricsPrefix}_streaminghub_elapsed_milliseconds"); // sum
            // StreamingHub request count. num
            streamingHubRequestCounter = meter.CreateInt64Counter($"{metricsPrefix}_streaminghub_requests_count");        // sum
            // StreamingHub request size. bytes
            streamingHubRequestSizeMeasure = meter.CreateInt64Measure($"{metricsPrefix}_streaminghub_request_size");      // sum
            // StreamingHub response size. bytes
            streamingHubResponseSizeMeasure = meter.CreateInt64Measure($"{metricsPrefix}_streaminghub_response_size");    // sum
            // ConnectCount - DisconnectCount = current connect count. (successfully disconnected)
            // StreamingHub connect count. num
            streamingHubConnectCounter = meter.CreateInt64Counter($"{metricsPrefix}_streaminghub_connect_count");       // sum
            // StreamingHub disconnect count. num
            streamingHubDisconnectCounter = meter.CreateInt64Counter($"{metricsPrefix}_streaminghub_disconnect_count"); // sum

            // HubBroadcast request count. num
            broadcastRequestCounter = meter.CreateInt64Counter($"{metricsPrefix}_broadcast_requests_count");   // sum
            // HubBroadcast request size. num
            broadcastRequestSizeMeasure = meter.CreateInt64Measure($"{metricsPrefix}_broadcast_request_size"); // sum
            // HubBroadcast group count. num
            broadcastGroupCounter = meter.CreateInt64Counter($"{metricsPrefix}_broadcast_group_count");        // sum
        }
Пример #12
0
        public void Setup()
        {
            this.meter = new Meter(Utils.GetCurrentMethodName());

            var exportedItems = new List <Metric>();
            var reader        = new PeriodicExportingMetricReader(new InMemoryExporter <Metric>(exportedItems), 1000);

            reader.PreferredAggregationTemporality = 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");
        }
Пример #13
0
        /// <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);
        }
Пример #14
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);
        }
Пример #15
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 MeterProvider_UpdateDefault_CachedTracer()
        {
            var defaultMeter = MeterProvider.Default.GetMeter(string.Empty);
            var noOpCounter  = defaultMeter.CreateDoubleCounter("ctr");

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

            MeterProvider.SetDefault(Sdk.CreateMeterProvider(b => { }));
            var counter = defaultMeter.CreateDoubleCounter("ctr");

            Assert.IsType <DoubleCounterMetricSdk>(counter);

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

            Assert.NotSame(defaultMeter, newdefaultMeter);
            Assert.IsType <MeterSdk>(newdefaultMeter);
        }
        /// <summary>
        /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an
        /// <see cref="IApplicationBuilder"/> instance.
        /// </summary>
        /// <remarks>Note: A branched pipeline is created based on the <paramref
        /// name="predicate"/> or <paramref name="path"/>. If neither <paramref
        /// name="predicate"/> nor <paramref name="path"/> are provided then
        /// <see cref="PrometheusExporterOptions.ScrapeEndpointPath"/> is
        /// used.</remarks>
        /// <param name="app">The <see cref="IApplicationBuilder"/> to add
        /// middleware to.</param>
        /// <param name="meterProvider">Optional <see cref="MeterProvider"/>
        /// containing a <see cref="PrometheusExporter"/> otherwise the primary
        /// SDK provider will be resolved using application services.</param>
        /// <param name="predicate">Optional predicate for deciding if a given
        /// <see cref="HttpContext"/> should be branched. If supplied <paramref
        /// name="path"/> is ignored.</param>
        /// <param name="path">Optional path to use for the branched pipeline.
        /// Ignored if <paramref name="predicate"/> is supplied.</param>
        /// <param name="configureBranchedPipeline">Optional callback to
        /// configure the branched pipeline. Called before registration of the
        /// Prometheus middleware.</param>
        /// <returns>A reference to the original <see
        /// cref="IApplicationBuilder"/> for chaining calls.</returns>
        public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(
            this IApplicationBuilder app,
            MeterProvider meterProvider,
            Func <HttpContext, bool> predicate,
            string path,
            Action <IApplicationBuilder> configureBranchedPipeline)
        {
            // Note: Order is important here. MeterProvider is accessed before
            // GetOptions<PrometheusExporterOptions> so that any changes made to
            // PrometheusExporterOptions in deferred AddPrometheusExporter
            // configure actions are reflected.
            meterProvider ??= app.ApplicationServices.GetRequiredService <MeterProvider>();

            if (predicate == null)
            {
                if (path == null)
                {
                    var options = app.ApplicationServices.GetOptions <PrometheusExporterOptions>();

                    path = options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath;
                }

                if (!path.StartsWith("/"))
                {
                    path = $"/{path}";
                }

                return(app.Map(
                           new PathString(path),
                           builder =>
                {
                    configureBranchedPipeline?.Invoke(builder);
                    builder.UseMiddleware <PrometheusExporterMiddleware>(meterProvider);
                }));
            }

            return(app.MapWhen(
                       context => predicate(context),
                       builder =>
            {
                configureBranchedPipeline?.Invoke(builder);
                builder.UseMiddleware <PrometheusExporterMiddleware>(meterProvider);
            }));
        }
        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();
        }
Пример #19
0
        public void ServerEndpointSanityCheckNegativeTest(params string[] uris)
        {
            try
            {
                using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder()
                                                    .AddPrometheusExporter(opt =>
                {
                    opt.HttpListenerPrefixes = uris;
                })
                                                    .Build();
            }
            catch (Exception ex)
            {
                if (ex is not ArgumentNullException)
                {
                    Assert.Equal("System.ArgumentException", ex.GetType().ToString());
#if NETFRAMEWORK
                    Assert.Equal("Prometheus server path should be a valid URI with http/https scheme.\r\nParameter name: httpListenerPrefixes", ex.Message);
#else
                    Assert.Equal("Prometheus server path should be a valid URI with http/https scheme. (Parameter 'httpListenerPrefixes')", ex.Message);
#endif
                }
            }
        }
Пример #20
0
 public MeterProviderTests()
 {
     MeterProvider.Reset();
 }
Пример #21
0
        async void CreateConfigFile(string setting, string dragoConnexCode)
        {
            var dialog = new CommonOpenFileDialog();

            dialog.IsFolderPicker = true;
            CommonFileDialogResult result = dialog.ShowDialog();

            if (result == CommonFileDialogResult.Ok)
            {
                var configFolder = $"{dialog.FileName} \\Config {dragoConnexCode}\\";
                Directory.CreateDirectory(configFolder);

                Dictionary <string, string> dict = JsonConvert.DeserializeObject <Dictionary <string, string> >(setting);
                string toWrite = "";
                foreach (var item in dict.Reverse().Skip(2).Reverse())
                {
                    if (string.IsNullOrEmpty(item.Value))
                    {
                        toWrite += "\"" + Environment.NewLine;
                    }
                    else
                    {
                        if (!item.Key.Equals("AlarmSetting") || !item.Key.Equals("AMRSetting"))
                        {
                            toWrite += item.Value + Environment.NewLine;
                        }
                    }
                }

                toWrite  = toWrite.Remove(toWrite.Length - 1);
                toWrite += Environment.NewLine;
                File.WriteAllText(configFolder + "NETWORK.csv", toWrite);
                MeterProvider MeterProvider = new MeterProvider();
                toWrite = "";
                var meters = await MeterProvider.GetMetersAsync("http://dragoservices.azurewebsites.net/api/DragoAdmin/Meters/DragoConnex/" + dragoConnexCode);

                if (meters != null)
                {
                    foreach (var meter in meters)
                    {
                        Dictionary <string, string> dictMeter = JsonConvert.DeserializeObject <Dictionary <string, string> >(meter.MeterSetting);
                        foreach (var item in dictMeter)
                        {
                            toWrite += item.Value + ",";
                        }

                        toWrite  = toWrite.Remove(toWrite.Length - 1);
                        toWrite += Environment.NewLine;
                    }

                    File.WriteAllText(configFolder + "METER.csv", toWrite);
                }
                var dictAlarmSetting = JsonConvert.DeserializeObject <Dictionary <string, string> >(dict["AlarmSetting"]);
                toWrite = "";
                foreach (var item in dictAlarmSetting)
                {
                    if (String.IsNullOrEmpty(item.Value))
                    {
                        toWrite += "0" + ",";
                    }
                    else
                    {
                        toWrite += item.Value + ",";
                    }
                }
                toWrite  = toWrite.Remove(toWrite.Length - 1);
                toWrite += Environment.NewLine;

                File.WriteAllText(configFolder + "ALARM.csv", toWrite);

                var dictAMRSetting = JsonConvert.DeserializeObject <Dictionary <string, string> >(dict["AMRSetting"]);
                toWrite = "";
                foreach (var item in dictAMRSetting)
                {
                    if (String.IsNullOrEmpty(item.Value))
                    {
                        toWrite += "0" + Environment.NewLine;
                    }
                    else
                    {
                        toWrite += item.Value + Environment.NewLine;
                    }
                }
                File.WriteAllText(configFolder + "AMR.csv", toWrite);
            }
        }
Пример #22
0
        static async Task Main(string[] args)
        {
            var config                  = new ConfigurationBuilder().AddEnvironmentVariables().Build();
            var exporterEndpoint        = config.GetValue <string>("MeterExporterEndpoint", "http://localhost:9184/metrics/");
            var exporterHostingEndpoint = config.GetValue <string>("MeterExporterHostingEndpoint", "http://localhost:9184/metrics/");
            var tracerEndpoint          = config.GetValue <string>("TracerExporterEndpoint", "http://localhost:9411/api/v2/spans");

            // MetricsServer for Prometheus pull model
            var exporter = new PrometheusExporter(new PrometheusExporterOptions()
            {
                Url = exporterEndpoint
            });
            var metricsServer = new PrometheusExporterMetricsHttpServerCustom(exporter, exporterHostingEndpoint);

            metricsServer.Start();
            Console.WriteLine($"Started Metrics Server on {exporterEndpoint}");

            /*
             * 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']
             */

            // Metrics (factory is cacheable)
            var processor   = new UngroupedBatcher();
            var spanContext = default(SpanContext);

            MeterProvider.SetDefault(Sdk.CreateMeterProviderBuilder()
                                     .SetProcessor(processor)
                                     .SetExporter(exporter)
                                     .SetPushInterval(TimeSpan.FromSeconds(10))
                                     .Build());
            var meterProvider = MeterProvider.Default;
            var meter         = meterProvider.GetMeter("Sample");
            var counter       = meter.CreateInt64Counter("sample/measure/initialize");

            var labels1 = new List <KeyValuePair <string, string> >();

            labels1.Add(new KeyValuePair <string, string>("dim1", "value1"));

            var labels2 = new List <KeyValuePair <string, string> >();

            labels2.Add(new KeyValuePair <string, string>("dim2", "value2"));

            // TracerServer for Zipkin push model (in case you won't run on docker)
            // $ docker run --rm -p 9411:9411 openzipkin/zipkin
            // Tracer (factory is cacheable)
            using var tracerFactory = Sdk.CreateTracerProviderBuilder()
                                      .AddSource("Samples.SampleClient", "Samples.SampleServer")
                                      .AddZipkinExporter(o =>
            {
                o.ServiceName = "front-zipkin";
                o.Endpoint    = new Uri(tracerEndpoint);
            })
                                      .Build();
            using var backEndTracerFactory = Sdk.CreateTracerProviderBuilder()
                                             .AddSource("Samples.SampleServer.Redis", "Samples.SampleServer.Db")
                                             .AddZipkinExporter(o =>
            {
                o.ServiceName = "backend-zipkin";
                o.Endpoint    = new Uri(tracerEndpoint);
            })
                                             .Build();
            Console.WriteLine($"Started Tracer Server on {tracerEndpoint}");

            // Execute http://0.0.0.0:19999
            using var sample = new InstrumentationWithActivitySource();
            sample.Start();

            var sw = Stopwatch.StartNew();

            while (sw.Elapsed.TotalMinutes < 10)
            {
                // metrics
                counter.Add(spanContext, 100, meter.GetLabelSet(labels1));

                await Task.Delay(1000);

                var remaining = (10 * 60) - sw.Elapsed.TotalSeconds;
                Console.WriteLine("Running and emitting metrics. Remaining time:" + (int)remaining + " seconds");
            }

            metricsServer.Stop();
        }
Пример #23
0
 public void Dispose()
 {
     MeterProvider.Reset();
 }
        public async Task RequestMetricIsCaptured()
        {
            var metricItems = new List <Metric>();

            this.meterProvider = Sdk.CreateMeterProviderBuilder()
                                 .AddAspNetCoreInstrumentation()
                                 .AddInMemoryExporter(metricItems)
                                 .Build();

            using (var client = this.factory.CreateClient())
            {
                var response = await client.GetAsync("/api/values");

                response.EnsureSuccessStatusCode();
            }

            // We need to let End callback execute as it is executed AFTER response was returned.
            // In unit tests environment there may be a lot of parallel unit tests executed, so
            // giving some breezing room for the End callback to complete
            await Task.Delay(TimeSpan.FromSeconds(1));

            this.meterProvider.Dispose();

            var requestMetrics = metricItems
                                 .Where(item => item.Name == "http.server.duration")
                                 .ToArray();

            Assert.True(requestMetrics.Length == 1);

            var metric = requestMetrics[0];

            Assert.NotNull(metric);
            Assert.True(metric.MetricType == MetricType.Histogram);
            var metricPoints = new List <MetricPoint>();

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

            Assert.Single(metricPoints);

            var metricPoint = metricPoints[0];

            var count = metricPoint.GetHistogramCount();
            var sum   = metricPoint.GetHistogramSum();

            Assert.Equal(1L, count);
            Assert.True(sum > 0);

            /*
             * var bucket = metric.Buckets
             *  .Where(b =>
             *      metric.PopulationSum > b.LowBoundary &&
             *      metric.PopulationSum <= b.HighBoundary)
             *  .FirstOrDefault();
             * Assert.NotEqual(default, bucket);
             * Assert.Equal(1, bucket.Count);
             */

            var attributes = new KeyValuePair <string, object> [metricPoint.Tags.Count];
            int i          = 0;

            foreach (var tag in metricPoint.Tags)
            {
                attributes[i++] = tag;
            }

            var method     = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpMethod, "GET");
            var scheme     = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpScheme, "http");
            var statusCode = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpStatusCode, "200");
            var flavor     = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpFlavor, "HTTP/1.1");
            var host       = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpHost, "localhost");
            var target     = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpTarget, "api/Values");

            Assert.Contains(method, attributes);
            Assert.Contains(scheme, attributes);
            Assert.Contains(statusCode, attributes);
            Assert.Contains(flavor, attributes);
            Assert.Contains(host, attributes);
            Assert.Contains(target, attributes);
            Assert.Equal(6, attributes.Length);
        }
Пример #25
0
 public void MeterProvider_SetDefaultNull()
 {
     Assert.Throws <ArgumentNullException>(() => MeterProvider.SetDefault(null));
 }
 public void MeterProvider_SetDefaultTwice_Throws()
 {
     MeterProvider.SetDefault(Sdk.CreateMeterProvider(b => { }));
     Assert.Throws <InvalidOperationException>(() => MeterProvider.SetDefault(Sdk.CreateMeterProvider(b => { })));
 }
Пример #27
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo {
                    Title = "My API", Version = "v1"
                });

                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                if (File.Exists(xmlPath))
                {
                    c.IncludeXmlComments(xmlPath);
                }
            });

            // Switch between Zipkin/Jaeger by setting UseExporter in appsettings.json.
            var exporter = this.Configuration.GetValue <string>("UseExporter").ToLowerInvariant();

            switch (exporter)
            {
            case "jaeger":
                services.AddOpenTelemetryTracing((builder) => builder
                                                 .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(this.Configuration.GetValue <string>("Jaeger:ServiceName")))
                                                 .AddAspNetCoreInstrumentation()
                                                 .AddHttpClientInstrumentation()
                                                 .AddJaegerExporter());

                services.Configure <JaegerExporterOptions>(this.Configuration.GetSection("Jaeger"));
                break;

            case "zipkin":
                services.AddOpenTelemetryTracing((builder) => builder
                                                 .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(this.Configuration.GetValue <string>("Zipkin:ServiceName")))
                                                 .AddAspNetCoreInstrumentation()
                                                 .AddHttpClientInstrumentation()
                                                 .AddZipkinExporter());

                services.Configure <ZipkinExporterOptions>(this.Configuration.GetSection("Zipkin"));
                break;

            case "otlp":
                // 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);

                services.AddOpenTelemetryTracing((builder) => builder
                                                 .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(this.Configuration.GetValue <string>("Otlp:ServiceName")))
                                                 .AddAspNetCoreInstrumentation()
                                                 .AddHttpClientInstrumentation()
                                                 .AddOtlpExporter(otlpOptions =>
                {
                    otlpOptions.Endpoint = new Uri(this.Configuration.GetValue <string>("Otlp:Endpoint"));
                }));
                break;

            default:
                services.AddOpenTelemetryTracing((builder) => builder
                                                 .AddAspNetCoreInstrumentation()
                                                 .AddHttpClientInstrumentation()
                                                 .AddConsoleExporter());

                // For options which can be bound from IConfiguration.
                services.Configure <AspNetCoreInstrumentationOptions>(this.Configuration.GetSection("AspNetCoreInstrumentation"));

                // For options which can be configured from code only.
                services.Configure <AspNetCoreInstrumentationOptions>(options =>
                {
                    options.Filter = (req) =>
                    {
                        return(req.Request.Host != null);
                    };
                });

                break;
            }

            // TODO: Add IServiceCollection.AddOpenTelemetryMetrics extension method
            var providerBuilder = Sdk.CreateMeterProviderBuilder()
                                  .AddAspNetCoreInstrumentation();

            // TODO: Add configuration switch for Prometheus and OTLP export
            providerBuilder
            .AddConsoleExporter();

            this.meterProvider = providerBuilder.Build();
        }
Пример #28
0
        internal static async Task <object> RunAsync(int port, int pushIntervalInSecs, int totalDurationInMins)
        {
            System.Console.WriteLine($"OpenTelemetry Prometheus Exporter is making metrics available at http://localhost:{port}/metrics/");

            /*
             * 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']
             */

            // Create and Setup Prometheus Exporter
            var promOptions = new PrometheusExporterOptions()
            {
                Url = $"http://localhost:{port}/metrics/"
            };
            var promExporter      = new PrometheusExporter(promOptions);
            var metricsHttpServer = new PrometheusExporterMetricsHttpServer(promExporter);

            metricsHttpServer.Start();

            // Create Processor (called Batcher in Metric spec, this is still not decided)
            var processor = new UngroupedBatcher();

            // Application which decides to enable OpenTelemetry metrics
            // would setup a MeterProvider and make it default.
            // All meters from this factory will be configured with the common processing pipeline.
            MeterProvider.SetDefault(Sdk.CreateMeterProviderBuilder()
                                     .SetProcessor(processor)
                                     .SetExporter(promExporter)
                                     .SetPushInterval(TimeSpan.FromSeconds(pushIntervalInSecs))
                                     .Build());

            // The following shows how libraries would obtain a MeterProvider.
            // MeterProvider is the entry point, which provides Meter.
            // If user did not set the Default MeterProvider (shown in earlier lines),
            // all metric operations become no-ops.
            var meterProvider = MeterProvider.Default;
            var meter         = meterProvider.GetMeter("MyMeter");

            // the rest is purely from Metrics API.
            var testCounter  = meter.CreateInt64Counter("MyCounter");
            var testMeasure  = meter.CreateInt64Measure("MyMeasure");
            var testObserver = meter.CreateInt64Observer("MyObservation", CallBackForMyObservation);
            var labels1      = new List <KeyValuePair <string, string> >();

            labels1.Add(new KeyValuePair <string, string>("dim1", "value1"));

            var labels2 = new List <KeyValuePair <string, string> >();

            labels2.Add(new KeyValuePair <string, string>("dim1", "value2"));
            var defaultContext = default(SpanContext);

            Stopwatch sw = Stopwatch.StartNew();

            while (sw.Elapsed.TotalMinutes < totalDurationInMins)
            {
                testCounter.Add(defaultContext, 100, meter.GetLabelSet(labels1));

                testMeasure.Record(defaultContext, 100, meter.GetLabelSet(labels1));
                testMeasure.Record(defaultContext, 500, meter.GetLabelSet(labels1));
                testMeasure.Record(defaultContext, 5, meter.GetLabelSet(labels1));
                testMeasure.Record(defaultContext, 750, meter.GetLabelSet(labels1));

                // Obviously there is no testObserver.Oberve() here, as Observer instruments
                // have callbacks that are called by the Meter automatically at each collection interval.

                await Task.Delay(1000);

                var remaining = (totalDurationInMins * 60) - sw.Elapsed.TotalSeconds;
                System.Console.WriteLine("Running and emitting metrics. Remaining time:" + (int)remaining + " seconds");
            }

            // Stopping
            metricsHttpServer.Stop();
            System.Console.WriteLine("Metrics server shutdown.");
            System.Console.WriteLine("Press Enter key to exit.");
            return(null);
        }
Пример #29
0
        public async Task RequestMetricIsCaptured()
        {
            var metricItems    = new List <Metric>();
            var metricExporter = new TestExporter <Metric>(ProcessExport);

            void ProcessExport(Batch <Metric> batch)
            {
                foreach (var metricItem in batch)
                {
                    metricItems.Add(metricItem);
                }
            }

            var metricReader = new BaseExportingMetricReader(metricExporter)
            {
                PreferredAggregationTemporality = AggregationTemporality.Cumulative,
            };

            this.meterProvider = Sdk.CreateMeterProviderBuilder()
                                 .AddAspNetCoreInstrumentation()
                                 .AddReader(metricReader)
                                 .Build();

            using (var client = this.factory.CreateClient())
            {
                var response = await client.GetAsync("/api/values");

                response.EnsureSuccessStatusCode();
            }

            // We need to let End callback execute as it is executed AFTER response was returned.
            // In unit tests environment there may be a lot of parallel unit tests executed, so
            // giving some breezing room for the End callback to complete
            await Task.Delay(TimeSpan.FromSeconds(1));

            this.meterProvider.Dispose();

            var requestMetrics = metricItems
                                 .Where(item => item.Name == "http.server.duration")
                                 .ToArray();

            Assert.True(requestMetrics.Length == 1);

            var metric = requestMetrics[0];

            Assert.NotNull(metric);
            Assert.True(metric.MetricType == MetricType.Histogram);
            var metricPoints = new List <MetricPoint>();

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

            Assert.Single(metricPoints);

            var metricPoint = metricPoints[0];

            Assert.Equal(1L, metricPoint.LongValue);
            Assert.True(metricPoint.DoubleValue > 0);

            /*
             * var bucket = metric.Buckets
             *  .Where(b =>
             *      metric.PopulationSum > b.LowBoundary &&
             *      metric.PopulationSum <= b.HighBoundary)
             *  .FirstOrDefault();
             * Assert.NotEqual(default, bucket);
             * Assert.Equal(1, bucket.Count);
             */

            var attributes = new KeyValuePair <string, object> [metricPoint.Keys.Length];

            for (int i = 0; i < attributes.Length; i++)
            {
                attributes[i] = new KeyValuePair <string, object>(metricPoint.Keys[i], metricPoint.Values[i]);
            }

            var method     = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpMethod, "GET");
            var scheme     = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpScheme, "http");
            var statusCode = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpStatusCode, 200);
            var flavor     = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpFlavor, "HTTP/1.1");

            Assert.Contains(method, attributes);
            Assert.Contains(scheme, attributes);
            Assert.Contains(statusCode, attributes);
            Assert.Contains(flavor, attributes);
            Assert.Equal(4, attributes.Length);
        }
        /// <summary>
        /// Adds OpenTelemetry Prometheus scraping endpoint middleware to an
        /// <see cref="IApplicationBuilder"/> instance.
        /// </summary>
        /// <param name="app">The <see cref="IApplicationBuilder"/> to add
        /// middleware to.</param>
        /// <param name="meterProvider">Optional <see cref="MeterProvider"/>
        /// containing a <see cref="PrometheusExporter"/> otherwise the primary
        /// SDK provider will be resolved using application services.</param>
        /// <returns>A reference to the <see cref="IApplicationBuilder"/> instance after the operation has completed.</returns>
        public static IApplicationBuilder UseOpenTelemetryPrometheusScrapingEndpoint(this IApplicationBuilder app, MeterProvider meterProvider = null)
        {
            var options = app.ApplicationServices.GetOptions <PrometheusExporterOptions>();

            string path = options.ScrapeEndpointPath ?? PrometheusExporterOptions.DefaultScrapeEndpointPath;

            if (!path.StartsWith("/"))
            {
                path = $"/{path}";
            }

            return(app.Map(
                       new PathString(path),
                       builder => builder.UseMiddleware <PrometheusExporterMiddleware>(meterProvider ?? app.ApplicationServices.GetRequiredService <MeterProvider>())));
        }