Improve Prometheus example (#2601)

This commit is contained in:
Reiley Yang 2021-11-12 11:29:26 -08:00 committed by GitHub
parent df756ee50d
commit 3fbf1d98df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 65 deletions

View File

@ -30,7 +30,7 @@ public class Program
{ {
var process = Process.GetCurrentProcess(); var process = Process.GetCurrentProcess();
MyMeter.CreateObservableCounter("Thread.CpuTime", () => GetThreadCpuTime(process), "seconds"); MyMeter.CreateObservableCounter("Thread.CpuTime", () => GetThreadCpuTime(process), "ms");
MyMeter.CreateObservableGauge("Thread.State", () => GetThreadState(process)); MyMeter.CreateObservableGauge("Thread.State", () => GetThreadState(process));
} }

View File

@ -47,7 +47,7 @@ namespace Examples.Console
.MapResult( .MapResult(
(JaegerOptions options) => TestJaegerExporter.Run(options.Host, options.Port), (JaegerOptions options) => TestJaegerExporter.Run(options.Host, options.Port),
(ZipkinOptions options) => TestZipkinExporter.Run(options.Uri), (ZipkinOptions options) => TestZipkinExporter.Run(options.Uri),
(PrometheusOptions options) => TestPrometheusExporter.Run(options.Port, options.DurationInMins), (PrometheusOptions options) => TestPrometheusExporter.Run(options.Port),
(MetricsOptions options) => TestMetrics.Run(options), (MetricsOptions options) => TestMetrics.Run(options),
(LogsOptions options) => TestLogs.Run(options), (LogsOptions options) => TestLogs.Run(options),
(GrpcNetClientOptions options) => TestGrpcNetClient.Run(), (GrpcNetClientOptions options) => TestGrpcNetClient.Run(),
@ -85,11 +85,8 @@ namespace Examples.Console
[Verb("prometheus", HelpText = "Specify the options required to test Prometheus")] [Verb("prometheus", HelpText = "Specify the options required to test Prometheus")]
internal class PrometheusOptions internal class PrometheusOptions
{ {
[Option('p', "port", Default = 9184, HelpText = "The port to expose metrics. The endpoint will be http://localhost:port/metrics (This is the port from which your Prometheus server scraps metrics from.)", Required = false)] [Option('p', "port", Default = 9184, HelpText = "The port to expose metrics. The endpoint will be http://localhost:port/metrics/ (this is the port from which your Prometheus server scraps metrics from.)", Required = false)]
public int Port { get; set; } public int Port { get; set; }
[Option('d', "duration", Default = 2, HelpText = "Total duration in minutes to run the demo.", Required = false)]
public int DurationInMins { get; set; }
} }
[Verb("metrics", HelpText = "Specify the options required to test Metrics")] [Verb("metrics", HelpText = "Specify the options required to test Metrics")]

View File

@ -16,6 +16,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Metrics; using System.Diagnostics.Metrics;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -23,73 +24,67 @@ using OpenTelemetry;
using OpenTelemetry.Metrics; using OpenTelemetry.Metrics;
using OpenTelemetry.Trace; using OpenTelemetry.Trace;
namespace Examples.Console namespace Examples.Console;
internal class TestPrometheusExporter
{ {
internal class TestPrometheusExporter private static readonly Meter MyMeter = new Meter("MyMeter");
private static readonly Counter<double> Counter = MyMeter.CreateCounter<double>("myCounter", description: "A counter for demonstration purpose.");
private static readonly Histogram<long> MyHistogram = MyMeter.CreateHistogram<long>("myHistogram");
private static readonly ThreadLocal<Random> ThreadLocalRandom = new ThreadLocal<Random>(() => new Random());
internal static object Run(int port)
{ {
private static readonly Meter MyMeter = new Meter("TestMeter"); /* prometheus.yml
private static readonly Counter<double> Counter = MyMeter.CreateCounter<double>("myCounter", description: "A counter for demonstration purpose.");
private static readonly Histogram<long> MyHistogram = MyMeter.CreateHistogram<long>("myHistogram");
private static readonly ThreadLocal<Random> ThreadLocalRandom = new ThreadLocal<Random>(() => new Random());
internal static object Run(int port, int totalDurationInMins) 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)
Following is sample prometheus.yml config. Adjust port,interval as needed.
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: 'OpenTelemetryTest'
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
static_configs:
- targets: ['localhost:9184']
*/
using var meterProvider = Sdk.CreateMeterProviderBuilder()
.AddMeter(MyMeter.Name)
.AddPrometheusExporter(opt =>
{
opt.StartHttpListener = true;
opt.HttpListenerPrefixes = new string[] { $"http://localhost:{port}/" };
})
.Build();
ObservableGauge<long> gauge = MyMeter.CreateObservableGauge(
"myGauge",
() =>
{ {
return new List<Measurement<long>>() Counter.Add(9.9, new("name", "apple"), new("color", "red"));
{ Counter.Add(99.9, new("name", "lemon"), new("color", "yellow"));
new Measurement<long>(ThreadLocalRandom.Value.Next(1, 1000), new("tag1", "value1"), new("tag2", "value2")), MyHistogram.Record(ThreadLocalRandom.Value.Next(1, 1500), new("tag1", "value1"), new("tag2", "value2"));
new Measurement<long>(ThreadLocalRandom.Value.Next(1, 1000), new("tag1", "value1"), new("tag2", "value3")), Task.Delay(10).Wait();
}; }
}, });
description: "A gauge for demonstration purpose.");
using var token = new CancellationTokenSource(); System.Console.WriteLine($"PrometheusExporter is listening on http://localhost:{port}/metrics/");
Task writeMetricTask = new Task(() => System.Console.WriteLine($"Press any key to exit...");
{ System.Console.ReadKey();
while (!token.IsCancellationRequested) token.Cancel();
{
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(); return null;
} }
});
writeMetricTask.Start();
token.CancelAfter(totalDurationInMins * 60 * 1000); private static IEnumerable<Measurement<double>> GetThreadCpuTime(Process process)
{
System.Console.WriteLine($"OpenTelemetry Prometheus Exporter is making metrics available at http://localhost:{port}/metrics/"); foreach (ProcessThread thread in process.Threads)
System.Console.WriteLine($"Press Enter key to exit now or will exit automatically after {totalDurationInMins} minutes."); {
System.Console.ReadLine(); yield return new(thread.TotalProcessorTime.TotalMilliseconds, new("ProcessId", process.Id), new("ThreadId", thread.Id));
token.Cancel();
System.Console.WriteLine("Exiting...");
return null;
} }
} }
} }