Files
windows_exporter/docs/collector.wmi.md
T

20 KiB

wmi collector

The wmi collector runs user-defined WMI queries and exposes numeric properties of the returned instances as named metrics.

Like the performancecounter and registry collectors, each property is mapped to its own metric: the query is a grouping container, and every property under it declares the metric name, type, and labels it is exported as. Unlike those collectors, a query usually returns several instances, so properties can also be turned into labels that tell the instances apart.

Note

Prefer the performancecounter collector when the data is also available as a performance counter. WMI queries are considerably more expensive, and some WMI providers take hundreds of milliseconds per query.

Metric name prefix wmi
Data source WMI (MI)
Enabled by default? No

Flags

--collector.wmi.queries

Queries is a list of WMI queries to run. The value takes the form of a JSON array of objects. YAML is supported.

Caution

If you are using a configuration file, the value must be kept as a string.

Use a |- to keep the value as a string.

Example

collector:
  wmi:
    queries: |-
      - name: logical_disk
        class: Win32_LogicalDisk
        where: DriveType = 3
        label_properties:
          - name: DeviceID
            label: volume
        properties:
          - name: FreeSpace
            metric: windows_wmi_logical_disk_free_bytes
            help: Free space on the logical disk in bytes.
          - name: Size
            metric: windows_wmi_logical_disk_size_bytes
            help: Size of the logical disk in bytes.
      - name: os
        class: Win32_OperatingSystem
        properties:
          - name: LastBootUpTime
            metric: windows_wmi_os_last_boot_timestamp_seconds
            help: Time of the last boot as a Unix timestamp.
          - name: FreePhysicalMemory
            metric: windows_wmi_os_physical_free_bytes
            help: Free physical memory in bytes.
            multiplier: 1024 # WMI reports kilobytes
          - name: NumberOfProcesses

FreePhysicalMemory shows the multiplier; the memory collector already exports this value as windows_memory_physical_free_bytes.

Schema

YAML:

- name: logical_disk # required, unique ID for the query
  namespace: root/CIMv2 # optional
  class: Win32_LogicalDisk # required
  where: DriveType = 3 # optional
  label_properties: # optional
    - name: DeviceID # WMI property name
      label: volume # optional
  properties:
    - name: FreeSpace # WMI property name
      metric: windows_wmi_logical_disk_free_bytes # optional
      help: Free space on the logical disk in bytes. # optional
      type: gauge # optional
      multiplier: 1 # optional
      labels: # optional
        source: wmi

JSON:

[
  {
    "name": "logical_disk",
    "namespace": "root/CIMv2",
    "class": "Win32_LogicalDisk",
    "where": "DriveType = 3",
    "label_properties": [
      { "name": "DeviceID", "label": "volume" }
    ],
    "properties": [
      {
        "name": "FreeSpace",
        "metric": "windows_wmi_logical_disk_free_bytes",
        "help": "Free space on the logical disk in bytes.",
        "type": "gauge",
        "multiplier": 1,
        "labels": { "source": "wmi" }
      }
    ]
  }
]

The collector builds the WQL statement from the configuration:

SELECT <label_properties>, <properties> FROM <class> [WHERE <where>]

name

Required, unique ID for the query. It is used as the query label on windows_wmi_query_success and windows_wmi_query_duration_seconds, to identify the query in logs, and to seed auto-generated metric names (see Metric naming). Duplicates are rejected at build time, and so are names that only differ in case or special characters (os and OS, or my_disk and my-disk), because they produce the same metric names.

namespace

The WMI namespace of the class. Optional — defaults to root/CIMv2. Backslashes are accepted as well, for example root\Microsoft\Windows\Storage.

class

The WMI class to query, for example Win32_LogicalDisk. Required. Only letters, digits and _ are allowed.

where

An optional WQL condition appended as the WHERE clause, for example DriveType = 3 or Name LIKE 'sql%'. It is passed to WMI verbatim.

label_properties

The list of properties exported as labels on every metric of the query. Use them to tell the returned instances apart, typically with the key property of the class (DeviceID, Name, …). Optional.

String, boolean and integer properties are supported. A property without a value (null) becomes an empty label value. A label property of any other type, for example a datetime, fails the whole query at scrape time, and none of its metrics are exported.

The label properties must uniquely identify every returned instance. Two instances with identical label values produce duplicate series, which are dropped and logged at scrape time.

label_properties Sub-Schema

name

The name of the WMI property. Required.

label

The name of the label. Optional — defaults to the property name, lowercased, with every character that is not a letter or digit replaced by _ and leading and trailing _ trimmed. Each label must be unique within a query.

properties

The list of WMI properties to export as metrics. At least one property must be listed. Property names are matched case-insensitively, and a property listed more than once under one query is rejected as a duplicate.

The following property types are supported:

WMI type Exported value
boolean 1 for true, 0 for false
uint8/sint8 … uint64/sint64 the number
real32, real64 the number
datetime (timestamp) seconds since the Unix epoch
datetime (interval) seconds

A property without a value (null) is skipped for that instance rather than exported as 0. A property of any other type, for example a string or an array, fails the query at scrape time (see windows_wmi_query_success).

properties Sub-Schema

name

The name of the WMI property. Required.

metric

The name of the metric to expose. Optional — if omitted, a name is generated automatically. See Metric naming for the exact rules and examples.

Properties may deliberately share a metric name, also across queries, as long as they agree on help text, type and label names, and their labels keep the series apart. Build rejects identical series within a query, and across queries without label properties. For queries with label properties, the series depend on the instances returned at runtime; duplicates are dropped and logged at scrape time.

The names windows_wmi_query_success and windows_wmi_query_duration_seconds are reserved for the collector's own metrics.

help

The metric # HELP text. Optional — if omitted, it defaults to windows_exporter: custom WMI metric.

type

The metric type. The value can be gauge or counter. If not specified, it defaults to gauge.

This key is optional.

multiplier

A factor that the value is multiplied by before it is exported, to convert it to the base unit the Prometheus naming conventions ask for. For example, 0.001 converts milliseconds to seconds, 0.01 percent to a ratio, 3600 hours to seconds and 1024 kilobytes to bytes. It must be a positive number, so counters keep counting up. If the multiplier is the reciprocal of an integer, like 0.001, the value is divided by that integer instead, which avoids rounding artifacts such as 0.009000000000000001. If not specified, the value is exported as is.

This key is optional.

labels

Labels is a map of key-value pairs that will be added as constant labels to the metric. A constant label may not use the name of a label property.

This key is optional.

Metrics

The wmi collector returns one metric per configured property and returned instance, named and typed according to the configuration, plus a success and a duration metric per query.

Name Description Type Labels
user defined Numeric value of a configured WMI property gauge / counter label properties, user defined
windows_wmi_query_success Whether the query ran and all of its configured properties could be read (0, 1) gauge query
windows_wmi_query_duration_seconds Duration of the query gauge query

A windows_wmi_query_success value of 0 means one of:

  • The query failed, for example because the namespace, class or a property does not exist, the where clause is invalid, or a label property has an unsupported type. Nothing is exported for the query.
  • The scrape timeout ran out (see Notes). Instances read before that are exported.
  • At least one configured property could not be converted to a number. All other properties are still exported.

Failing queries are logged as warnings, but do not mark the whole collector as failed: windows_exporter_collector_success{collector="wmi"} stays 1, like for the registry collector. Alert on windows_wmi_query_success instead.

Build only validates the configuration; it does not run the queries. A class that is missing on a host is therefore reported via windows_wmi_query_success rather than preventing the exporter from starting.

Metric naming

Each property is exported under its own metric name. You can set it explicitly with the metric field, or let the collector generate one.

Explicit name. When metric is set, it is used verbatim. You are responsible for following the Prometheus naming conventions (a windows_ prefix, and a unit suffix such as _bytes, _seconds or _timestamp_seconds where applicable).

Auto-generated name. When metric is omitted, the name is assembled as:

windows_wmi_<query>_<property>

where <query> is the query name and <property> is the WMI property name. The whole string is then lowercased, every character that is not a letter or digit is replaced with _, and leading/trailing _ are trimmed.

Example:

- name: os
  class: Win32_OperatingSystem
  properties:
    - name: NumberOfProcesses

→ windows_wmi_os_numberofprocesses

Example metric

For the example configuration above:

# HELP windows_wmi_logical_disk_free_bytes Free space on the logical disk in bytes.
# TYPE windows_wmi_logical_disk_free_bytes gauge
windows_wmi_logical_disk_free_bytes{volume="C:"} 4.20703092736e+11
windows_wmi_logical_disk_free_bytes{volume="D:"} 2.9705715712e+10
# HELP windows_wmi_logical_disk_size_bytes Size of the logical disk in bytes.
# TYPE windows_wmi_logical_disk_size_bytes gauge
windows_wmi_logical_disk_size_bytes{volume="C:"} 9.99132491776e+11
windows_wmi_logical_disk_size_bytes{volume="D:"} 4.60898430976e+11
# HELP windows_wmi_os_last_boot_timestamp_seconds Time of the last boot as a Unix timestamp.
# TYPE windows_wmi_os_last_boot_timestamp_seconds gauge
windows_wmi_os_last_boot_timestamp_seconds 1.791272732355078e+09
# HELP windows_wmi_os_numberofprocesses windows_exporter: custom WMI metric
# TYPE windows_wmi_os_numberofprocesses gauge
windows_wmi_os_numberofprocesses 478
# HELP windows_wmi_os_physical_free_bytes Free physical memory in bytes.
# TYPE windows_wmi_os_physical_free_bytes gauge
windows_wmi_os_physical_free_bytes 1.6777216e+10
# HELP windows_wmi_query_duration_seconds Duration of the WMI query.
# TYPE windows_wmi_query_duration_seconds gauge
windows_wmi_query_duration_seconds{query="logical_disk"} 0.0375302
windows_wmi_query_duration_seconds{query="os"} 0.1690887
# HELP windows_wmi_query_success Whether the WMI query and all of its configured properties could be read successfully.
# TYPE windows_wmi_query_success gauge
windows_wmi_query_success{query="logical_disk"} 1
windows_wmi_query_success{query="os"} 1

Notes

  • The queries run one after another and share the scrape timeout. A query that is still running when it runs out is cancelled, and the remaining queries are skipped; all of them report windows_wmi_query_success 0. Keep queries narrow with where, avoid slow providers, and check windows_wmi_query_duration_seconds.
  • uint64 and sint64 values larger than 2^53 lose precision when converted to the 64-bit float used by Prometheus.
  • WQL ASSOCIATORS OF and REFERENCES OF queries are not supported.

More examples

The values in these examples are already in base units: datetime properties are exported as Unix timestamps in seconds, and the others are flags or status codes, so they need no multiplier.

Microsoft Defender Antivirus

The status of Microsoft Defender Antivirus is in the MSFT_MpComputerStatus class, which returns one instance. Windows has no performance counters for it. The query takes about 50 ms and works without administrator rights. On hosts without Defender, for example Windows Server without the feature installed, the namespace is missing and windows_wmi_query_success{query="defender"} is 0. With a third-party antivirus, Defender turns itself off or, on devices onboarded to Microsoft Defender for Endpoint, runs in passive mode; the running_mode label shows which. The label is on every series of the query, so a change of the mode starts new series.

collector:
  wmi:
    queries: |-
      - name: defender
        namespace: root/Microsoft/Windows/Defender
        class: MSFT_MpComputerStatus
        label_properties:
          - name: AMRunningMode
            label: running_mode
        properties:
          - name: AntivirusEnabled
            metric: windows_wmi_defender_protection_enabled
            help: Whether a Microsoft Defender protection feature is enabled.
            labels:
              feature: antivirus
          - name: RealTimeProtectionEnabled
            metric: windows_wmi_defender_protection_enabled
            help: Whether a Microsoft Defender protection feature is enabled.
            labels:
              feature: real_time_protection
          - name: BehaviorMonitorEnabled
            metric: windows_wmi_defender_protection_enabled
            help: Whether a Microsoft Defender protection feature is enabled.
            labels:
              feature: behavior_monitor
          - name: IsTamperProtected
            metric: windows_wmi_defender_protection_enabled
            help: Whether a Microsoft Defender protection feature is enabled.
            labels:
              feature: tamper_protection
          - name: AntivirusSignatureLastUpdated
            metric: windows_wmi_defender_signature_last_updated_timestamp_seconds
            help: Time of the last Microsoft Defender signature update as a Unix timestamp.
            labels:
              signature: antivirus
          - name: DefenderSignaturesOutOfDate
            metric: windows_wmi_defender_signatures_out_of_date
            help: Whether the Microsoft Defender signatures are out of date.
          - name: QuickScanEndTime
            metric: windows_wmi_defender_scan_end_timestamp_seconds
            help: End time of the last Microsoft Defender scan as a Unix timestamp.
            labels:
              scan: quick
          - name: FullScanEndTime
            metric: windows_wmi_defender_scan_end_timestamp_seconds
            help: End time of the last Microsoft Defender scan as a Unix timestamp.
            labels:
              scan: full
          - name: RebootRequired
            metric: windows_wmi_defender_reboot_required
            help: Whether Microsoft Defender needs a reboot to finish an action.

Other boolean properties of the class, such as AntispywareEnabled, IoavProtectionEnabled and NISEnabled, can be added the same way, and AntispywareSignatureLastUpdated and NISSignatureLastUpdated with their own signature label. A scan that never ran has no end time, so its series is missing; the query still reports success. Older Defender platforms may lack some properties, for example IsTamperProtected; a missing property fails the whole query, so remove it from the list there.

Example output (excerpt):

windows_wmi_defender_protection_enabled{feature="antivirus",running_mode="Normal"} 1
windows_wmi_defender_protection_enabled{feature="real_time_protection",running_mode="Normal"} 1
windows_wmi_defender_scan_end_timestamp_seconds{running_mode="Normal",scan="quick"} 1.792057959101e+09
windows_wmi_defender_signature_last_updated_timestamp_seconds{running_mode="Normal",signature="antivirus"} 1.792124105e+09
windows_wmi_defender_signatures_out_of_date{running_mode="Normal"} 0

Disk health and SMART data

MSFT_PhysicalDisk has the health status that Windows derives from the SMART data of the disk, and MSStorageDriver_FailurePredictStatus the SMART failure prediction. The disk label is the disk number, the same as in the physical_disk collector.

  • MSFT_PhysicalDisk works without administrator rights.
  • MSStorageDriver_FailurePredictStatus needs administrator rights. The exporter has them when it runs as a service (LocalSystem); as a regular user, the query fails with MI_RESULT_ACCESS_DENIED. It only returns disks whose driver implements SMART failure prediction, usually SATA disks and not NVMe disks or virtual disks. It names the device by its PnP instance name, not by disk number.
collector:
  wmi:
    queries: |-
      - name: physical_disk_health
        namespace: root/Microsoft/Windows/Storage
        class: MSFT_PhysicalDisk
        label_properties:
          - name: DeviceId
            label: disk
          - name: FriendlyName
            label: model
        properties:
          - name: HealthStatus
            metric: windows_wmi_physical_disk_health_status
            help: Health status of the physical disk (0 healthy, 1 warning, 2 unhealthy, 5 unknown).
      - name: disk_failure_predict
        namespace: root/wmi
        class: MSStorageDriver_FailurePredictStatus
        label_properties:
          - name: InstanceName
            label: device
        properties:
          - name: PredictFailure
            metric: windows_wmi_disk_failure_predicted
            help: Whether the SMART self-monitoring of the disk predicts a failure.

The parsed SMART attributes, such as temperature, wear and power-on hours (Get-StorageReliabilityCounter), are in MSFT_StorageReliabilityCounter. Windows only returns them through the association with MSFT_PhysicalDisk; a query of the class returns no instances, even as LocalSystem. The wmi collector does not support association queries, so it cannot read them.

Useful queries

Free space ratio per volume:

windows_wmi_logical_disk_free_bytes / windows_wmi_logical_disk_size_bytes

Age of the Microsoft Defender signatures in seconds:

time() - windows_wmi_defender_signature_last_updated_timestamp_seconds

Alerting examples

WMIQueryFailure also fires for queries of classes that are missing on a host, for example the Defender query on Windows Server without Defender. Scope it with a query matcher where needed.

prometheus.rules

  - alert: WMIQueryFailure
    expr: windows_wmi_query_success == 0
    for: 15m
    labels:
      severity: warning
    annotations:
      summary: "WMI query failed (instance {{ $labels.instance }})"
      description: "The WMI query {{ $labels.query }} failed for 15 minutes."

  - alert: DefenderSignaturesOutdated
    expr: time() - windows_wmi_defender_signature_last_updated_timestamp_seconds{running_mode="Normal",signature="antivirus"} > 3 * 86400
    for: 1h
    labels:
      severity: warning
    annotations:
      summary: "Defender signatures outdated (instance {{ $labels.instance }})"
      description: "The Microsoft Defender signatures were last updated more than 3 days ago."

  - alert: DiskUnhealthy
    expr: windows_wmi_physical_disk_health_status == 2
    for: 15m
    labels:
      severity: critical
    annotations:
      summary: "Disk unhealthy (instance {{ $labels.instance }})"
      description: "Windows reports disk {{ $labels.disk }} ({{ $labels.model }}) as unhealthy."

  - alert: DiskHealthWarning
    expr: windows_wmi_physical_disk_health_status == 1
    for: 15m
    labels:
      severity: warning
    annotations:
      summary: "Disk health warning (instance {{ $labels.instance }})"
      description: "Windows reports a health warning for disk {{ $labels.disk }} ({{ $labels.model }})."