- 可观测性
- 指标监控
【免费下载链接】windows_exporter
Prometheus exporter for Windows machines
本文围绕 windows_exporter 中的 license collector 展开:它如何通过 Windows 软件许可 API(slc.dll的SLIsWindowsGenuineLocal)暴露windows_license_status指标、如何在默认禁用的情况下启用该 collector,以及如何使用该指标编写 PromQL 查询与 Prometheus 告警规则。读完后你可以独立在 Windows 主机上启用并监控授权状态,并理解指标背后每一个state标签值的来源。
Collector 概览
license collector 用于暴露 Windows 系统授权(genuineness)状态相关的指标。它在仓库中的基本信息如下(继承自 docs/collector.license.md):
| 项目 | 说明 |
|---|---|
| Metric name prefix | license |
| Data source | Win32 |
| Enabled by default? | No(默认不启用) |
| Flags | 无 |
其中 "Data source: Win32" 指的是该 collector 直接调用 Windows 用户态 API 而非 WMI 查询:从源码看,它通过 Go 的golang.org/x/sys/windows封装调用系统库slc.dll中的SLIsWindowsGenuineLocal函数(见 internal/headers/slc/slc.go)。
启用方式:默认禁用,需显式开启
在 windows_exporter 中,默认启用的 collector 集合由 pkg/collector/types.go 定义:
const DefaultCollectors = "cpu,memory,logical_disk,physical_disk,net,os,service,system"license不在其中,因此必须显式启用。有两种等价方式:
方式一:命令行参数--collectors.enabled
--collectors.enabled=[defaults],license其中[defaults]是一个占位符,启动时会被 cmd/windows_exporter/main.go 中的expandEnabledCollectors展开为上面DefaultCollectors的完整列表:
func expandEnabledCollectors(enabled string) []string { expanded := strings.ReplaceAll(enabled, "[defaults]", collector.DefaultCollectors) return slices.Compact(strings.Split(expanded, ",")) }方式二:配置文件collectors.enabled
参考 docs/example_config.yml 的配置格式,将enabled列表追加license:
collectors: enabled: cpu,logical_disk,net,os,service,system,licenselicense collector 的Config结构体是空结构(见 internal/collector/license/license.go),因此--collector.license.*没有任何可调参数,文档中 "Flags: None" 与此一致:
type Config struct{} //nolint:gochecknoglobals var ConfigDefaults = Config{}该 collector 在 collector 注册表中的挂接点有三处,均可在仓库中查证:
- 构造注册:pkg/collector/collection.go 中
collectors[license.Name] = license.New(&config.License); - YAML 配置映射:pkg/collector/config.go 中
License license.Config \yaml:"license"``; - 命令行 flag 构建器:pkg/collector/map.go 中
license.Name: NewBuilderWithFlags(license.NewWithFlags)。
指标详解:windows_license_status
license collector 只暴露一个指标:
| Name | Description | Type | Labels |
|---|---|---|---|
windows_license_status | license status | gauge | state |
指标名为windows_license_status:前缀windows是全局命名空间常量(internal/types/const.go 中Namespace = "windows"),中间段license来自包内常量const Name = "license",后缀status在Build方法中通过prometheus.BuildFQName(types.Namespace, Name, "status")拼装,并声明了唯一标签state:
c.licenseStatus = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "status"), "Status of windows license", []string{"state"}, nil, )state 标签取值及其来源
state标签共有 5 个可能取值,它们在 internal/collector/license/license.go 的labelMap中由 Windows 许可 API 的枚举常量一一映射而来:
| Windows API 枚举值 | 指标标签值 | 含义 |
|---|---|---|
SL_GEN_STATE_IS_GENUINE | genuine | 系统为正版授权 |
SL_GEN_STATE_INVALID_LICENSE | invalid_license | 许可证无效 |
SL_GEN_STATE_TAMPERED | tampered | 系统文件被篡改,触发 KMS 保护 |
SL_GEN_STATE_OFFLINE | offline | 无法完成在线激活 |
SL_GEN_STATE_LAST | last | 枚举边界值(Windows 文档中的占位枚举) |
这些枚举在 internal/headers/slc/slc.go 中按 WindowsSL_GENUINE_STATE定义顺序声明(iota递增,与 Windows SDK 头文件slpublic.h中的取值一致)。
采集逻辑:one-hot 编码
Collect方法的核心逻辑是对当前授权状态做 one-hot 编码:先调用slc.SLIsWindowsGenuineLocal()取得当前的SL_GENUINE_STATE,然后遍历全部 5 个标签值,命中当前状态的那个取值为 1,其余均为 0:
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error { status, err := slc.SLIsWindowsGenuineLocal() if err != nil { return err } for k, v := range labelMap { val := 0.0 if status == k { val = 1.0 } ch <- prometheus.MustNewConstMetric(c.licenseStatus, prometheus.GaugeValue, val, v) } return nil }采用这种"5 个标签值全部输出、命中者为 1"的编码方式,使得windows_license_status{state="genuine"}可以直接与 0/1 比较,告警表达式因此非常简洁(见下文"告警示例")。
示例输出
一次正常抓取(授权状态为正版时)的输出如下(引自 docs/collector.license.md):
# HELP windows_license_status Status of windows license # TYPE windows_license_status gauge windows_license_status{state="genuine"} 1 windows_license_status{state="invalid_license"} 0 windows_license_status{state="last"} 0 windows_license_status{state="offline"} 0 windows_license_status{state="tampered"} 0底层实现:slc.dll 的 FFI 调用
指标的数据来自 Windows Software Licensing Client 库。internal/headers/slc/slc.go 中的实现值得逐行看一下:
var ( slc = windows.NewLazySystemDLL("slc.dll") procSLIsWindowsGenuineLocal = slc.NewProc("SLIsWindowsGenuineLocal") ) // SLIsWindowsGenuineLocal function wrapper. func SLIsWindowsGenuineLocal() (SL_GENUINE_STATE, error) { var genuineState SL_GENUINE_STATE _, _, err := procSLIsWindowsGenuineLocal.Call( uintptr(unsafe.Pointer(&genuineState)), ) if !errors.Is(err, windows.NTE_OP_OK) { return 0, err } return genuineState, nil }几个实现要点:
SLIsWindowsGenuineLocal(SL_GENUINE_STATE*):Windows 提供的本地查询函数,将查询结果写入调用方分配的SL_GENUINE_STATE变量。它查询的是本机(local)的授权状态,不依赖网络激活服务可达性来判断"是否正版"。- 返回值判断:
golang.org/x/sys/windows的Proc.Call返回的第三个值是函数返回值(NTSTATUS 语义)。这里用errors.Is(err, windows.NTE_OP_OK)判断调用是否成功;失败时Collect会直接返回错误,导致本次抓取在/metrics中体现为采集失败,而不是输出一个误导性的状态值。 - 平台限制:
license.go与slc.go都带有//go:build windows构建标签,该 collector 只能在 Windows 上构建和运行,这与 windows_exporter 整体仅运行于 Windows 的前提一致。
Useful queries
以下查询引自 docs/collector.license.md:
查看授权是否为正版(返回 1 表示正版,0 表示非正版):
windows_license_status{state="genuine"}由于指标采用 one-hot 编码,你还可以用同样的模式检查其他异常状态,例如:
windows_license_status{state="tampered"} windows_license_status{state="invalid_license"}Alerting examples
仓库文档给出了一个可直接用于prometheus.rules的告警规则示例:
- alert: "WindowsLicense" expr: 'windows_license_status{state="genuine"} == 0' for: "10m" labels: severity: "high" annotations: summary: "Windows system license is not genuine" description: "The Windows system license is not genuine. Please check the license status."规则要点:
expr直接利用 one-hot 编码,state="genuine"的取值为 0 即代表当前系统处于invalid_license、tampered或offline中的任一状态;for: 10m提供 10 分钟持续条件,过滤瞬时抖动(例如状态查询偶发失败导致的短暂缺测);- 严重级别标记为
high,因为非正版授权在 Windows 上会导致功能降级、水印提示及 KMS 保护触发,属于需要尽快处理的基础设施问题。
如果希望区分具体原因,可以把表达式细化到具体标签值,例如windows_license_status{state="tampered"} == 1,用于单独追踪文件被篡改导致的 KMS 保护。
测试与验证
license collector 的测试位于 internal/collector/license/license_test.go,包含两个用例:
func BenchmarkCollector(b *testing.B) { testutils.FuncBenchmarkCollector(b, license.Name, license.NewWithFlags) } func TestCollector(t *testing.T) { testutils.TestCollector(t, license.New, nil) }其中testutils.TestCollector(internal/utils/testutils/testutils.go)是仓库统一的真实环境验证框架:它初始化 MI 应用与 session、调用Build完成指标描述符构建、随后执行真实采集并校验输出。由于SLIsWindowsGenuineLocal需要真实的 Windows 环境,该测试只在满足条件的 Windows CI 环境(通过环境变量WINDOWS_EXPORTER_TEST_COLLECTORS声明已预置的 collector 列表)中真正运行,否则会被跳过——这是仓库对系统 API 类 collector 的通用测试策略。
小结
| 关注点 | 结论 |
|---|---|
| 指标 | 仅 1 个:windows_license_status{state},gauge,5 个固定标签值 |
| 数据来源 | slc.dll的SLIsWindowsGenuineLocal(Win32 API,非 WMI) |
| 默认启用 | 否,需通过--collectors.enabled或collectors.enabled显式开启 |
| 可调参数 | 无(Config为空结构) |
| 典型用法 | 监控state="genuine"是否为 1,配合for: 10m的 high 级别告警 |
如果你还需要进一步排查授权问题,可以结合 docs/collector.os.md 等默认启用的 collector 一起观察主机整体状态;而 license collector 本身的价值,就在于用一个最简单的 0/1 指标,把"这台 Windows 是否正版授权"变成了可查询、可告警的 Prometheus 数据。
- 可观测性
- 指标监控
【免费下载链接】windows_exporter
Prometheus exporter for Windows machines
相关推荐
windows_exporter 的 cpu 采集器详解:基于 Windows 性能计数器的 CPU 监控指标、PromQL 查询与告警实践
windows_exporter 的 cpu 采集器详解:基于 Windows 性能计数器的 CPU 监控指标、PromQL 查询与告警实践 本文围绕 wind
可观测性指标监控SkyWalking Windows 监控接入指南:windows_exporter + OpenTelemetry Collector 数据链路与 MAL 指标规则解析
SkyWalking Windows 监控接入指南:windows_exporter + OpenTelemetry Collector 数据链路与 MAL 指
可观测性APM链路追踪指标监控日志分析微服务windows_exporter fsrmquota Collector 详解:用 Prometheus 监控 FSRM 磁盘配额
windows_exporter fsrmquota Collector 详解:用 Prometheus 监控 FSRM 磁盘配额 本文以 fsrmquota
可观测性指标监控
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考