public async Task E2ETestMiddleware() { var promOptions = new PrometheusExporterOptions() { Url = "/metrics" }; var promExporter = new PrometheusExporter(promOptions); var simpleProcessor = new UngroupedBatcher(); var builder = new WebHostBuilder() .Configure(app => { app.UsePrometheus(); }) .ConfigureServices(services => { services.AddSingleton(promOptions); services.AddSingleton(promExporter); //Temporary till we figure out metrics configuration }); var server = new TestServer(builder); var client = server.CreateClient(); try { CollectMetrics(simpleProcessor, promExporter); } finally { var response = await client.GetAsync("/foo"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); await Task.Delay(waitDuration); response = await client.GetAsync("/metrics"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); var responseText = response.Content.ReadAsStringAsync().Result; this.output.WriteLine($"Respone from metrics API is \n {responseText}"); ValidateResponse(responseText); } }
public static MeterProviderBuilder AddPrometheusExporter(this MeterProviderBuilder builder, Action <PrometheusExporterOptions> configure = null) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } var options = new PrometheusExporterOptions(); configure?.Invoke(options); var exporter = new PrometheusExporter(options); var pullMetricProcessor = new PullMetricProcessor(exporter, false); exporter.MakePullRequest = pullMetricProcessor.PullRequest; var metricsHttpServer = new PrometheusExporterMetricsHttpServer(exporter); metricsHttpServer.Start(); return(builder.AddMetricProcessor(pullMetricProcessor)); }
public async Task E2ETestMiddleware() { var promOptions = new PrometheusExporterOptions() { Url = "/metrics" }; var promExporter = new PrometheusExporter(promOptions); var simpleProcessor = new UngroupedBatcher(promExporter, new System.TimeSpan(100)); var builder = new WebHostBuilder() .Configure(app => { app.UsePrometheus(); }) .ConfigureServices(services => { services.AddSingleton(promOptions); services.AddSingleton(promExporter); //Temporary till we figure out metrics configuration }); var server = new TestServer(builder); var client = server.CreateClient(); try { CollectMetrics(simpleProcessor); } finally { var response = await client.GetAsync("/foo"); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); Task.Delay(200).Wait(); response = await client.GetAsync("/metrics"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Contains("testCounter{dim1=\"value1\"}", response.Content.ReadAsStringAsync().Result); Assert.Contains("testCounter{dim1=\"value2\"}", response.Content.ReadAsStringAsync().Result); } }
public void PrometheusExporterTest1() { var promOptions = new PrometheusExporterOptions() { Url = "http://localhost:9184/metrics/" }; Metric <long> metric = new Metric <long>("sample"); var promExporter = new PrometheusExporter <long>(promOptions, metric); try { promExporter.Start(); List <KeyValuePair <string, string> > label1 = new List <KeyValuePair <string, string> >(); label1.Add(new KeyValuePair <string, string>("dim1", "value1")); var labelSet1 = new LabelSet(label1); metric.GetOrCreateMetricTimeSeries(labelSet1).Add(100); metric.GetOrCreateMetricTimeSeries(labelSet1).Add(200); } finally { Task.Delay(10000).Wait(); promExporter.Stop(); } }
public void E2ETestMetricsHttpServer() { var promOptions = new PrometheusExporterOptions() { Url = "http://localhost:9184/metrics/" }; var promExporter = new PrometheusExporter(promOptions); var simpleProcessor = new UngroupedBatcher(promExporter); var metricsHttpServer = new PrometheusExporterMetricsHttpServer(promExporter); try { metricsHttpServer.Start(); CollectMetrics(simpleProcessor); } finally { // Change delay to higher value to manually check Promtheus. // These tests are just to temporarily validate export to prometheus. Task.Delay(100).Wait(); metricsHttpServer.Stop(); } }
static IServiceCollection AddSampleOpenTelemetry(this IServiceCollection services, SampleAppOptions sampleAppOptions, IConfiguration configuration, Action <TracerBuilder> traceBuilder = null) { var openTelemetryConfigSection = configuration.GetSection("OpenTelemetry"); var jaegerConfigSection = openTelemetryConfigSection.GetSection("Jaeger"); services.Configure <JaegerExporterOptions>(jaegerConfigSection); var zipkinConfigSection = openTelemetryConfigSection.GetSection("Zipkin"); services.Configure <ZipkinTraceExporterOptions>(zipkinConfigSection); // setup open telemetry services.AddOpenTelemetry((sp, builder) => { var serviceName = OpenTelemetryExtensions.TracerServiceName; var exporterCount = 0; if (zipkinConfigSection.Exists()) { var zipkinOptions = sp.GetService <IOptions <ZipkinTraceExporterOptions> >(); if (zipkinOptions.Value != null && zipkinOptions.Value.Endpoint != null) { // To start zipkin: // docker run -d -p 9411:9411 openzipkin/zipkin exporterCount++; builder.UseZipkin(o => { o.Endpoint = zipkinOptions.Value.Endpoint; o.ServiceName = serviceName; }); Console.WriteLine("Using OpenTelemetry Zipkin exporter"); } } if (!string.IsNullOrWhiteSpace(sampleAppOptions.ApplicationInsightsForOpenTelemetryInstrumentationKey)) { exporterCount++; builder.UseApplicationInsights(o => { o.InstrumentationKey = sampleAppOptions.ApplicationInsightsForOpenTelemetryInstrumentationKey; o.TelemetryInitializers.Add(new CloudRoleTelemetryInitializer()); }); Console.WriteLine("Using OpenTelemetry ApplicationInsights exporter"); } if (jaegerConfigSection.Exists()) { // Running jaeger with docker // docker run -d --name jaeger \ // -e COLLECTOR_ZIPKIN_HTTP_PORT=19411 \ // -p 5775:5775/udp \ // -p 6831:6831/udp \ // -p 6832:6832/udp \ // -p 5778:5778 \ // -p 16686:16686 \ // -p 14268:14268 \ // -p 19411:19411 \ // jaegertracing/all-in-one var jaegerOptions = sp.GetService <IOptions <JaegerExporterOptions> >(); if (jaegerOptions.Value != null && !string.IsNullOrWhiteSpace(jaegerOptions.Value.AgentHost)) { exporterCount++; builder.UseJaeger(o => { o.ServiceName = serviceName; o.AgentHost = jaegerOptions.Value.AgentHost; o.AgentPort = jaegerOptions.Value.AgentPort; o.MaxPacketSize = jaegerOptions.Value.MaxPacketSize; o.ProcessTags = jaegerOptions.Value.ProcessTags; }); Console.WriteLine("Using OpenTelemetry Jaeger exporter"); } } if (exporterCount == 0) { throw new Exception("No sink for open telemetry was configured"); } builder .SetSampler(new AlwaysSampleSampler()) .AddDependencyCollector(config => { config.SetHttpFlavor = true; }) .AddRequestCollector() .SetResource(new Resource(new Dictionary <string, object> { { "service.name", serviceName } })); traceBuilder?.Invoke(builder); }); var prometheusConfigSection = openTelemetryConfigSection.GetSection("Prometheus"); if (prometheusConfigSection.Exists()) { var prometheusExporterOptions = new PrometheusExporterOptions(); prometheusConfigSection.Bind(prometheusExporterOptions); if (!string.IsNullOrWhiteSpace(prometheusExporterOptions.Url)) { var prometheusExporter = new PrometheusExporter(prometheusExporterOptions); services.AddSingleton(prometheusExporter); // Add start/stop lifetime support services.AddHostedService <PromotheusExporterHostedService>(); Console.WriteLine($"Using OpenTelemetry Prometheus exporter in '{prometheusExporterOptions.Url}'"); } } return(services); }
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); }
/// <summary> /// Initializes a new instance of the <see cref="PrometheusExporterMetricsHttpServer"/> class. /// </summary> /// <param name="exporter">The <see cref="PrometheusExporter"/> instance.</param> public PrometheusExporterMetricsHttpServerCustom(PrometheusExporter exporter, string listenerUrl) { this.exporter = exporter ?? throw new ArgumentNullException(nameof(exporter)); this.httpListener.Prefixes.Add(listenerUrl); }
/// <summary> /// Initializes a new instance of the <see cref="PrometheusExporterMetricsHttpServer"/> class. /// </summary> /// <param name="exporter">The <see cref="PrometheusExporter"/> instance.</param> /// <param name="listenerUrl">listener endpoint</param> public PrometheusExporterMetricsHttpServerCustom(PrometheusExporter exporter, string listenerUrl) { this.exporter = exporter; this.httpListener.Prefixes.Add(listenerUrl); }
public PrometheusScraperEndpoint(IPrometheusEndpointOptions options, PrometheusExporter exporter) : base(options) { _exporter = exporter ?? throw new ArgumentNullException(nameof(exporter)); }
static IServiceCollection AddSampleOpenTelemetry(this IServiceCollection services, IConfiguration configuration, Action <TracerBuilder> traceBuilder = null) { // setup open telemetry services.AddOpenTelemetry(builder => { var serviceName = OpenTelemetryExtensions.TracerServiceName; var exporterCount = 0; // To start zipkin: // docker run -d -p 9411:9411 openzipkin/zipkin var zipkinUrl = configuration.GetZipkinUrl(); if (!string.IsNullOrWhiteSpace(zipkinUrl)) { exporterCount++; builder.UseZipkin(o => { o.Endpoint = new Uri(zipkinUrl); o.ServiceName = serviceName; }); } var appInsightsKey = configuration.GetApplicationInsightsInstrumentationKeyForOpenTelemetry(); if (!string.IsNullOrWhiteSpace(appInsightsKey)) { exporterCount++; builder.UseApplicationInsights(o => { o.InstrumentationKey = appInsightsKey; o.TelemetryInitializers.Add(new CloudRoleTelemetryInitializer()); }); } // Running jaeger with docker // docker run -d--name jaeger \ // -e COLLECTOR_ZIPKIN_HTTP_PORT = 19411 \ // -p 5775:5775 / udp \ // -p 6831:6831 / udp \ // -p 6832:6832 / udp \ // -p 5778:5778 \ // -p 16686:16686 \ // -p 14268:14268 \ // -p 19411:19411 \ // jaegertracing/all -in-one:1.15 var jaegerHost = configuration.GetJaegerHost(); if (!string.IsNullOrWhiteSpace(jaegerHost)) { exporterCount++; builder.UseJaeger(o => { o.ServiceName = serviceName; o.AgentHost = jaegerHost; o.AgentPort = 6831; // o.AgentPort = 14268; o.MaxPacketSize = 1000; }); } if (exporterCount == 0) { throw new Exception("No sink for open telemetry was configured"); } builder.SetSampler(new AlwaysSampleSampler()); builder.AddDependencyCollector(config => { config.SetHttpFlavor = true; }); builder.AddRequestCollector(o => { }); builder.SetResource(new Resource(new Dictionary <string, object> { { "service.name", serviceName } })); traceBuilder?.Invoke(builder); }); if (!string.IsNullOrWhiteSpace(configuration.GetPrometheusExportURL())) { var prometheusExporterOptions = new PrometheusExporterOptions() { Url = configuration.GetPrometheusExportURL(), }; var prometheusExporter = new PrometheusExporter(prometheusExporterOptions); services.AddSingleton(prometheusExporter); // Add start/stop lifetime support services.AddHostedService <PromotheusExporterHostedService>(); } return(services); }
public PromotheusExporterHostedService(PrometheusExporter exporter, IEnumerable <IAppMetrics> initializers) { this.exporter = exporter ?? throw new System.ArgumentNullException(nameof(exporter)); this.initializers = initializers; }
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(); }