collector: publish base units and _total counter names (#2743)

Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
Jan-Otto Kröpke
2026-10-16 10:48:26 +02:00
committed by GitHub
parent dc8092f46d
commit 3fb18521f6
131 changed files with 1674 additions and 1459 deletions
+8 -8
View File
@@ -1,7 +1,7 @@
local b = import 'builders.libsonnet';
local host = '{job=~"$job", instance="$instance"}';
local cores = 'scalar(max(windows_cpu_logical_processor' + host + '))';
local mode(m) = 'sum(rate(windows_cpu_time_total{job=~"$job", instance="$instance", mode="' + m + '"}[$__rate_interval])) / ' + cores;
local mode(m) = 'sum(rate(windows_cpu_time_seconds_total{job=~"$job", instance="$instance", mode="' + m + '"}[$__rate_interval])) / ' + cores;
function(on)
b.tab(
@@ -13,7 +13,7 @@ function(on)
if on('cpu') then b.row('System calls and frequency', b.flow([if on('system') then [29, 12, 8], [30, 12, 8]])),
]),
[
b.stat(160, 'CPU busy', 'Non-idle CPU time averaged across logical processors.', '1 - avg(clamp_max(rate(windows_cpu_time_total{job=~"$job", instance="$instance", mode="idle"}[$__rate_interval]), 1))', 'percentunit', steps=b.levels(0.8, 0.9))
b.stat(160, 'CPU busy', 'Non-idle CPU time averaged across logical processors.', '1 - avg(clamp_max(rate(windows_cpu_time_seconds_total{job=~"$job", instance="$instance", mode="idle"}[$__rate_interval]), 1))', 'percentunit', steps=b.levels(0.8, 0.9))
+ b.panel.withDefaults({ decimals: 1, max: 1, min: 0 }),
b.stat(161, 'User', 'CPU time spent in user mode, as a share of all logical processors.', mode('user'), 'percentunit')
+ b.panel.withDefaults({ decimals: 1, min: 0 }),
@@ -22,12 +22,12 @@ function(on)
b.stat(163, 'Queue per CPU', 'Threads waiting for a CPU per logical processor. A sustained value above 2 indicates CPU contention.', 'windows_system_processor_queue_length' + host + ' / ' + cores, 'short', steps=b.levels(1, 2))
+ b.panel.withDefaults({ decimals: 2, min: 0 }),
b.stat(164, 'Ctx switches', 'Context switches per second across the host.', 'rate(windows_system_context_switches_total' + host + '[$__rate_interval])', 'ops'),
b.stat(165, 'Frequency', 'Average effective frequency across logical processors. Values above the nominal frequency mean turbo boost.', 'avg(1e4 * windows_cpu_core_frequency_mhz' + host + ' * rate(windows_cpu_processor_performance_total' + host + '[$__rate_interval]) / rate(windows_cpu_processor_mperf_total' + host + '[$__rate_interval]))', 'hertz'),
b.stat(165, 'Frequency', 'Average effective frequency across logical processors. Values above the nominal frequency mean turbo boost.', 'avg(1e-2 * windows_cpu_core_frequency_hertz' + host + ' * rate(windows_cpu_processor_performance_total' + host + '[$__rate_interval]) / rate(windows_cpu_processor_mperf_total' + host + '[$__rate_interval]))', 'hertz'),
b.panel.new(24, 'CPU utilization by mode', 'timeseries')
+ b.panel.withDescription('Share of total CPU time across all logical processors.')
+ b.panel.withQueries([
b.query.new('sum by (mode) (rate(windows_cpu_time_total{job=~"$job", instance="$instance", mode!="idle"}[$__rate_interval])) / scalar(count(windows_cpu_time_total{job=~"$job", instance="$instance", mode="idle"}))', 'A')
b.query.new('sum by (mode) (rate(windows_cpu_time_seconds_total{job=~"$job", instance="$instance", mode!="idle"}[$__rate_interval])) / scalar(count(windows_cpu_time_seconds_total{job=~"$job", instance="$instance", mode="idle"}))', 'A')
+ b.query.withLegendFormat('{{mode}}'),
])
+ b.panel.withDefaults({
@@ -44,7 +44,7 @@ function(on)
b.panel.new(25, 'CPU utilization per core', 'state-timeline')
+ b.panel.withDescription('Busy time of each logical processor, labelled processor group,core. Green is idle, red is fully busy.')
+ b.panel.withQueries([
b.query.new('label_replace(clamp(1 - rate(windows_cpu_time_total{job=~"$job", instance="$instance", mode="idle"}[$__rate_interval]), 0, 1), "core", "$1,0$2", "core", "(\\\\d+),(\\\\d)")', 'A')
b.query.new('label_replace(clamp(1 - rate(windows_cpu_time_seconds_total{job=~"$job", instance="$instance", mode="idle"}[$__rate_interval]), 0, 1), "core", "$1,0$2", "core", "(\\\\d+),(\\\\d)")', 'A')
+ b.query.withLegendFormat('{{core}}'),
])
+ b.panel.withDefaults({
@@ -151,11 +151,11 @@ function(on)
b.panel.new(30, 'CPU frequency', 'timeseries')
+ b.panel.withDescription('Effective frequency from the APERF/MPERF counters, averaged and maximum across logical processors, against the nominal frequency. Values above nominal mean turbo boost.')
+ b.panel.withQueries([
b.query.new('avg(1e4 * windows_cpu_core_frequency_mhz{job=~"$job", instance="$instance"} * rate(windows_cpu_processor_performance_total{job=~"$job", instance="$instance"}[$__rate_interval]) / rate(windows_cpu_processor_mperf_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'A')
b.query.new('avg(1e-2 * windows_cpu_core_frequency_hertz{job=~"$job", instance="$instance"} * rate(windows_cpu_processor_performance_total{job=~"$job", instance="$instance"}[$__rate_interval]) / rate(windows_cpu_processor_mperf_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'A')
+ b.query.withLegendFormat('average'),
b.query.new('max(1e4 * windows_cpu_core_frequency_mhz{job=~"$job", instance="$instance"} * rate(windows_cpu_processor_performance_total{job=~"$job", instance="$instance"}[$__rate_interval]) / rate(windows_cpu_processor_mperf_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'B')
b.query.new('max(1e-2 * windows_cpu_core_frequency_hertz{job=~"$job", instance="$instance"} * rate(windows_cpu_processor_performance_total{job=~"$job", instance="$instance"}[$__rate_interval]) / rate(windows_cpu_processor_mperf_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'B')
+ b.query.withLegendFormat('maximum'),
b.query.new('avg(windows_cpu_core_frequency_mhz{job=~"$job", instance="$instance"}) * 1e6', 'C')
b.query.new('avg(windows_cpu_core_frequency_hertz{job=~"$job", instance="$instance"})', 'C')
+ b.query.withLegendFormat('nominal'),
])
+ b.panel.withDefaults({
+3 -3
View File
@@ -392,7 +392,7 @@ function(on)
b.joinedTable(202, 'Drives', 'Model, size, partitions and operational status of each drive. Requires the diskdrive collector.', 'disk', [
'max by (disk, model) (' + drive('info') + ')',
'max by (disk) (' + drive('size') + ')',
'max by (disk) (' + drive('size_bytes') + ')',
'max by (disk) (' + drive('partitions') + ')',
'max by (disk, status) (' + drive('status') + ' == 1)',
], [['disk', 'Disk'], ['model', 'Model'], ['Value #B', 'Size'], ['Value #C', 'Partitions'], ['status', 'Status']], [
@@ -444,10 +444,10 @@ function(on)
'max by (name) (' + spaces('virtual_disk_size_bytes') + ')',
'max by (name) (' + spaces('virtual_disk_allocated_size_bytes') + ')',
'max by (name) (' + spaces('virtual_disk_footprint_on_pool_bytes') + ')',
'max by (name) (' + spaces('virtual_disk_storage_efficiency_percent') + ')',
'max by (name) (' + spaces('virtual_disk_storage_efficiency_ratio') + ')',
], [['name', 'Virtual disk'], ['Value #A', 'Health'], ['Value #B', 'Size'], ['Value #C', 'Allocated'], ['Value #D', 'Footprint'], ['Value #E', 'Efficiency']], [
health,
{ matcher: { id: 'byName', options: 'Efficiency' }, properties: [{ id: 'unit', value: 'percent' }, { id: 'decimals', value: 1 }] },
{ matcher: { id: 'byName', options: 'Efficiency' }, properties: [{ id: 'unit', value: 'percentunit' }, { id: 'decimals', value: 1 }] },
] + bytes(['Size', 'Allocated', 'Footprint'])),
b.graph(244, 'Pool usage', 'Allocated share of each storage pool, excluding the primordial pool. A full pool cannot extend thin-provisioned virtual disks, which then fail writes.', 'percent', [['100 * ' + pool('allocated_size_bytes') + ' / ' + pool('size_bytes'), '{{name}}']])
+3 -3
View File
@@ -2,7 +2,7 @@ local b = import 'builders.libsonnet';
local hosts = 'windows_os_hostname{job=~"$job", hostname=~"$hostname"}';
// Counts hosts matching expr, a vector by instance. Falls back to 0 while hosts are selected.
local countHosts(expr) = 'count((' + expr + ') and on (instance) ' + hosts + ') or (0 * count(' + hosts + '))';
local cpuBusy = '100 * (1 - avg by (instance) (clamp_max(rate(windows_cpu_time_total{job=~"$job", mode="idle"}[$__rate_interval]), 1)))';
local cpuBusy = '100 * (1 - avg by (instance) (clamp_max(rate(windows_cpu_time_seconds_total{job=~"$job", mode="idle"}[$__rate_interval]), 1)))';
local memoryUsed = '100 * (1 - windows_memory_physical_free_bytes{job=~"$job"} / windows_memory_physical_total_bytes{job=~"$job"})';
local volumeFree = '100 * windows_logical_disk_free_bytes{job=~"$job", volume!~"HarddiskVolume.*"} / windows_logical_disk_size_bytes{job=~"$job", volume!~"HarddiskVolume.*"}';
local attention = [{ color: 'green', value: null }, { color: 'orange', value: 1 }];
@@ -49,7 +49,7 @@ function(on, config, overview=null)
b.query.new('(max by (instance) (windows_cpu_logical_processor{job=~"$job"})) and on (instance) windows_os_hostname{job=~"$job", hostname=~"$hostname"}', 'D')
+ b.query.withInstant()
+ b.query.withFormat('table'),
b.query.new('(100 * (1 - avg by (instance) (clamp_max(rate(windows_cpu_time_total{job=~"$job", mode="idle"}[$__rate_interval]), 1)))) and on (instance) windows_os_hostname{job=~"$job", hostname=~"$hostname"}', 'E')
b.query.new('(100 * (1 - avg by (instance) (clamp_max(rate(windows_cpu_time_seconds_total{job=~"$job", mode="idle"}[$__rate_interval]), 1)))) and on (instance) windows_os_hostname{job=~"$job", hostname=~"$hostname"}', 'E')
+ b.query.withInstant()
+ b.query.withFormat('table'),
b.query.new('(max by (instance) (windows_memory_physical_total_bytes{job=~"$job"})) and on (instance) windows_os_hostname{job=~"$job", hostname=~"$hostname"}', 'F')
@@ -643,7 +643,7 @@ function(on, config, overview=null)
b.panel.new(3, 'CPU utilization', 'timeseries')
+ b.panel.withDescription('Shows the 25 highest hosts at each point in time.')
+ b.panel.withQueries([
b.query.new('topk(25, (100 * (1 - avg by (instance) (clamp_max(rate(windows_cpu_time_total{job=~"$job", mode="idle"}[$__rate_interval]), 1)))) * on (instance) group_left (hostname) max by (instance, hostname) (windows_os_hostname{job=~"$job", hostname=~"$hostname"}))', 'A')
b.query.new('topk(25, (100 * (1 - avg by (instance) (clamp_max(rate(windows_cpu_time_seconds_total{job=~"$job", mode="idle"}[$__rate_interval]), 1)))) * on (instance) group_left (hostname) max by (instance, hostname) (windows_os_hostname{job=~"$job", hostname=~"$hostname"}))', 'A')
+ b.query.withLegendFormat('{{hostname}}'),
])
+ b.panel.withDefaults({
+4 -4
View File
@@ -12,7 +12,7 @@ function(on)
if on('gpu') then b.row('Processes', b.flow([[60, 12, 8], [61, 12, 8], [128, 12, 8], [129, 12, 8], [130, 12, 8], [131, 12, 8]])),
]),
[
b.stat(184, 'Utilization', 'Utilization of the busiest engine on the busiest GPU.', 'max(clamp_max(max by (luid) (sum by (luid, eng, engtype) (rate(' + metric('engine_time_seconds') + '[$__rate_interval]))), 1))', 'percentunit', steps=b.levels(0.8, 0.9))
b.stat(184, 'Utilization', 'Utilization of the busiest engine on the busiest GPU.', 'max(clamp_max(max by (luid) (sum by (luid, eng, engtype) (rate(' + metric('engine_time_seconds_total') + '[$__rate_interval]))), 1))', 'percentunit', steps=b.levels(0.8, 0.9))
+ b.panel.withDefaults({ decimals: 1, max: 1, min: 0 }),
b.stat(185, 'VRAM used', 'Dedicated GPU memory in use, summed over all GPUs.', perGpu('adapter_memory_dedicated_bytes'), 'bytes')
+ b.panel.withDefaults({ decimals: 1 }),
@@ -30,7 +30,7 @@ function(on)
b.query.new('max by (luid, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'A')
+ b.query.withInstant()
+ b.query.withFormat('table'),
b.query.new('clamp_max(max by (luid) (sum by (luid, eng, engtype) (rate(windows_gpu_engine_time_seconds{job=~"$job", instance="$instance"}[$__rate_interval]))), 1)', 'B')
b.query.new('clamp_max(max by (luid) (sum by (luid, eng, engtype) (rate(windows_gpu_engine_time_seconds_total{job=~"$job", instance="$instance"}[$__rate_interval]))), 1)', 'B')
+ b.query.withInstant()
+ b.query.withFormat('table'),
b.query.new('max by (luid) (windows_gpu_adapter_memory_dedicated_bytes{job=~"$job", instance="$instance"})', 'C')
@@ -208,7 +208,7 @@ function(on)
b.panel.new(58, 'GPU utilization by engine type', 'timeseries')
+ b.panel.withDescription('Busiest engine of each engine type, as in Task Manager.')
+ b.panel.withQueries([
b.query.new('clamp_max(max by (luid, engtype) (sum by (luid, eng, engtype) (rate(windows_gpu_engine_time_seconds{job=~"$job", instance="$instance"}[$__rate_interval]))), 1) * on (luid) group_left (name) max by (luid, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'A')
b.query.new('clamp_max(max by (luid, engtype) (sum by (luid, eng, engtype) (rate(windows_gpu_engine_time_seconds_total{job=~"$job", instance="$instance"}[$__rate_interval]))), 1) * on (luid) group_left (name) max by (luid, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'A')
+ b.query.withLegendFormat('{{name}} {{engtype}}'),
])
+ b.panel.withDefaults({
@@ -260,7 +260,7 @@ function(on)
b.panel.new(60, 'Top 10 processes by GPU utilization', 'timeseries')
+ b.panel.withDescription('Busiest GPU engine used by each process. Process names need the process collector; otherwise only the PID is shown.')
+ b.panel.withQueries([
b.query.new('topk(10, (max by (process_id) (sum by (process_id, luid, eng) (rate(windows_gpu_engine_time_seconds{job=~"$job", instance="$instance"}[$__rate_interval]))) * on (process_id) group_left (process) max by (process_id, process) (windows_process_info{job=~"$job", instance="$instance"})) or on (process_id) max by (process_id) (sum by (process_id, luid, eng) (rate(windows_gpu_engine_time_seconds{job=~"$job", instance="$instance"}[$__rate_interval]))))', 'A')
b.query.new('topk(10, (max by (process_id) (sum by (process_id, luid, eng) (rate(windows_gpu_engine_time_seconds_total{job=~"$job", instance="$instance"}[$__rate_interval]))) * on (process_id) group_left (process) max by (process_id, process) (windows_process_info{job=~"$job", instance="$instance"})) or on (process_id) max by (process_id) (sum by (process_id, luid, eng) (rate(windows_gpu_engine_time_seconds_total{job=~"$job", instance="$instance"}[$__rate_interval]))))', 'A')
+ b.query.withLegendFormat('{{process}} ({{process_id}})'),
])
+ b.panel.withDefaults({
+10 -10
View File
@@ -11,9 +11,9 @@ function(on)
if on('hyperv') then b.row('Network', b.flow([[80, 8, 8], [81, 8, 8], [82, 8, 8]])),
]),
[
b.stat(63, 'Virtual machines', 'Needs the hyperv collector, which is not enabled by default.', 'sum(windows_hyperv_virtual_machine_health_total_count{job=~"$job", instance="$instance"})', 'short'),
b.stat(63, 'Virtual machines', 'Needs the hyperv collector, which is not enabled by default.', 'sum(windows_hyperv_virtual_machines{job=~"$job", instance="$instance"})', 'short'),
b.stat(64, 'VMs in critical health', 'Number of Hyper-V virtual machines reporting critical health. Inspect the affected VM and Hyper-V event logs; this requires the optional hyperv collector.', 'sum(windows_hyperv_virtual_machine_health_total_count{job=~"$job", instance="$instance", state="critical"})', steps=[{ color: 'green', value: null }, { color: 'red', value: 1 }]),
b.stat(64, 'VMs in critical health', 'Number of Hyper-V virtual machines reporting critical health. Inspect the affected VM and Hyper-V event logs; this requires the optional hyperv collector.', 'sum(windows_hyperv_virtual_machines{job=~"$job", instance="$instance", state="critical"})', steps=[{ color: 'green', value: null }, { color: 'red', value: 1 }]),
b.panel.new(65, 'Hyper-V WMI', 'stat')
+ b.panel.withDescription('Whether the Hyper-V WMI namespace answers. When it stops answering, Hyper-V Manager and Failover Cluster Manager usually cannot manage the host.')
@@ -52,17 +52,17 @@ function(on)
unit: '',
}),
b.stat(66, 'Logical processors', 'Number of host logical processors reported by Hyper-V. Use this as capacity context for host and virtual processor load; this requires the optional hyperv collector.', 'windows_hyperv_host_logical_processor_count{job=~"$job", instance="$instance"}', 'short'),
b.stat(66, 'Logical processors', 'Number of host logical processors reported by Hyper-V. Use this as capacity context for host and virtual processor load; this requires the optional hyperv collector.', 'windows_hyperv_host_logical_processors{job=~"$job", instance="$instance"}', 'short'),
b.stat(67, 'Virtual processors', 'Virtual processors assigned to all VMs.', 'windows_hyperv_total_vm_processor_count{job=~"$job", instance="$instance"}', 'short'),
b.stat(67, 'Virtual processors', 'Virtual processors assigned to all VMs.', 'windows_hyperv_assigned_vm_processors{job=~"$job", instance="$instance"}', 'short'),
b.stat(68, 'vCPU per logical CPU', 'Virtual processors assigned to VMs per logical processor of the host.', 'windows_hyperv_total_vm_processor_count{job=~"$job", instance="$instance"} / windows_hyperv_host_logical_processor_count{job=~"$job", instance="$instance"}', 'short')
b.stat(68, 'vCPU per logical CPU', 'Virtual processors assigned to VMs per logical processor of the host.', 'windows_hyperv_assigned_vm_processors{job=~"$job", instance="$instance"} / windows_hyperv_host_logical_processors{job=~"$job", instance="$instance"}', 'short')
+ b.panel.withDefaults({ decimals: 2 }),
b.panel.new(69, 'Host CPU time by state', 'timeseries')
+ b.panel.withDescription('Share of all logical processors spent running guest code (VMs and the root partition) and in the hypervisor. With Hyper-V enabled, the CPU tab only sees the root partition.')
+ b.panel.withQueries([
b.query.new('sum by (state) (rate(windows_hyperv_hypervisor_logical_processor_time_total{job=~"$job", instance="$instance", state!="idle"}[$__rate_interval])) / scalar(count(windows_hyperv_hypervisor_logical_processor_time_total{job=~"$job", instance="$instance", state="idle"}))', 'A')
b.query.new('sum by (state) (rate(windows_hyperv_hypervisor_logical_processor_time_seconds_total{job=~"$job", instance="$instance", state!="idle"}[$__rate_interval])) / scalar(count(windows_hyperv_hypervisor_logical_processor_time_seconds_total{job=~"$job", instance="$instance", state="idle"}))', 'A')
+ b.query.withLegendFormat('{{state}}'),
])
+ b.panel.withDefaults({
@@ -79,7 +79,7 @@ function(on)
b.panel.new(70, 'CPU usage per VM', 'timeseries')
+ b.panel.withDescription('Virtual processor run time of each VM as a share of all logical processors of the host.')
+ b.panel.withQueries([
b.query.new('sum by (vm) (rate(windows_hyperv_hypervisor_virtual_processor_run_time_total{job=~"$job", instance="$instance"}[$__rate_interval])) / scalar(max(windows_hyperv_host_logical_processor_count{job=~"$job", instance="$instance"}))', 'A')
b.query.new('sum by (vm) (rate(windows_hyperv_hypervisor_virtual_processor_run_time_seconds_total{job=~"$job", instance="$instance"}[$__rate_interval])) / scalar(max(windows_hyperv_host_logical_processors{job=~"$job", instance="$instance"}))', 'A')
+ b.query.withLegendFormat('{{vm}}'),
])
+ b.panel.withDefaults({
@@ -168,9 +168,9 @@ function(on)
b.panel.new(76, 'Virtual disk throughput', 'timeseries')
+ b.panel.withDescription('Reads are drawn below the axis.')
+ b.panel.withQueries([
b.query.new('rate(windows_hyperv_virtual_storage_device_bytes_written{job=~"$job", instance="$instance"}[$__rate_interval])', 'A')
b.query.new('rate(windows_hyperv_virtual_storage_device_written_bytes_total{job=~"$job", instance="$instance"}[$__rate_interval])', 'A')
+ b.query.withLegendFormat('{{device}} write'),
b.query.new('rate(windows_hyperv_virtual_storage_device_bytes_read{job=~"$job", instance="$instance"}[$__rate_interval])', 'B')
b.query.new('rate(windows_hyperv_virtual_storage_device_read_bytes_total{job=~"$job", instance="$instance"}[$__rate_interval])', 'B')
+ b.query.withLegendFormat('{{device}} read'),
])
+ b.panel.withDefaults({
@@ -222,7 +222,7 @@ function(on)
+ b.panel.withQueries([
b.query.new('rate(windows_hyperv_virtual_storage_device_io_latency_seconds_total{job=~"$job", instance="$instance"}[$__rate_interval]) / rate(windows_hyperv_virtual_storage_device_throughput_total{job=~"$job", instance="$instance"}[$__rate_interval])', 'A')
+ b.query.withLegendFormat('{{device}} latency'),
b.query.new('rate(windows_hyperv_virtual_storage_device_error_count_total{job=~"$job", instance="$instance"}[$__rate_interval]) > 0', 'B')
b.query.new('rate(windows_hyperv_virtual_storage_device_errors_total{job=~"$job", instance="$instance"}[$__rate_interval]) > 0', 'B')
+ b.query.withLegendFormat('{{device}} errors'),
])
+ b.panel.withDefaults({
+34 -34
View File
@@ -38,9 +38,9 @@ function(on)
[
b.stat(256, 'Sub-collector failures', 'mssql sub-collectors that failed at the last scrape for this SQL Server instance. The Exporter tab shows the scrape errors.' + requirement, 'count(' + metric('collector_success') + ' == 0) or (0 * count(' + metric('collector_success') + '))', steps=[{ color: 'green', value: null }, { color: 'red', value: 1 }]),
b.stat(257, 'User connections', 'Users connected to the instance. Each user can have several connections.' + requirement, metric('genstats_user_connections')),
b.stat(258, 'Batch requests', 'Transact-SQL command batches received per second.' + requirement, rate('sqlstats_batch_requests'), 'reqps'),
b.stat(258, 'Batch requests', 'Transact-SQL command batches received per second.' + requirement, rate('sqlstats_batch_requests_total'), 'reqps'),
b.stat(259, 'Blocked processes', 'Processes currently blocked by another process.' + requirement, metric('genstats_blocked_processes'), steps=[{ color: 'green', value: null }, { color: 'orange', value: 1 }]),
b.stat(260, 'Deadlocks', 'Lock requests per minute that resulted in a deadlock, across all lock resource types.' + requirement, '60 * sum(' + rate('locks_deadlocks') + ')', 'opm', steps=b.levels(0.1, 1))
b.stat(260, 'Deadlocks', 'Lock requests per minute that resulted in a deadlock, across all lock resource types.' + requirement, '60 * sum(' + rate('locks_deadlocks_total') + ')', 'opm', steps=b.levels(0.1, 1))
+ b.panel.withDefaults({ decimals: 1 }),
b.stat(261, 'Pending memory grants', 'Processes waiting for a workspace memory grant to run a query. Values above zero mean queries wait for memory.' + requirement, metric('memmgr_pending_memory_grants'), steps=[{ color: 'green', value: null }, { color: 'orange', value: 1 }]),
b.stat(262, 'Page life expectancy', 'Seconds a page stays in the buffer pool without references. A falling value means the buffer pool is under memory pressure.' + requirement, metric('bufman_page_life_expectancy_seconds'), 's'),
@@ -48,27 +48,27 @@ function(on)
+ b.panel.withDefaults({ decimals: 1, max: 1, min: 0 }),
b.graph(264, 'Batch requests and compilations', 'Transact-SQL batches, query compilations and recompilations per second. Many compilations per batch can indicate plans that are not reused.' + requirement, 'ops', [
[rate('sqlstats_batch_requests'), 'batch requests'],
[rate('sqlstats_sql_compilations'), 'compilations'],
[rate('sqlstats_sql_recompilations'), 'recompilations'],
[rate('sqlstats_sql_attentions'), 'attentions'],
[rate('sqlstats_batch_requests_total'), 'batch requests'],
[rate('sqlstats_sql_compilations_total'), 'compilations'],
[rate('sqlstats_sql_recompilations_total'), 'recompilations'],
[rate('sqlstats_sql_attentions_total'), 'attentions'],
]),
b.graph(265, 'Connections', 'Users connected to the instance, and logical connections to it. Each user can have several connections.' + requirement, 'short', [
[metric('genstats_user_connections'), 'users'],
[metric('genstats_logical_connections'), 'logical connections'],
]),
b.graph(266, 'Access methods', 'Index searches, unrestricted full scans and page splits per second. Full scans of large tables and many page splits can indicate missing indexes or a low fill factor.' + requirement, 'ops', [
[rate('accessmethods_index_searches'), 'index searches'],
[rate('accessmethods_full_scans'), 'full scans'],
[rate('accessmethods_page_splits'), 'page splits'],
[rate('accessmethods_index_searches_total'), 'index searches'],
[rate('accessmethods_full_scans_total'), 'full scans'],
[rate('accessmethods_page_splits_total'), 'page splits'],
]),
b.graph(267, 'SQL errors', 'Errors per second by error class.' + requirement, 'ops', [
['sum by (resource) (' + rate('sql_errors_total') + ')', '{{resource}}'],
]),
b.graph(268, 'Logins and logouts', 'Logins, logouts and connection resets from the connection pool per second. Logouts are drawn below the axis.' + requirement, 'ops', [
[rate('genstats_logins'), 'logins'],
[rate('genstats_logouts'), 'logouts'],
[rate('genstats_connection_resets'), 'connection resets'],
[rate('genstats_logins_total'), 'logins'],
[rate('genstats_logouts_total'), 'logouts'],
[rate('genstats_connection_resets_total'), 'connection resets'],
], below='logouts'),
b.graph(269, 'Wait time by wait class', 'Time sessions spent waiting per second, by wait class, over the most recent SQL Server sampling interval. 2 s means two sessions waited the whole second on average.' + requirement, 's', [
@@ -78,14 +78,14 @@ function(on)
+ b.panel.withDefaults({ custom: { fillOpacity: 40, stacking: { mode: 'normal' } } })
+ b.panel.withOptions({ legend: { placement: 'right' } }),
b.graph(270, 'Lock waits', 'Lock requests per second that had to wait, by lock resource type.' + requirement, 'ops', [
['sum by (resource) (' + rate('locks_lock_waits') + ')', '{{resource}}'],
['sum by (resource) (' + rate('locks_lock_waits_total') + ')', '{{resource}}'],
]),
b.graph(271, 'Average lock wait', 'Average wait time of the lock requests that waited, by lock resource type.' + requirement, 's', [
['sum by (resource) (' + rate('locks_wait_time_seconds_total') + ') / (sum by (resource) (' + rate('locks_count_total') + ') > 0)', '{{resource}}'],
['sum by (resource) (' + rate('locks_wait_time_seconds_total') + ') / (sum by (resource) (' + rate('locks_lock_waits_total') + ') > 0)', '{{resource}}'],
]),
b.graph(272, 'Deadlocks and lock timeouts', 'Lock requests per second that resulted in a deadlock or timed out, across all lock resource types. Timeouts exclude NOWAIT requests.' + requirement, 'ops', [
['sum(' + rate('locks_deadlocks') + ')', 'deadlocks'],
['sum(' + rate('locks_lock_timeouts_excluding_NOWAIT') + ')', 'timeouts'],
['sum(' + rate('locks_deadlocks_total') + ')', 'deadlocks'],
['sum(' + rate('locks_lock_timeouts_excluding_nowait_total') + ')', 'timeouts'],
]),
b.graph(273, 'Server memory', 'Memory the memory manager has committed, against the memory it can use. The total stays below the target when SQL Server needs no more memory.' + requirement, 'bytes', [
@@ -117,11 +117,11 @@ function(on)
[metric('bufman_page_life_expectancy_seconds'), 'page life expectancy'],
]),
b.graph(276, 'Buffer pool I/O', 'Bytes per second of all physical page writes and the parts written by checkpoints and the lazy writer, and of all page reads and the part read ahead. Reads are drawn below the axis.' + requirement, 'Bps', [
[pageBytes + ' * ' + rate('bufman_page_writes'), 'writes'],
[pageBytes + ' * ' + rate('bufman_checkpoint_pages'), 'checkpoint writes'],
[pageBytes + ' * ' + rate('bufman_lazywrites'), 'lazy writes'],
[pageBytes + ' * ' + rate('bufman_page_reads'), 'reads'],
[pageBytes + ' * ' + rate('bufman_read_ahead_pages'), 'read-ahead reads'],
[pageBytes + ' * ' + rate('bufman_page_writes_total'), 'writes'],
[pageBytes + ' * ' + rate('bufman_checkpoint_pages_total'), 'checkpoint writes'],
[pageBytes + ' * ' + rate('bufman_lazywrites_total'), 'lazy writes'],
[pageBytes + ' * ' + rate('bufman_page_reads_total'), 'reads'],
[pageBytes + ' * ' + rate('bufman_read_ahead_pages_total'), 'read-ahead reads'],
], below='.*reads'),
b.graph(277, 'Memory grants', 'Processes that received a workspace memory grant, and processes waiting for one.' + requirement, 'short', [
[metric('memmgr_outstanding_memory_grants'), 'granted'],
@@ -131,17 +131,17 @@ function(on)
b.joinedTable(278, 'Databases', 'Size, log usage and activity of each selected database.' + requirement, 'database', [
'max by (database) (' + database('data_files_size_bytes') + ')',
'max by (database) (' + database('log_files_size_bytes') + ')',
'max by (database) (' + database('log_used_percent') + ')',
'max by (database) (' + database('log_used_ratio') + ')',
'max by (database) (' + database('active_transactions') + ')',
'max by (database) (' + databaseRate('transactions') + ')',
'max by (database) (' + databaseRate('write_transactions') + ')',
'max by (database) (' + databaseRate('transactions_total') + ')',
'max by (database) (' + databaseRate('write_transactions_total') + ')',
], [['database', 'Database'], ['Value #A', 'Data size'], ['Value #B', 'Log size'], ['Value #C', 'Log used'], ['Value #D', 'Active transactions'], ['Value #E', 'Transactions/s'], ['Value #F', 'Writes/s']], [
{
matcher: { id: 'byName', options: 'Log used' },
properties: [
{ id: 'unit', value: 'percent' },
{ id: 'unit', value: 'percentunit' },
{ id: 'min', value: 0 },
{ id: 'max', value: 100 },
{ id: 'max', value: 1 },
{ id: 'decimals', value: 1 },
{ id: 'custom.cellOptions', value: { mode: 'basic', type: 'gauge', valueDisplayMode: 'text' } },
],
@@ -152,18 +152,18 @@ function(on)
b.graph(279, 'Data file size', 'Size of the data files of each selected database.' + requirement, 'bytes', [
['max by (database) (' + database('data_files_size_bytes') + ')', '{{database}}'],
]),
b.graph(280, 'Log used', 'Share of the log files of each selected database in use. A log that stays full needs a log backup, a checkpoint or more space.' + requirement, 'percent', [
['max by (database) (' + database('log_used_percent') + ')', '{{database}}'],
b.graph(280, 'Log used', 'Share of the log files of each selected database in use. A log that stays full needs a log backup, a checkpoint or more space.' + requirement, 'percentunit', [
['max by (database) (' + database('log_used_ratio') + ')', '{{database}}'],
])
+ b.panel.withDefaults({ max: 100 }),
+ b.panel.withDefaults({ max: 1 }),
b.graph(281, 'Transactions', 'Transactions started per second in each selected database.' + requirement, 'ops', [
['max by (database) (' + databaseRate('transactions') + ')', '{{database}}'],
['max by (database) (' + databaseRate('transactions_total') + ')', '{{database}}'],
]),
b.graph(282, 'Log flushes', 'Bytes per second written to the transaction log of each selected database.' + requirement, 'Bps', [
['max by (database) (' + databaseRate('log_flushed_bytes') + ')', '{{database}}'],
['max by (database) (' + databaseRate('log_flushed_bytes_total') + ')', '{{database}}'],
]),
b.graph(283, 'Log flush write time', 'Average time to write a log flush to disk in each selected database. Commits wait for this write, so slow log storage slows every write transaction.' + requirement, 's', [
['max by (database) (' + databaseRate('log_flush_write_seconds_total') + ' / (' + databaseRate('log_flushes') + ' > 0))', '{{database}}'],
['max by (database) (' + databaseRate('log_flush_write_seconds_total') + ' / (' + databaseRate('log_flushes_total') + ' > 0))', '{{database}}'],
]),
b.graph(284, 'tempdb space', 'Free space in tempdb and the size of the version store kept in it for snapshot isolation and online index operations.' + requirement, 'bytes', [
@@ -185,8 +185,8 @@ function(on)
['max by (replica) (' + metric('dbreplica_recovery_queue_bytes') + ')', '{{replica}} redo queue'],
]),
b.graph(288, 'Replica traffic', 'Bytes per second sent to and received from each availability replica. Received bytes are drawn below the axis.' + requirement, 'Bps', [
['max by (replica) (' + rate('availreplica_sent_to_replica_bytes') + ')', '{{replica}} sent'],
['max by (replica) (' + rate('availreplica_received_from_replica_bytes') + ')', '{{replica}} received'],
['max by (replica) (' + rate('availreplica_sent_to_replica_bytes_total') + ')', '{{replica}} sent'],
['max by (replica) (' + rate('availreplica_received_from_replica_bytes_total') + ')', '{{replica}} received'],
], below='.* received'),
]
)
+1 -1
View File
@@ -123,7 +123,7 @@ function(on)
b.panel.new(140, 'TCP connections by state', 'timeseries')
+ b.panel.withDescription('Needs the tcp collector, which is not enabled by default. A growing CLOSE_WAIT count means an application does not close its sockets. Many TIME_WAIT connections can use up the dynamic port range for outgoing connections.')
+ b.panel.withQueries([
b.query.new('sum by (state) (windows_tcp_connections_state_count{job=~"$job", instance="$instance"})', 'A')
b.query.new('sum by (state) (windows_tcp_connections{job=~"$job", instance="$instance"})', 'A')
+ b.query.withLegendFormat('{{state}}'),
])
+ b.panel.withDefaults({
+2 -2
View File
@@ -70,7 +70,7 @@ function(on)
b.panel.new(14, 'CPU busy', 'stat')
+ b.panel.withDescription('Percentage of non-idle CPU time averaged across logical processors over the rate interval. Sustained high values together with a growing processor queue can indicate CPU contention.')
+ b.panel.withQueries([
b.query.new('100 * (1 - avg by (instance) (clamp_max(rate(windows_cpu_time_total{job=~"$job", instance="$instance", mode="idle"}[$__rate_interval]), 1)))', 'A'),
b.query.new('100 * (1 - avg by (instance) (clamp_max(rate(windows_cpu_time_seconds_total{job=~"$job", instance="$instance", mode="idle"}[$__rate_interval]), 1)))', 'A'),
])
+ b.panel.withDefaults({
decimals: 1,
@@ -184,7 +184,7 @@ function(on)
b.panel.new(18, 'CPU utilization', 'timeseries')
+ b.panel.withDescription('Percentage of non-idle CPU time averaged across logical processors. This measures CPU time rather than the frequency-adjusted processor utility shown by Windows Task Manager.')
+ b.panel.withQueries([
b.query.new('100 * (1 - avg by (instance) (clamp_max(rate(windows_cpu_time_total{job=~"$job", instance="$instance", mode="idle"}[$__rate_interval]), 1)))', 'A')
b.query.new('100 * (1 - avg by (instance) (clamp_max(rate(windows_cpu_time_seconds_total{job=~"$job", instance="$instance", mode="idle"}[$__rate_interval]), 1)))', 'A')
+ b.query.withLegendFormat('CPU busy'),
])
+ b.panel.withDefaults({
+2 -2
View File
@@ -30,11 +30,11 @@ function(on)
stat(150, 'Processes', 'Number of distinct process IDs currently collected, excluding Idle.', 'count(count by (process_id) (' + gauge('info') + '))', 'short'),
stat(151, 'Threads', 'Total active threads in the selected processes.', 'sum(' + gauge('threads') + ')', 'short'),
stat(152, 'Handles', 'Total open handles in the selected processes.', 'sum(' + gauge('handles') + ')', 'short'),
stat(153, 'CPU busy', 'CPU time used by the selected processes as a share of all logical processors of the host, excluding Idle.', 'sum(' + rate('cpu_time_total') + ') / scalar(max(windows_cpu_logical_processor{job=~"$job", instance="$instance"}))', 'percentunit', steps=b.levels(0.8, 0.9)),
stat(153, 'CPU busy', 'CPU time used by the selected processes as a share of all logical processors of the host, excluding Idle.', 'sum(' + rate('cpu_time_seconds_total') + ') / scalar(max(windows_cpu_logical_processor{job=~"$job", instance="$instance"}))', 'percentunit', steps=b.levels(0.8, 0.9)),
stat(154, 'Private working set', 'Physical memory private to the selected processes; shared pages are excluded.', 'sum(' + gauge('working_set_private_bytes') + ')', 'bytes'),
stat(155, 'Private bytes', 'Total memory allocated by the selected processes that cannot be shared; it may include nonresident memory.', 'sum(' + gauge('private_bytes') + ')', 'bytes'),
graph(112, 'Process CPU usage', 'User and privileged CPU time per process as a share of one logical processor. Values above 100% mean the process uses more than one core.', sumRates('cpu_time_total'), sumRates('cpu_time_total', ' @ end()'), 'percentunit'),
graph(112, 'Process CPU usage', 'User and privileged CPU time per process as a share of one logical processor. Values above 100% mean the process uses more than one core.', sumRates('cpu_time_seconds_total'), sumRates('cpu_time_seconds_total', ' @ end()'), 'percentunit'),
graph(113, 'Process working set', 'Physical memory in the working set of each process, including shared pages.', gauge('working_set_bytes'), gauge('working_set_bytes', ' @ end()'), 'bytes'),
graph(114, 'Process private bytes', 'Memory allocated by each process that cannot be shared with other processes.', gauge('private_bytes'), gauge('private_bytes', ' @ end()'), 'bytes'),
graph(115, 'Process I/O throughput', 'Total bytes issued for read, write and other I/O per process, including file, network and device operations.', sumRates('io_bytes_total'), sumRates('io_bytes_total', ' @ end()'), 'Bps'),
+4 -4
View File
@@ -25,8 +25,8 @@ function(on)
if on('smbclient') then b.row('Client shares', b.flow([[231, 12, 8], [232, 12, 8], [233, 12, 8], [234, 12, 8], [235, 12, 8], [236, 12, 8]])),
]),
[
b.stat(220, 'Open files', 'Files open on the shares of this SMB server.' + serverRequirement, 'sum(' + server('current_open_file_count') + ')'),
b.stat(221, 'Connections', 'Client connections (tree connects) to the shares of this SMB server.' + serverRequirement, 'sum(' + server('tree_connect_count') + ')'),
b.stat(220, 'Open files', 'Files open on the shares of this SMB server.' + serverRequirement, 'sum(' + server('open_files') + ')'),
b.stat(221, 'Connections', 'Client connections (tree connects) to the shares of this SMB server.' + serverRequirement, 'sum(' + server('tree_connects') + ')'),
b.stat(222, 'Server traffic', 'Bytes sent and received per second by the shares of this SMB server.' + serverRequirement, 'sum(' + serverRate('received_bytes_total') + ') + sum(' + serverRate('sent_bytes_total') + ')', 'Bps'),
b.stat(223, 'Client traffic', 'Bytes read and written per second by this host on remote SMB shares.' + clientRequirement, 'sum(' + clientRate('data_bytes_total') + ')', 'Bps'),
b.stat(224, 'Client latency', 'Average time per request of this host on remote SMB shares. 0 when there are no requests.' + clientRequirement, '(sum(' + clientRate('request_seconds_total') + ') / (sum(' + clientRate('requests_total') + ') > 0)) or (0 * sum(' + clientRate('requests_total') + '))', 's', steps=b.levels(0.02, 0.05)),
@@ -41,8 +41,8 @@ function(on)
[serverRate('write_requests_total'), share + ' write'],
[serverRate('metadata_requests_total'), share + ' metadata'],
]),
b.graph(228, 'Open files', 'Files open per share.' + serverRequirement, 'short', [[server('current_open_file_count'), share]]),
b.graph(229, 'Connections', 'Client connections (tree connects) per share.' + serverRequirement, 'short', [[server('tree_connect_count'), share]]),
b.graph(228, 'Open files', 'Files open per share.' + serverRequirement, 'short', [[server('open_files'), share]]),
b.graph(229, 'Connections', 'Client connections (tree connects) per share.' + serverRequirement, 'short', [[server('tree_connects'), share]]),
b.graph(230, 'Files opened', 'Files opened per second per share.' + serverRequirement, 'ops', [[serverRate('files_opened_total'), share]]),
b.graph(231, 'Client traffic', 'Bytes read and written per second per remote share. Reads are drawn below the axis.' + clientRequirement, 'Bps', [
+1 -1
View File
@@ -6,7 +6,7 @@ function(c)
// Drop undefined ratios instead of recording NaN or +Inf for idle devices.
ratio(numerator, denominator): '(%s / (%s > 0))' % [numerator, denominator],
cpuUsage:
'1 - avg without (core, mode) (%s)' % self.rate('windows_cpu_time_total', ['mode="idle"']),
'1 - avg without (core, mode) (%s)' % self.rate('windows_cpu_time_seconds_total', ['mode="idle"']),
memoryUsage:
'1 - %s' % self.ratio(
self.metric('windows_memory_available_bytes'),
+2 -2
View File
@@ -7,8 +7,8 @@
name: 'windows-exporter-recording',
rules: [
{ record: 'windows:cpu_usage:ratio', expr: q.cpuUsage },
{ record: 'windows:cpu_cores:count', expr: 'count without (core, mode) (%s)' % q.metric('windows_cpu_time_total', ['mode="idle"']) },
{ record: 'windows:cpu_time:ratio_rate', expr: 'avg without (core) (%s)' % q.rate('windows_cpu_time_total') },
{ record: 'windows:cpu_cores:count', expr: 'count without (core, mode) (%s)' % q.metric('windows_cpu_time_seconds_total', ['mode="idle"']) },
{ record: 'windows:cpu_time:ratio_rate', expr: 'avg without (core) (%s)' % q.rate('windows_cpu_time_seconds_total') },
{ record: 'windows:memory_usage:ratio', expr: q.memoryUsage },
{
record: 'windows:memory_used:bytes',
+2 -2
View File
@@ -159,7 +159,7 @@ tests:
- name: Resource alerts use recording rules and wait fifteen minutes
interval: 1m
input_series:
- series: 'windows_cpu_time_total{job="windows_exporter", instance="host:9182", cluster="a", core="0", mode="idle"}'
- series: 'windows_cpu_time_seconds_total{job="windows_exporter", instance="host:9182", cluster="a", core="0", mode="idle"}'
values: '0+3x20 120+60x10'
- series: 'windows_memory_available_bytes{job="windows_exporter", instance="host:9182", cluster="a"}'
values: '5x20 50x10'
@@ -226,7 +226,7 @@ tests:
- name: Healthy resources at the exact thresholds do not fire
interval: 1m
input_series:
- series: 'windows_cpu_time_total{job="windows_exporter", instance="host:9182", core="0", mode="idle"}'
- series: 'windows_cpu_time_seconds_total{job="windows_exporter", instance="host:9182", core="0", mode="idle"}'
values: '0+6x20'
- series: 'windows_memory_available_bytes{job="windows_exporter", instance="host:9182"}'
values: '10x20'
+1 -1
View File
@@ -137,7 +137,7 @@ tests:
values: '0x20'
- series: 'up{job="windows-custom", instance="host:9182", cluster="prod"}'
values: '0x20'
- series: 'windows_cpu_time_total{job="windows-custom", instance="host:9182", cluster="test", core="0", mode="idle"}'
- series: 'windows_cpu_time_seconds_total{job="windows-custom", instance="host:9182", cluster="test", core="0", mode="idle"}'
values: '0+9x20'
- series: 'windows_memory_available_bytes{job="windows-custom", instance="host:9182", cluster="test"}'
values: '12x20'
+5 -5
View File
@@ -7,15 +7,15 @@ tests:
- name: CPU is averaged across cores and preserves target labels
interval: 1m
input_series:
- series: 'windows_cpu_time_total{job="windows_exporter", instance="host:9182", cluster="a", core="0", mode="idle"}'
- series: 'windows_cpu_time_seconds_total{job="windows_exporter", instance="host:9182", cluster="a", core="0", mode="idle"}'
values: '0+12x10'
- series: 'windows_cpu_time_total{job="windows_exporter", instance="host:9182", cluster="a", core="1", mode="idle"}'
- series: 'windows_cpu_time_seconds_total{job="windows_exporter", instance="host:9182", cluster="a", core="1", mode="idle"}'
values: '0+36x10'
- series: 'windows_cpu_time_total{job="windows_exporter", instance="host:9182", cluster="a", core="0", mode="user"}'
- series: 'windows_cpu_time_seconds_total{job="windows_exporter", instance="host:9182", cluster="a", core="0", mode="user"}'
values: '0+48x10'
- series: 'windows_cpu_time_total{job="windows_exporter", instance="host:9182", cluster="b", core="0", mode="idle"}'
- series: 'windows_cpu_time_seconds_total{job="windows_exporter", instance="host:9182", cluster="b", core="0", mode="idle"}'
values: '0+30x10'
- series: 'windows_cpu_time_total{job="other", instance="host:9182", core="0", mode="idle"}'
- series: 'windows_cpu_time_seconds_total{job="other", instance="host:9182", core="0", mode="idle"}'
values: '0+6x10'
promql_expr_test:
- expr: windows:cpu_cores:count