用 36 行 C# 寫個 CPU、RAM、Disk 效能監視 WebAPI
2 | 7,813 |
前幾天分享過好用的 CPU/RAM/Disk 效能監視 CLI 工具,並用它 結合 K6 壓力測試在圖表呈現 CPU 使用率(下圖藍線):
這個做法雖然可行,但操作起來頗麻煩。得在測試前登入目標主機執行 typeperf -cf counters.txt -si 1
,測試完成按 Ctrl-C 中斷程式,把 CSV 檔帶回來給解析程式以做成圖表。
於是我開始動腦筋優化流程:若 CPU/RAM 等效能數值能透過 WebAPI 查詢,會更容易整合進 K6 測試,壓測時一併蒐集 CPU 數據寫進結果 JSON,產生報表時一起解析畫進圖表,豈不美滋滋?
(註:這個 WebAPI 需放在壓測對象主機執行,過程可能因該主機 CPU 100% 導致無回應或延遲,但考慮這些數據純為參考觀察趨勢用,不需絕對準確,漏拍或延遲幾秒還可被接受)
不囉嗦,捲起袖子我寫了個超簡單的 ASP.NET Core Minimal API。在 Program.cs 中啟動 Process 執行 typeperf,再由 StandardOutput Stream 讀取每秒一次的輸出,更新最近狀態透過 HTTP GET 存取。只用了 36 行就寫好一個提供 HTTP 查詢 CPU/RAM/Disk 即時使用率的 WebAPI (原本想走 UDP 更輕巧,但考慮呼叫方便,最後仍決定用 WebAPI)。要讀取哪些計數器可透過 counters.txt 自訂(細節請參考前文),可視需要彈性擴充調整。另外,針對未來也會測試 Linux,我順手加上偵測 OS 改用 vmstate -1
取代 typeperf
的邏輯,讓程式也能在 Linux 執行。完整程式碼如下:
using System.Diagnostics;
using System.Runtime.InteropServices;
string perfCounters = string.Empty;
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
throw new NotImplementedException("OSX not supported yet");
var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
var task = Task.Factory.StartNew(() =>
{
var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = isLinux ? "vmstat" : "typeperf.exe",
Arguments = isLinux ? "1" : "-cf counters.txt",
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
proc.Start();
while (!proc.StandardOutput.EndOfStream)
{
var line = proc.StandardOutput.ReadLine();
if (string.IsNullOrEmpty(line) || line.Contains("s")) continue;
try
{
string[] parts = isLinux ?
line.Split(' ', StringSplitOptions.RemoveEmptyEntries) :
line.Split(',').Skip(1).Select(o => o.Trim('"')).ToArray();
perfCounters = $"{DateTime.Now:HH:mm:ss.fff},{string.Join(",", parts)}";
} catch { /* ignore */ }
}
});
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => perfCounters);
app.Run();
在 Windows 執行 OK:
在 Linux 執行也沒問題:
就醬,又用 .NET 輕鬆搞定一件需求。好久沒呼口號了,今天來一下:
.NET 好威呀,C# 真棒!
原始碼已放上 Github,想玩的同學請自取。
The program collects performance counter data using the typeperf command on Windows and the vmstat command on Linux, with a one-second interval. The collected data is used to update the latest status and is provided to the client through HTTP GET for querying.
Comments
# by 57
如果要指定 port 要怎麼改?
# by Jeffrey
to 57,可參考這篇 https://blog.darkthread.net/blog/set-kestrel-port/