How to Set Up Prometheus Windows Exporter on Windows Server 2012 R2

The Prometheus Windows Exporter (formerly known as wmi_exporter) is an open-source metrics collection agent that exposes Windows performance counters, WMI data, and system metrics in the Prometheus exposition format over HTTP. This makes Windows Server 2012 R2 natively scrapable by Prometheus, enabling integration with the Prometheus/Grafana observability stack that is standard in modern DevOps environments. The exporter collects CPU, memory, disk, network, IIS, MSSQL, scheduled task, and service metrics, among many others, providing deep visibility into WS2012 R2 server health without requiring a commercial monitoring agent. This guide covers downloading, installing, and configuring the Windows Exporter as a service, enabling specific metric collectors, and verifying Prometheus scraping.

Prerequisites

  • Windows Server 2012 R2 with administrator access
  • PowerShell 4.0
  • A Prometheus server configured to scrape the exporter endpoint
  • TCP port 9182 open inbound from the Prometheus server
  • Outbound internet access to download the exporter binary

Step 1: Download the Windows Exporter

The Windows Exporter is distributed as a single MSI installer. Download from the GitHub releases page. Version 0.27+ provides the best collector coverage for WS2012 R2:

$ExporterVersion = "0.27.2"
$ExporterMSI = "windows_exporter-${ExporterVersion}-amd64.msi"
$DownloadUrl = "https://github.com/prometheus-community/windows_exporter/releases/download/v${ExporterVersion}/${ExporterMSI}"

New-Item -ItemType Directory -Path "C:Temp" -Force
Invoke-WebRequest -Uri $DownloadUrl -OutFile "C:Temp$ExporterMSI"

Step 2: Install the Windows Exporter

Install the exporter with a specific set of enabled collectors. The MSI accepts an ENABLED_COLLECTORS property to define which metrics to expose. Choose collectors appropriate for your workload:

$Collectors = "ad,adfs,cache,cpu,cpu_info,cs,dfsr,dhcp,disk,dns,exchange,fsrmquota,iis,logon,memory,msmq,mssql,net,os,process,remote_fx,scheduled_task,service,smb,smbclient,system,tcp,teap,time,vmware"

# Install with specific collectors enabled
Start-Process -FilePath "msiexec.exe" -ArgumentList `
    "/i `"C:Temp$ExporterMSI`"",
    "/quiet /norestart",
    "ENABLED_COLLECTORS=`"$Collectors`"",
    "LISTEN_PORT=9182",
    "LISTEN_ADDR=0.0.0.0" `
    -Wait -PassThru

Write-Host "Windows Exporter installed"

Verify the service is running:

Get-Service "windows_exporter" | Select-Object Name, Status, StartType
netstat -ano | findstr ":9182"

Step 3: Open Firewall Port

New-NetFirewallRule `
    -DisplayName "Prometheus Windows Exporter (9182)" `
    -Direction Inbound `
    -Protocol TCP `
    -LocalPort 9182 `
    -Action Allow `
    -RemoteAddress "prometheus-server-ip"  # Restrict to Prometheus server only

Write-Host "Firewall rule created for port 9182"

Step 4: Verify the Metrics Endpoint

Test that the exporter is serving metrics correctly from a local PowerShell session:

# Check the metrics endpoint
$response = Invoke-WebRequest -Uri "http://localhost:9182/metrics" -UseBasicParsing
$response.StatusCode
$response.Content | Select-String "windows_cpu_time_total" | Select-Object -First 5
$response.Content | Select-String "windows_memory_available_bytes" | Select-Object -First 3

You should see thousands of metric lines in the Prometheus text exposition format, each in the format metric_name{labels} value timestamp.

Step 5: Configure Custom Collector Settings

The MSI installs the exporter with a fixed collector list. To change the configuration after installation, modify the service arguments. Use the Windows Exporter configuration file approach for more complex settings:

# Create a configuration file for advanced settings
$ConfigYaml = @"
collectors:
  enabled: cpu,cpu_info,cs,disk,memory,net,os,process,service,system,tcp,iis,mssql,scheduled_task

collector:
  iis:
    site-include: ".+"
    app-include: ".+"
  mssql:
    enabled-classes: "accessmethods,availreplica,bufman,databases,dbreplica,genstats,locks,memmgr,sqlstats,sqlerrors,transactions,waitstats"
  process:
    include: "java|w3wp|sqlservr|jenkins|tomcat"
  service:
    services-where: "Name LIKE '%'"
  
log:
  level: info
"@

New-Item -ItemType Directory -Path "C:Program Fileswindows_exporter" -Force
Set-Content -Path "C:Program Fileswindows_exporterconfig.yml" -Value $ConfigYaml -Encoding UTF8

# Update service to use config file
$svc = Get-WmiObject Win32_Service -Filter "Name='windows_exporter'"
$svc.Change($null,"$($svc.PathName) --config.file=`"C:Program Fileswindows_exporterconfig.yml`"",$null,$null,$null,$null,$null,$null,$null,$null,$null)
Restart-Service windows_exporter

Step 6: Configure Prometheus to Scrape the Exporter

On your Prometheus server, add the Windows Server 2012 R2 exporter to the scrape configuration in prometheus.yml:

scrape_configs:
  - job_name: 'windows-servers-2012r2'
    scrape_interval: 60s
    scrape_timeout: 30s
    static_configs:
      - targets:
          - 'winserver01.domain.local:9182'
          - 'winserver02.domain.local:9182'
          - 'winserver03.domain.local:9182'
        labels:
          environment: 'production'
          os: 'windows-server-2012r2'
          datacenter: 'primary'
    relabel_configs:
      - source_labels: [__address__]
        target_label: hostname
        regex: '([^:]+)(?::d+)?'
        replacement: '${1}'

Step 7: Create Essential Grafana Dashboard Queries

Once Prometheus is scraping your Windows Exporter, use these PromQL queries in Grafana to build a WS2012 R2 dashboard:

# CPU utilization percentage (all cores average)
100 - (avg by (hostname) (irate(windows_cpu_time_total{mode="idle"}[5m])) * 100)

# Memory available in GB
windows_memory_available_bytes / (1024^3)

# Disk read IOPS
irate(windows_disk_io_total{type="read"}[5m])

# Network receive bytes/sec
irate(windows_net_bytes_received_total[5m])

# IIS requests per second
irate(windows_iis_requests_total[5m])

# Windows services in stopped state
count(windows_service_state{state="stopped"} == 1) by (hostname)

# Scheduled tasks that failed
windows_scheduled_task_last_result == 1

Step 8: Set Up Alerting Rules in Prometheus

Create Prometheus alerting rules to notify on critical conditions:

groups:
  - name: windows-server-2012r2
    interval: 60s
    rules:
      - alert: WindowsHighCPU
        expr: 100 - (avg by (hostname) (irate(windows_cpu_time_total{mode="idle"}[5m])) * 100) > 90
        for: 10m
        labels:
          severity: critical
        annotations:
          summary: "High CPU on {{ $labels.hostname }}"
          description: "CPU utilization is {{ $value }}% for 10+ minutes"

      - alert: WindowsLowDiskSpace
        expr: (windows_logical_disk_free_bytes{volume="C:"} / windows_logical_disk_size_bytes{volume="C:"}) * 100 < 10
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Low disk space on {{ $labels.hostname }}"
          description: "C: drive has less than 10% free space"

      - alert: WindowsExporterDown
        expr: up{job="windows-servers-2012r2"} == 0
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Windows Exporter unreachable on {{ $labels.hostname }}"

Step 9: Verify Complete Metrics Collection

# Check how many metrics are being exposed
$metrics = (Invoke-WebRequest -Uri "http://localhost:9182/metrics" -UseBasicParsing).Content
$metricCount = ($metrics -split "`n" | Where-Object { $_ -notmatch "^#" -and $_ -ne "" }).Count
Write-Host "Total metrics exposed: $metricCount"

# Check specific metric categories
Write-Host "IIS metrics       : $(($metrics -split "`n" | Where-Object { $_ -like "windows_iis*" }).Count)"
Write-Host "MSSQL metrics     : $(($metrics -split "`n" | Where-Object { $_ -like "windows_mssql*" }).Count)"
Write-Host "Service metrics   : $(($metrics -split "`n" | Where-Object { $_ -like "windows_service*" }).Count)"
Write-Host "Process metrics   : $(($metrics -split "`n" | Where-Object { $_ -like "windows_process*" }).Count)"

Summary

The Prometheus Windows Exporter is now running as a Windows service on Windows Server 2012 R2, exposing hundreds of system, application, and infrastructure metrics over HTTP on port 9182. The configuration includes targeted collectors for CPU, memory, disk, network, IIS, MSSQL, services, and scheduled tasks; a Prometheus scrape configuration with server labels; essential PromQL queries for Grafana dashboards; and alerting rules for CPU saturation, low disk space, and exporter availability. This integration brings WS2012 R2 servers into the same Prometheus/Grafana observability stack used for Linux and modern Windows Server workloads, providing consistent, unified monitoring across your entire infrastructure.