Meter 是指标采集入口,负责创建管理 Counter、Histogram、Gauge;MeterListener 是需显式注册启用的监听者,用于订阅过滤导出指标。

什么是 Meter 和 MeterListener?
Meter 是指标采集的入口,负责创建和管理计数器(Counter)、直方图(Histogram)、仪表(Gauge)等指标对象;MeterListener 则是监听者,用于订阅、过滤、采样或导出指标数据——它不自动收集,必须显式启用(meterListener.Register() )才能生效。
如何创建并使用 Counter 记录请求次数
最常用的是整数计数器,适合记录 HTTP 请求、消息处理等离散事件:
Meter meter = new Meter("myapp.http", "1.0");
Counter requestCounter = meter.CreateCounter("http.requests.total");
// 每次请求调用
requestCounter.Add(1, new KeyValuePair("method", "GET"));
requestCounter.Add(1, new KeyValuePair("method", "POST"));
- 标签(
KeyValuePair)必须是只读且不可变的;传入可变字典或匿名对象会抛ArgumentException - 不要在热路径反复新建
Tag实例,建议缓存复用new[] { new KeyValuePair("method", "GET") } -
Add()是线程安全的,但避免在锁内调用——它内部有无锁优化
为什么 MeterListener 没有收到指标?
常见原因是没启用监听或过滤太严。默认情况下 MeterListener 不监听任何 Meter,必须显式注册并设置匹配逻辑:
MeterListener listener = new MeterListener();
listener.InstrumentPublished = (instrument, meter) =>
{
if (meter.Name == "myapp.http" && instrument.Name == "http.requests.total")
listener.EnableMeasurementReporting(instrument);
};
listener.Start(); // 必须调用!
-
Start()必须在InstrumentPublished回调中调用EnableMeasurementReporting()之后,否则指标被丢弃 - 如果应用启动时
Meter已创建(如 DI 容器提前构造),需在listener.Start()前调用listener.RecordObservableInstrument()或确保监听器注册早于指标初始化 -
SetMeasurementEventCallback只对() ObservableCounter/ObservableGauge生效,普通Counter走MeasurementRecorded
直方图 Histogram 怎么记录延迟并避免性能抖动?
Histogram 适合记录响应时间等分布型指标,但要注意:它的 Record() 方法默认不采样,高频打点会显著影响性能:
HistogramlatencyHist = meter.CreateHistogram ("http.request.duration", unit: "ms"); latencyHist.Record(elapsedMs, new KeyValuePair ("status_code", 200));
- 若每秒调用超千次,建议搭配
MeterListener在回调中做采样(如每 10 次取 1 次),而不是在业务代码里判断 - 内置分位数计算(如 P95)由导出端(如 OpenTelemetry Collector)完成,
Histogram本身只存原始观测值 + 边界桶(bucket) - 不要用
double.NaN或double.PositiveInfinity调用Record(),会触发静默丢弃(无异常,但不计入)
真正容易被忽略的是生命周期管理:Meter 无需释放,但 MeterListener 应在应用退出前调用 Stop(),否则可能持有对 Meter 的引用导致 GC 延迟;同时,多个 MeterListener 实例之间不共享状态,各自独立过滤和回调。










