前言
工友們, .NET 6 Preview 7 已經在8月10號釋出了, 除了眾多的功能更新和效能改進之外, 在 preview 7 版本中, 也新增了全新的指標API, System.Diagnostics.Metrics
, 為了讓應用能有更好的可觀測性, 在之前的釋出的.NET 5中, 也把 Activity 增強為 ActivitySource, 主要原因還是 .NET 執行時團隊和 OpenTelemetry .NET SIG 進行了深度合作, 並且一起制定了 OpenTelemetry .NET 指標計劃。
目前 System.Diagnostics.Metrics 這個api還只能在 .NET preview 7 中使用, 當然後邊也會像 System.Text.Json 庫一樣釋出到Nuget平臺, 讓其他版本的 .NET 專案接入使用。
指標介紹
下邊介紹了幾個主要的類
- Meter 用來建立和跟蹤指標Instrument
- MeterListener 用來監聽指標Instrument的值的更新
- Counter 計數器, 一般記錄累加的值, 比如程式中的錯誤數, 請求數 都可以用計數器
- Histogram 直方圖, 記錄可統計的值, 比如記錄下每一個介面的響應時間, 然後再根據時間進行彙總
- ObservableCounter 可觀察計數器, 一般記錄累加的值, 比如 CPU 時間等
- ObservableGauge 可觀測儀表盤, 你可以用來記錄應用的記憶體, GC 的記憶體等
Meter
Meter類用來建立各種指標Instrument, 包括計數器,直方圖,儀表盤指標等等, Meter 類包含了 Name 和 Version 屬性, 你可以設定meter的名稱和版本。
var meter = new Meter("meter","v1.0");
var requestCount = meter.CreateCounter<long>("RequestCount");
var responseTime = meter.CreateHistogram<long>("ResponseTime");
// ...
MeterListener
MeterListener 可以用來監聽指標元件的值變化, 同樣相對應的也有 ActivityListener。
MeterListener listener = new MeterListener();
listener.InstrumentPublished = (instrument, meterListener) =>
{
Console.WriteLine($"EnableMeasurementEvents {instrument.Name} ");
meterListener.EnableMeasurementEvents(instrument);
};
listener.SetMeasurementEventCallback<long>((instrument, measurement, tags, state) =>
{
Console.WriteLine($"Instrument: {instrument.Name} has recorded the measurement {measurement}");
});
listener.MeasurementsCompleted = (instrument, state) =>
{
listener.DisableMeasurementEvents(instrument);
};
listener.Start();
屬性
-
InstrumentPublished 當使用Meter類建立指標Instrument時, 這個回撥可以接收到建立的指標資訊。
-
MeasurementsCompleted 當停止指標的收集時,這個回撥可以接收到相應的指標資訊, 通常是執行了 Meter 和 MeterListener 的Dispose() 方法
方法
-
EnableMeasurementEvents 開啟相應指標Instrument的監聽
-
DisableMeasurementEvents 關閉相應指標Instrument的監聽
-
SetMeasurementEventCallback 設定指標Instrument的測量值更新的回撥
-
RecordObservableInstruments 記錄所有監聽的可觀察指標(Observable instruments)的當前測量值。
-
Start 開啟監聽指標Instrument。
Counter 計數器
Counter是計數器指標,可以用來記錄累加的值,使用非常簡單,下邊的示例中,模擬記錄了程式的請求次數,首先呼叫 CreateCounter 函式建立一個計數器指標 requestCount, 然後呼叫Add 方法, 進行Counter的累加操作。
Meter meter = new Meter("meter","v1.0");
var requestCount = meter.CreateCounter<long>("RequestCount");
for (int i = 0; i < 10; i++)
{
requestCount.Add(1);
}
然後使用上面的 MeterListener 來監聽計數器指標, 程式的輸出如下:
在第一行, MeterListener 檢測到了上面建立的 RequestCount 計數器, 並且開啟了指標的監聽, 當我們呼叫 requestCount.Add(1) 後, MeterListener 捕獲到了指標測量值的更新, 然後在控制檯輸出了相應的值, 需要注意的是, MeasurementEventCallback 回撥方法只會捕獲指標每次更新的測量值, 而不是彙總後的總數,所以這裡的輸出都是1。
Histogram 直方圖
Histogram 是直方圖指標,記錄可統計的值, 比如記錄下每一個介面的響應時間, 然後再根據時間進行彙總, 和 Counter 差不多, 不過指標的維度不一樣, 而且 Histogram 使用Record()方法記錄每次的值,而不是Add()方法。
Meter meter = new Meter("meter","v1.0");
var responseTime = meter.CreateHistogram<long>("ResponseTime");
for (int i = 0; i < 10; i++)
{
var cost = new Random().Next(100,1000);
responseTime.Record(cost);
}
用隨機數表示了介面的響應耗時, 輸出如下:
ObservableCounter 可觀察計數器
ObservableCounter 是可觀察的計數器, 和 Counter 不一樣的是, 建立 ObservableCounter 需要傳入一個Func委託, 來返回一個測量值, 當然也不需要手動呼叫 Add(), Record() 方法, 只需要定時呼叫 MeterListener的RecordObservableInstruments 方法, 獲取當前的指標測量值。
class Program
{
static async Task Main(string[] args)
{
MeterListener listener = new MeterListener();
Start(listener);
AutoRecord(listener);
Meter meter = new Meter("meter","v1.0");
_ = meter.CreateObservableCounter<long>("CPU_Counter",() => new Random().Next(100,1000));
Console.ReadKey();
}
static void Start(MeterListener listener)
{
listener.InstrumentPublished = (instrument, meterListener) =>
{
Console.WriteLine($"EnableMeasurementEvents {instrument.Name} ");
meterListener.EnableMeasurementEvents(instrument);
};
listener.SetMeasurementEventCallback<long>((instrument, measurement, tags, state) =>
{
Console.WriteLine($"Instrument: {instrument.Name} has recorded the measurement {measurement}");
});
listener.MeasurementsCompleted = (instrument, state) =>
{
listener.DisableMeasurementEvents(instrument);
};
listener.Start();
}
static void AutoRecord(MeterListener listener)
{
var cts = new CancellationTokenSource();
_ = Task.Run(async () => {
while (!cts.IsCancellationRequested)
{
await Task.Delay(3000);
listener.RecordObservableInstruments();
}
});
}
}
ObservableGauge 儀表盤指標
這個比較好理解, 你可以用來記錄應用的記憶體,GC 的記憶體等, 同樣是可觀察指標, 也需要傳入一個返回測量值的func委託。
MeterListener listener = new MeterListener();
Start(listener);
AutoRecord(listener);
Meter meter = new Meter("meter","v1.0");
_ = meter.CreateObservableGauge<long>("GC_Memory_Gauge",() => GC.GetTotalMemory(false));
Console.ReadKey();
程式的輸出如下:
總結
本文主要介紹了.NET 6 指標API System.Diagnostics.Metrics,通過這些API, 可以很方便的收集應用的指標資料, 但是本文好像沒有提到資料的聚合彙總? 不要擔心, 執行時團隊針對相應的指標API已經開發了一系列高效能的聚合API, 預計在.NET 6 preview 8 中釋出更新!