XiHan Framework 处于预览阶段

查看获取方式
跳转到内容

XiHan.Framework.Observability.Host ​

运行信息的默认实现:单例 IHostMonitor 读进程与所在主机的 CPU、内存、磁盘、网卡、GPU、主板与运行时长,后台采样 CPU 使用率与网卡速率。提供 observability.host@1,供管理界面的服务监控使用。

项内容
包 IDXiHan.Framework.Observability.Host
环层Ring 3(实现)
能力提供 observability.host@1(role: default);依赖 kernel.hosting@1
特性入口HostObservabilityFeature(清单 xihan.observability.host,IHostedFeature)
配置节XiHan:Observability:Host
依赖XiHan.Framework.Kernel、XiHan.Framework.Observability.Abstractions;Microsoft.Extensions.Logging.Abstractions;没有其他第三方包
AOT兼容(系统调用经 LibraryImport 源生成)
稳定性Preview

概述 ​

特性被选中时注册三个单例:按当前操作系统创建的平台读取器、后台采样器与 IHostMonitor。StartAsync 同步采第一次样再起采样循环,StopAsync 结束循环,最近算出的值保留(RFC-0023,ADR-0056)。

读取分两类。静态项(CPU 型号与核心、GPU、主板)首次读取后缓存;动态项(内存、磁盘、网卡、运行时)每次当场读。使用率与速率要两次采样求差,由采样器按间隔计算:

量算法
系统 CPU 使用率1 − 空闲增量 / 总增量
进程 CPU 使用率进程处理器时间增量 /(经过时间 × 逻辑核心数)
网卡收发速率累计字节增量 / 经过时间

计数变小(回绕、网卡重建)或总增量为零时该项为空;百分比限制在 0 到 100,不取整。一次采样失败记一条警告,保留上一次的值,循环继续。

何时使用 ​

管理界面要显示服务器状态、运维脚本要按阈值告警时。指标与链路的导出用 Observability.OpenTelemetry,两者互不依赖。Profiles.Full 已装配本包;不需要运行信息又想省下后台采样时,改用 Profiles.Standard 自行组合。

安装与启用 ​

bash
dotnet add package XiHan.Framework.Observability.Host --prerelease

当前是预览版,安装要带 --prerelease;从源码或本地包源引用见快速上手。

csharp
using XiHan.Framework.Hosting.AspNetCore;
using XiHan.Framework.Observability.Host;
using XiHan.Framework.Profiles.Standard;

var builder = WebApplication.CreateBuilder(args);
builder.AddXiHan(xihan => xihan
    .UseStandardProfile()
    .UseFeature<HostObservabilityFeature>());

var app = builder.Build();
app.UseXiHan();
app.Run();

配置 ​

键类型缺省说明
XiHan:Observability:Host:SampleIntervalSeconds数值,(0, 3600]5采样间隔(秒),CPU 使用率与网卡速率是相邻两次采样之差
json
{ "XiHan": { "Observability": { "Host": { "SampleIntervalSeconds": 5 } } } }

取值越界或不是数值时 HostObservabilityOptions.FromConfiguration 抛出 ArgumentException;上限是 HostObservabilityOptions.MaxSampleInterval(1 小时)。

主要类型 ​

类型说明
HostObservabilityFeature能力包入口;启动时采第一次样并起采样循环
HostObservabilityOptionsSampleInterval(缺省 5 秒);ConfigurationSection 为 XiHan:Observability:Host
IHostMonitor(抽象包)七个读取方法,见 Observability.Abstractions

使用示例 ​

服务监控页的端点见可观测性。在测试里等第一次使用率出来再断言:

csharp
using Microsoft.Extensions.DependencyInjection;
using XiHan.Framework.Observability.Abstractions;
using XiHan.Framework.Observability.Host;
using XiHan.Framework.Testing;

public sealed class MonitorTests
{
    [Fact]
    public async Task CpuUsage_AppearsAfterOneInterval()
    {
        await using var host = await TestHost.StartAsync(
            static b => b.UseFeature<HostObservabilityFeature>(),
            [new("XiHan:Observability:Host:SampleIntervalSeconds", "0.1")]);
        var monitor = host.Services.GetRequiredService<IHostMonitor>();

        // 只有 Linux 与 Windows 读得到系统 CPU 时间
        if (OperatingSystem.IsLinux() || OperatingSystem.IsWindows())
        {
            using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10));
            while (monitor.ReadProcessor().UsagePercent is null)
            {
                await Task.Delay(TimeSpan.FromMilliseconds(20), timeout.Token);
            }

            Assert.InRange(monitor.ReadProcessor().UsagePercent!.Value, 0d, 100d);
        }
    }
}

行为与限制 ​

  • 不启动外部命令:只读 BCL、/proc 与 /sys、pci.ids、注册表与 kernel32 的 GetSystemTimes、GetLogicalProcessorInformation、K32GetPerformanceInfo;不用 WMI、PowerShell、dmidecode、lspci、nvidia-smi、top。
  • 读不到的项为 null,列表读不到为空列表;字符串去掉首尾空白后为空也视为读不到。单项失败(权限不足、文件缺失、平台不支持)不影响其他项,读取不抛出、不睡眠、不等待采样。
  • 不暴露命令行参数、环境变量与当前目录。

各平台的读取来源:

项LinuxWindows其他(macOS 等)
CPU 型号、厂商/proc/cpuinfo 的 model name(没有时取 Hardware)、vendor_id注册表 HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0 的 ProcessorNameString、VendorIdentifier空
物理核心、最后一级缓存/sys/devices/system/cpu/cpu<N>/topology/ 与 cpu0/cache/index<N>/GetLogicalProcessorInformation空
标称频率cpu0/cpufreq/base_frequency,没有时取 cpuinfo_max_freq注册表 ~MHz空
CPU 使用率/proc/stat 首行GetSystemTimes空
内存/proc/meminfo 的 MemTotal、MemAvailable、MemFree、Buffers + CachedK32GetPerformanceInfo(空闲为空)空
系统运行时长/proc/uptimeEnvironment.TickCount64Environment.TickCount64
磁盘/proc/self/mounts 里以 /dev/ 开头、不是 /dev/loop 的设备,每个设备取第一个挂载点,容量取 DriveInfoDriveInfo 里就绪的固定、可移动与网络盘同 Windows
网卡NetworkInterface,平台不支持的属性为空同左同左
GPU/sys/class/drm/card<N>/device,名称与厂商名查 pci.ids(/usr/share/hwdata、/usr/share/misc、/usr/share)注册表显示适配器类 {4d36e968-e325-11ce-bfc1-08002be10318} 下 MatchingDeviceId 以 pci 开头的子键空列表
主板/sys/class/dmi/id/ 的 board_*、sys_vendor、product_name、bios_*注册表 HKLM\HARDWARE\DESCRIPTION\System\BIOS(没有序列号)空

已知的取舍:没有 NVIDIA 专有驱动的显存与温度、GPU 与显存使用率;Windows 没有 GPU 温度与主板序列号、没有空闲内存;Linux 的 board_serial 只有 root 读得到;容器里的内存与 CPU 使用率是宿主机的数值,不是 cgroup 限额,逻辑核心数是 .NET 看到的可用核心数。完整的取舍列在 RFC-0023。

相关 ​

Released under The MIT License