我在库中使用 .NET7 中的 System.Diagnostic.Counter 来对具有几个不同标签的事件进行计数。
// Meter creation
private static Meter meter = new Meter("my_library");
// Counter creation
private static Counter<int> myCounter= meter.CreateCounter<int>("my_metric_counter", description: "My counter");
// When event A happens
myCounter.Add(1,
KeyValuePair.Create<string, object>("tag_key", "A");
// When event B happens
myCounter.Add(1,
KeyValuePair.Create<string, object>("tag_key", "B");
包含该库的应用程序使用 Prometheus.NET 启动指标服务器。
applicationBuilder.UseMetricServer();
通过此设置,Prometheus 可以成功抓取应用程序并检索我的指标,如下所示......
my_library_my_metric_counter{tag_key="tag value A"} 10
my_library_my_metric_counter{tag_key="tag value B"} 20
如果计数器中的特定标签在库中大约 10 分钟没有更新,我的问题就会出现。假设“标签值 B”在超过 10 分钟内不被计数。此后,指标抓取仅返回...
my_library_my_metric_counter{tag_key="tag value A"} 100
即使 Prometheus 以 30 秒的间隔不断抓取指标端点,也会发生这种情况。
如果在这 10 分钟时间之后再次对“标签值 B”进行计数,则指标将重新出现在 Prometheus 中(以及应用程序的 /metrics 端点的手动抓取中)。但是,该指标的值将重置为 1。
my_library_my_metric_counter{tag_key="tag value A"} 200
my_library_my_metric_counter{tag_key="tag value B"} 1
我不确定这是否是 .NET System.Diagnostic.Counter 行为或者 Prometheus.NET 指标服务器行为。无论哪种情况,我都在寻找一种方法来保留这些指标,并且在 10 分钟不活动后不会重置它们。
我还要补充一点,我的库代码也有一些 System.Diagnostic.Metrics.ObservableGauge 实例。有趣的是,这些仪表的指标虽然很少更新,但在 10 分钟不更新后并没有在我身上消失(也许是因为抓取本质上是更新?)。有人可能会建议我使用 ObservableGauge 而不是 Counter;但我还没有找到一种将标签与 ObservableGauge 关联起来的方法。
在偶然发现同样的问题后,我发现这个超时是在prometheus-net中配置的,其中有
MeterAdapterOptions.MetricsExpireAfter
。
Metrics.ConfigureMeterAdapter()
进行配置。
所以对我来说,解决方案是使用这样的东西
Program.cs
。这应该在第一次指标收集之前执行:
Metrics.ConfigureMeterAdapter(o => o.MetricsExpireAfter = TimeSpan.FromDays(7));
查看代码,只有当您使用
SuppressDefaultMetrics()
调用 SuppressMeters = false
时,这可能才有效。如果您根本不调用 SuppressDefaultMetrics()
,则可能不会应用 MeterAdapterOptions。