diff --git a/contrib/mixin/.dashboard-lint.yaml b/contrib/mixin/.dashboard-lint.yaml index 3b809ed8..d2647962 100644 --- a/contrib/mixin/.dashboard-lint.yaml +++ b/contrib/mixin/.dashboard-lint.yaml @@ -21,48 +21,3 @@ exclusions: entries: - dashboard: Windows Exporter panel: Automatic services not running - panel-title-description-rule: - reason: These existing panels have titles but no descriptions; new panels must include both. - entries: - - dashboard: Windows Exporter - panel: Operating system - - dashboard: Windows Exporter - panel: CPUs - - dashboard: Windows Exporter - panel: RAM - - dashboard: Windows Exporter - panel: CPU busy - - dashboard: Windows Exporter - panel: Memory used - - dashboard: Windows Exporter - panel: CPU utilization - - dashboard: Windows Exporter - panel: Volumes - - dashboard: Windows Exporter - panel: Context switches and interrupts - - dashboard: Windows Exporter - panel: Processes and threads - - dashboard: Windows Exporter - panel: System calls and exceptions - - dashboard: Windows Exporter - panel: Volume usage - - dashboard: Windows Exporter - panel: Network errors and discards - - dashboard: Windows Exporter - panel: Running services - - dashboard: Windows Exporter - panel: Disabled services - - dashboard: Windows Exporter - panel: VMs in critical health - - dashboard: Windows Exporter - panel: Logical processors - - dashboard: Windows Exporter - panel: Virtual switch dropped packets - - dashboard: Windows Exporter - panel: Clock sync source - - dashboard: Windows Exporter - panel: Clock offset and NTP round-trip delay - - dashboard: Windows Exporter - panel: Samples per scrape - - dashboard: Windows Exporter - panel: Collectors diff --git a/contrib/mixin/README.md b/contrib/mixin/README.md index 4430b807..27b29fe4 100644 --- a/contrib/mixin/README.md +++ b/contrib/mixin/README.md @@ -285,9 +285,9 @@ used locally. Run `mise run lint-dashboards` to lint just the committed dashboard. `.dashboard-lint.yaml` documents exceptions for the sample dashboard's single-host selection, fleet -queries, editable state, and existing panels without descriptions or numeric -units. Other findings fail validation, including warnings. Remove panel -exceptions when adding the missing descriptions. +queries, editable state, and the service table without numeric units. All panels +include descriptions; missing titles or descriptions fail validation, including +warnings. `.pint.hcl` requires a non-empty severity label, summary/description annotations, and an HTTP(S) runbook URL on alerts, in addition to pint's built-in checks. diff --git a/contrib/mixin/dashboards/cpu.libsonnet b/contrib/mixin/dashboards/cpu.libsonnet index cc3a14af..5e801888 100644 --- a/contrib/mixin/dashboards/cpu.libsonnet +++ b/contrib/mixin/dashboards/cpu.libsonnet @@ -68,6 +68,7 @@ b.tab( }), b.panel.new(27, 'Context switches and interrupts', 'timeseries') + + b.panel.withDescription('Context switches, hardware interrupts and deferred procedure calls per second across the host. High rates can reflect scheduling or driver activity; correlate changes with CPU usage and workload rather than assuming they are faults.') + b.panel.withQueries([ b.query.new('rate(windows_system_context_switches_total{job=~"$job", instance="$instance"}[$__rate_interval])', 'A') + b.query.withLegendFormat('context switches'), @@ -82,6 +83,7 @@ b.tab( }), b.panel.new(28, 'Processes and threads', 'timeseries') + + b.panel.withDescription('Current process and thread counts on the host. Sustained growth can help identify runaway process creation or thread leaks; thread counts use the right-hand axis.') + b.panel.withQueries([ b.query.new('windows_system_processes{job=~"$job", instance="$instance"}', 'A') + b.query.withLegendFormat('processes'), @@ -108,6 +110,7 @@ b.tab( ]), b.panel.new(29, 'System calls and exceptions', 'timeseries') + + b.panel.withDescription('System calls and exception dispatches per second. Exception dispatches include handled exceptions and do not directly count application crashes; compare with application logs. Exceptions use the right-hand axis.') + b.panel.withQueries([ b.query.new('rate(windows_system_system_calls_total{job=~"$job", instance="$instance"}[$__rate_interval])', 'A') + b.query.withLegendFormat('system calls'), diff --git a/contrib/mixin/dashboards/disk.libsonnet b/contrib/mixin/dashboards/disk.libsonnet index 2fe8f525..417da5df 100644 --- a/contrib/mixin/dashboards/disk.libsonnet +++ b/contrib/mixin/dashboards/disk.libsonnet @@ -13,6 +13,7 @@ b.tab( ]), [ b.panel.new(37, 'Volumes', 'table') + + b.panel.withDescription('Size, available space and used percentage of each selected logical volume. Windows free-space counters can lag by 10 to 15 minutes; use trends rather than treating a single sample as immediate confirmation of reclaimed space.') + b.panel.withQueries([ b.query.new('windows_logical_disk_size_bytes{job=~"$job", instance="$instance", volume=~"$volume"}', 'A') + b.query.withInstant() @@ -161,6 +162,7 @@ b.tab( ]), b.panel.new(38, 'Volume usage', 'timeseries') + + b.panel.withDescription('Used space as a percentage of each selected logical volume. Sustained growth toward full capacity can prevent writes and disrupt applications; Windows free-space counters can lag by 10 to 15 minutes.') + b.panel.withQueries([ b.query.new('100 * (1 - windows_logical_disk_free_bytes{job=~"$job", instance="$instance", volume=~"$volume"} / windows_logical_disk_size_bytes{job=~"$job", instance="$instance", volume=~"$volume"})', 'A') + b.query.withLegendFormat('{{volume}}'), diff --git a/contrib/mixin/dashboards/exporter.libsonnet b/contrib/mixin/dashboards/exporter.libsonnet index bc64859e..e664749e 100644 --- a/contrib/mixin/dashboards/exporter.libsonnet +++ b/contrib/mixin/dashboards/exporter.libsonnet @@ -159,6 +159,7 @@ b.tab( }), b.panel.new(95, 'Samples per scrape', 'stat') + + b.panel.withDescription('Number of metric samples returned before Prometheus metric relabeling. Changes can reflect collector configuration or changing device/process counts; unexpected drops should be checked against scrape and collector success.') + b.panel.withQueries([ b.query.new('scrape_samples_scraped{job=~"$job", instance="$instance"}', 'A'), ]) @@ -213,6 +214,7 @@ b.tab( ]), b.panel.new(99, 'Collectors', 'table') + + b.panel.withDescription('Latest success, timeout and duration for each enabled collector. Success is 1 for a completed collection and 0 for a failure; timeout is 1 when the scrape budget was exceeded. Disabled collectors are absent.') + b.panel.withQueries([ b.query.new('windows_exporter_collector_success{job=~"$job", instance="$instance"}', 'A') + b.query.withInstant() diff --git a/contrib/mixin/dashboards/gpu.libsonnet b/contrib/mixin/dashboards/gpu.libsonnet index a89ed8aa..ec9d5ef6 100644 --- a/contrib/mixin/dashboards/gpu.libsonnet +++ b/contrib/mixin/dashboards/gpu.libsonnet @@ -8,6 +8,18 @@ b.tab( b.place(59, 12, 5, 12, 8), b.place(60, 0, 13, 12, 8), b.place(61, 12, 13, 12, 8), + b.place(120, 0, 21, 12, 8), + b.place(121, 12, 21, 12, 8), + b.place(122, 0, 29, 12, 8), + b.place(123, 12, 29, 12, 8), + b.place(124, 0, 37, 12, 8), + b.place(125, 12, 37, 12, 8), + b.place(126, 0, 45, 12, 8), + b.place(127, 12, 45, 12, 8), + b.place(128, 0, 53, 12, 8), + b.place(129, 12, 53, 12, 8), + b.place(130, 0, 61, 12, 8), + b.place(131, 12, 61, 12, 8), ]), [ b.panel.new(57, 'GPUs', 'table') @@ -275,5 +287,113 @@ b.tab( sortDesc: true, }, }), + + b.panel.new(120, 'GPU temperature', 'timeseries') + + b.panel.withDescription('Current GPU temperature, driver-reported throttling threshold and maximum temperature in degrees Celsius. Sustained readings near the warning threshold can indicate insufficient cooling. Requires the gpu collector, WDDM 2.4 or newer and driver support. Unsupported sensor values are absent, rather than zero.') + + b.panel.withQueries([ + b.query.new('max by (luid, phys) (windows_gpu_temperature_celsius{job=~"$job", instance="$instance"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'A') + + b.query.withLegendFormat('{{name}} GPU {{phys}} temperature'), + b.query.new('max by (luid, phys) (windows_gpu_temperature_warning_celsius{job=~"$job", instance="$instance"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'B') + + b.query.withLegendFormat('{{name}} GPU {{phys}} throttling threshold'), + b.query.new('max by (luid, phys) (windows_gpu_temperature_max_celsius{job=~"$job", instance="$instance"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'C') + + b.query.withLegendFormat('{{name}} GPU {{phys}} maximum'), + ]) + + b.panel.withDefaults({ min: 0, unit: 'celsius' }), + + b.panel.new(121, 'GPU fan speed', 'timeseries') + + b.panel.withDescription('Current and maximum main-fan speed in revolutions per minute. A supported fan can report zero when stopped under light load. Requires the gpu collector, WDDM 2.4 or newer and driver support. Unsupported sensor values are absent, rather than zero.') + + b.panel.withQueries([ + b.query.new('max by (luid, phys) (windows_gpu_fan_speed_rpm{job=~"$job", instance="$instance"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'A') + + b.query.withLegendFormat('{{name}} GPU {{phys}} fan'), + b.query.new('max by (luid, phys) (windows_gpu_fan_speed_max_rpm{job=~"$job", instance="$instance"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'B') + + b.query.withLegendFormat('{{name}} GPU {{phys}} maximum'), + ]) + + b.panel.withDefaults({ min: 0, unit: 'rotrpm' }), + + b.panel.new(122, 'GPU power usage', 'timeseries') + + b.panel.withDescription('Current GPU power draw as a fraction of the driver-reported maximum power (TDP). This is a ratio, not an absolute measurement in watts. Requires the gpu collector, WDDM 2.4 or newer and driver support. Unsupported sensor values are absent, rather than zero.') + + b.panel.withQueries([ + b.query.new('max by (luid, phys) (windows_gpu_power_usage_ratio{job=~"$job", instance="$instance"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'A') + + b.query.withLegendFormat('{{name}} GPU {{phys}} power'), + ]) + + b.panel.withDefaults({ min: 0, unit: 'percentunit' }), + + b.panel.new(123, 'GPU memory clock', 'timeseries') + + b.panel.withDescription('Current and maximum non-overclocked GPU memory clock in hertz. Clocks can fall at idle; correlate drops under load with temperature and power. Requires the gpu collector, WDDM 2.4 or newer and driver support. Unsupported sensor values are absent, rather than zero.') + + b.panel.withQueries([ + b.query.new('max by (luid, phys) (windows_gpu_memory_frequency_hertz{job=~"$job", instance="$instance"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'A') + + b.query.withLegendFormat('{{name}} GPU {{phys}} memory clock'), + b.query.new('max by (luid, phys) (windows_gpu_memory_frequency_max_hertz{job=~"$job", instance="$instance"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'B') + + b.query.withLegendFormat('{{name}} GPU {{phys}} maximum'), + ]) + + b.panel.withDefaults({ min: 0, unit: 'hertz' }), + + b.panel.new(124, 'GPU engine clock', 'timeseries') + + b.panel.withDescription('Current and maximum non-overclocked frequency per GPU engine in hertz. Only engines with a reported maximum clock are exposed, typically the 3D engine. Requires the gpu collector, WDDM 2.4 or newer and driver support. Unsupported sensor values are absent, rather than zero.') + + b.panel.withQueries([ + b.query.new('max by (luid, phys, eng) (windows_gpu_engine_frequency_hertz{job=~"$job", instance="$instance"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'A') + + b.query.withLegendFormat('{{name}} GPU {{phys}} engine {{eng}} clock'), + b.query.new('max by (luid, phys, eng) (windows_gpu_engine_frequency_max_hertz{job=~"$job", instance="$instance"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'B') + + b.query.withLegendFormat('{{name}} GPU {{phys}} engine {{eng}} maximum'), + ]) + + b.panel.withDefaults({ min: 0, unit: 'hertz' }), + + b.panel.new(125, 'GPU committed memory', 'timeseries') + + b.panel.withDescription('Total committed GPU memory per physical GPU in bytes. Commitment is a separate accounting measure from dedicated or shared memory residency; do not add these series together.') + + b.panel.withQueries([ + b.query.new('max by (luid, phys) (windows_gpu_adapter_memory_committed_bytes{job=~"$job", instance="$instance"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'A') + + b.query.withLegendFormat('{{name}} GPU {{phys}} committed'), + ]) + + b.panel.withDefaults({ min: 0, unit: 'bytes' }), + + b.panel.new(126, 'GPU local and non-local memory', 'timeseries') + + b.panel.withDescription('Local and non-local adapter memory usage in bytes, summed across memory partitions for each physical GPU. These describe memory locality and overlap the dedicated/shared accounting views.') + + b.panel.withQueries([ + b.query.new('sum by (luid, phys) (windows_gpu_local_adapter_memory_bytes{job=~"$job", instance="$instance"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'A') + + b.query.withLegendFormat('{{name}} GPU {{phys}} local'), + b.query.new('sum by (luid, phys) (windows_gpu_non_local_adapter_memory_bytes{job=~"$job", instance="$instance"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'B') + + b.query.withLegendFormat('{{name}} GPU {{phys}} non-local'), + ]) + + b.panel.withDefaults({ min: 0, unit: 'bytes' }), + + b.panel.new(127, 'GPU dedicated system memory capacity', 'timeseries') + + b.panel.withDescription('System memory dedicated to each GPU in bytes. This capacity is distinct from dedicated video memory and the shared system memory pool; it can be zero on discrete adapters.') + + b.panel.withQueries([ + b.query.new('max by (luid) (windows_gpu_dedicated_system_memory_size_bytes{job=~"$job", instance="$instance"}) * on (luid) group_left (name) max by (luid, name) (windows_gpu_info{job=~"$job", instance="$instance"})', 'A') + + b.query.withLegendFormat('{{name}} dedicated system capacity'), + ]) + + b.panel.withDefaults({ min: 0, unit: 'bytes' }), + + b.panel.new(128, 'Top 10 processes by shared GPU memory', 'timeseries') + + b.panel.withDescription('Top ten processes at each point in time by shared GPU memory in bytes, summed across GPUs. Membership can change over time. Process names require the process collector; otherwise the PID is shown. Memory accounting views overlap and should not be added together.') + + b.panel.withQueries([ + b.query.new('topk(10, (sum by (process_id) (windows_gpu_process_memory_shared_bytes{job=~"$job", instance="$instance"}) * on (process_id) group_left (process) max by (process_id, process) (windows_process_info{job=~"$job", instance="$instance"})) or on (process_id) sum by (process_id) (windows_gpu_process_memory_shared_bytes{job=~"$job", instance="$instance"}))', 'A') + + b.query.withLegendFormat('{{process}} ({{process_id}})'), + ]) + + b.panel.withDefaults({ min: 0, unit: 'bytes' }), + + b.panel.new(129, 'Top 10 processes by committed GPU memory', 'timeseries') + + b.panel.withDescription('Top ten processes at each point in time by committed GPU memory in bytes, summed across GPUs. Membership can change over time. Process names require the process collector; otherwise the PID is shown. Memory accounting views overlap and should not be added together.') + + b.panel.withQueries([ + b.query.new('topk(10, (sum by (process_id) (windows_gpu_process_memory_committed_bytes{job=~"$job", instance="$instance"}) * on (process_id) group_left (process) max by (process_id, process) (windows_process_info{job=~"$job", instance="$instance"})) or on (process_id) sum by (process_id) (windows_gpu_process_memory_committed_bytes{job=~"$job", instance="$instance"}))', 'A') + + b.query.withLegendFormat('{{process}} ({{process_id}})'), + ]) + + b.panel.withDefaults({ min: 0, unit: 'bytes' }), + + b.panel.new(130, 'Top 10 processes by local GPU memory', 'timeseries') + + b.panel.withDescription('Top ten processes at each point in time by local GPU memory in bytes, summed across GPUs. Membership can change over time. Process names require the process collector; otherwise the PID is shown. Memory accounting views overlap and should not be added together.') + + b.panel.withQueries([ + b.query.new('topk(10, (sum by (process_id) (windows_gpu_process_memory_local_bytes{job=~"$job", instance="$instance"}) * on (process_id) group_left (process) max by (process_id, process) (windows_process_info{job=~"$job", instance="$instance"})) or on (process_id) sum by (process_id) (windows_gpu_process_memory_local_bytes{job=~"$job", instance="$instance"}))', 'A') + + b.query.withLegendFormat('{{process}} ({{process_id}})'), + ]) + + b.panel.withDefaults({ min: 0, unit: 'bytes' }), + + b.panel.new(131, 'Top 10 processes by non-local GPU memory', 'timeseries') + + b.panel.withDescription('Top ten processes at each point in time by non-local GPU memory in bytes, summed across GPUs. Membership can change over time. Process names require the process collector; otherwise the PID is shown. Memory accounting views overlap and should not be added together.') + + b.panel.withQueries([ + b.query.new('topk(10, (sum by (process_id) (windows_gpu_process_memory_non_local_bytes{job=~"$job", instance="$instance"}) * on (process_id) group_left (process) max by (process_id, process) (windows_process_info{job=~"$job", instance="$instance"})) or on (process_id) sum by (process_id) (windows_gpu_process_memory_non_local_bytes{job=~"$job", instance="$instance"}))', 'A') + + b.query.withLegendFormat('{{process}} ({{process_id}})'), + ]) + + b.panel.withDefaults({ min: 0, unit: 'bytes' }), ] ) diff --git a/contrib/mixin/dashboards/hyper_v.libsonnet b/contrib/mixin/dashboards/hyper_v.libsonnet index 6f439f34..6dc4e71c 100644 --- a/contrib/mixin/dashboards/hyper_v.libsonnet +++ b/contrib/mixin/dashboards/hyper_v.libsonnet @@ -38,6 +38,7 @@ b.tab( ]), b.panel.new(64, 'VMs in critical health', 'stat') + + b.panel.withDescription('Number of Hyper-V virtual machines reporting critical health. Inspect the affected VM and Hyper-V event logs; this requires the optional hyperv collector.') + b.panel.withQueries([ b.query.new('sum(windows_hyperv_virtual_machine_health_total_count{job=~"$job", instance="$instance", state="critical"})', 'A') + b.query.withInstant(), @@ -95,6 +96,7 @@ b.tab( }), b.panel.new(66, 'Logical processors', 'stat') + + b.panel.withDescription('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.') + b.panel.withQueries([ b.query.new('windows_hyperv_host_logical_processor_count{job=~"$job", instance="$instance"}', 'A') + b.query.withInstant(), @@ -340,6 +342,7 @@ b.tab( ]), b.panel.new(81, 'Virtual switch dropped packets', 'timeseries') + + b.panel.withDescription('Incoming and outgoing packets dropped per second by each Hyper-V virtual switch. Correlate sustained drops with network load, resource pressure and switch policies; this requires the optional hyperv collector.') + b.panel.withQueries([ b.query.new('rate(windows_hyperv_vswitch_dropped_packets_incoming_total{job=~"$job", instance="$instance"}[$__rate_interval])', 'A') + b.query.withLegendFormat('{{vswitch}} incoming'), diff --git a/contrib/mixin/dashboards/network.libsonnet b/contrib/mixin/dashboards/network.libsonnet index 9ce5357b..5e8df8a7 100644 --- a/contrib/mixin/dashboards/network.libsonnet +++ b/contrib/mixin/dashboards/network.libsonnet @@ -2,11 +2,10 @@ local b = import 'builders.libsonnet'; b.tab( 'Network', - b.grid([ - b.place(45, 0, 0, 12, 8), - b.place(46, 12, 0, 12, 8), - b.place(47, 0, 8, 12, 8), - b.place(48, 12, 8, 12, 8), + b.rows([ + b.row('Interfaces', b.grid([b.place(45, 0, 0, 12, 8), b.place(46, 12, 0, 12, 8), b.place(47, 0, 8, 12, 8), b.place(48, 12, 8, 12, 8)])), + b.row('TCP', b.grid([b.place(140, 0, 0, 12, 8), b.place(141, 12, 0, 12, 8), b.place(142, 0, 8, 12, 8), b.place(143, 12, 8, 12, 8)])), + b.row('UDP', b.grid([b.place(144, 0, 0, 12, 8), b.place(145, 12, 0, 12, 8)])), ]), [ b.panel.new(45, 'Network throughput', 'timeseries') @@ -88,6 +87,7 @@ b.tab( ]), b.panel.new(48, 'Network errors and discards', 'timeseries') + + b.panel.withDescription('Receive and transmit packet errors, discarded packets and received packets with unknown protocols per second for each selected interface. Errors can indicate link or driver problems; discards can reflect buffer pressure or filtering.') + b.panel.withQueries([ b.query.new('rate(windows_net_packets_received_errors_total{job=~"$job", instance="$instance", nic=~"$nic"}[$__rate_interval])', 'A') + b.query.withLegendFormat('{{nic}} received errors'), @@ -104,5 +104,115 @@ b.tab( min: 0, unit: 'pps', }), + + 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.withLegendFormat('{{state}}'), + ]) + + b.panel.withDefaults({ + min: 0, + unit: 'short', + }) + + b.panel.withOverrides([]), + + b.panel.new(141, 'TCP connections opened, failed and reset', 'timeseries') + + b.panel.withDescription('Outgoing (active) and incoming (passive) connections opened per second, connection attempts that failed, and established connections that were reset.') + + b.panel.withQueries([ + b.query.new('sum(rate(windows_tcp_connections_active_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'A') + + b.query.withLegendFormat('opened outgoing'), + b.query.new('sum(rate(windows_tcp_connections_passive_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'B') + + b.query.withLegendFormat('accepted incoming'), + b.query.new('sum(rate(windows_tcp_connection_failures_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'C') + + b.query.withLegendFormat('failed'), + b.query.new('sum(rate(windows_tcp_connections_reset_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'D') + + b.query.withLegendFormat('reset'), + ]) + + b.panel.withDefaults({ + min: 0, + unit: 'ops', + }) + + b.panel.withOverrides([{ matcher: { id: 'byName', options: 'failed' }, properties: [{ id: 'color', value: { fixedColor: 'red', mode: 'fixed' } }] }, { matcher: { id: 'byName', options: 'reset' }, properties: [{ id: 'color', value: { fixedColor: 'orange', mode: 'fixed' } }] }]), + + b.panel.new(142, 'TCP segments', 'timeseries') + + b.panel.withDescription('Received segments are drawn below the axis.') + + b.panel.withQueries([ + b.query.new('sum(rate(windows_tcp_segments_sent_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'A') + + b.query.withLegendFormat('sent'), + b.query.new('sum(rate(windows_tcp_segments_received_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'B') + + b.query.withLegendFormat('received'), + b.query.new('sum(rate(windows_tcp_segments_retransmitted_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'C') + + b.query.withLegendFormat('retransmitted'), + ]) + + b.panel.withDefaults({ + unit: 'pps', + }) + + b.panel.withOverrides([{ matcher: { id: 'byRegexp', options: 'received' }, properties: [{ id: 'custom.transform', value: 'negative-Y' }] }, { matcher: { id: 'byName', options: 'retransmitted' }, properties: [{ id: 'color', value: { fixedColor: 'red', mode: 'fixed' } }] }]), + + b.panel.new(143, 'TCP retransmission rate', 'timeseries') + + b.panel.withDescription('Retransmitted segments as a share of sent segments. A rate that stays above a few percent points to packet loss on the network.') + + b.panel.withQueries([ + b.query.new('sum(rate(windows_tcp_segments_retransmitted_total{job=~"$job", instance="$instance"}[$__rate_interval])) / sum(rate(windows_tcp_segments_sent_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'A') + + b.query.withLegendFormat('retransmitted'), + ]) + + b.panel.withDefaults({ + custom: { + thresholdsStyle: { + mode: 'dashed', + }, + }, + min: 0, + thresholds: { + steps: [ + { + color: 'green', + value: null, + }, + { + color: 'orange', + value: 0.01, + }, + { + color: 'red', + value: 0.05, + }, + ], + }, + }) + + b.panel.withOptions({ + legend: { + calcs: [], + displayMode: 'list', + }, + }) + + b.panel.withOverrides([]), + + b.panel.new(144, 'UDP datagrams', 'timeseries') + + b.panel.withDescription('Needs the udp collector, which is not enabled by default. Received datagrams are drawn below the axis.') + + b.panel.withQueries([ + b.query.new('sum(rate(windows_udp_datagram_sent_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'A') + + b.query.withLegendFormat('sent'), + b.query.new('sum(rate(windows_udp_datagram_received_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'B') + + b.query.withLegendFormat('received'), + ]) + + b.panel.withDefaults({ + unit: 'pps', + }) + + b.panel.withOverrides([{ matcher: { id: 'byRegexp', options: 'received' }, properties: [{ id: 'custom.transform', value: 'negative-Y' }] }]), + + b.panel.new(145, 'UDP errors', 'timeseries') + + b.panel.withDescription('Received datagrams that could not be delivered, and datagrams for a port that no application listens on.') + + b.panel.withQueries([ + b.query.new('sum(rate(windows_udp_datagram_received_errors_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'A') + + b.query.withLegendFormat('received errors'), + b.query.new('sum(rate(windows_udp_datagram_no_port_total{job=~"$job", instance="$instance"}[$__rate_interval]))', 'B') + + b.query.withLegendFormat('no listening port'), + ]) + + b.panel.withDefaults({ + min: 0, + unit: 'pps', + }) + + b.panel.withOverrides([{ matcher: { id: 'byName', options: 'received errors' }, properties: [{ id: 'color', value: { fixedColor: 'red', mode: 'fixed' } }] }]), ] ) diff --git a/contrib/mixin/dashboards/overview.libsonnet b/contrib/mixin/dashboards/overview.libsonnet index ac93ac48..c339921c 100644 --- a/contrib/mixin/dashboards/overview.libsonnet +++ b/contrib/mixin/dashboards/overview.libsonnet @@ -19,6 +19,7 @@ b.tab( ]), [ b.panel.new(10, 'Operating system', 'stat') + + b.panel.withDescription('Windows product name and version reported by the os collector. Use this to distinguish hosts when investigating version-specific behavior.') + b.panel.withQueries([ b.query.new('windows_os_info{job=~"$job", instance="$instance"}', 'A') + b.query.withInstant() @@ -58,12 +59,14 @@ b.tab( }), b.panel.new(12, 'CPUs', 'stat') + + b.panel.withDescription('Number of logical processors available to Windows, including SMT threads. This is the logical CPU count rather than the number of physical sockets.') + b.panel.withQueries([ b.query.new('windows_cpu_logical_processor{job=~"$job", instance="$instance"}', 'A') + b.query.withInstant(), ]), b.panel.new(13, 'RAM', 'stat') + + b.panel.withDescription('Total physical memory visible to Windows in bytes. Compare with used memory and commit charge when investigating memory pressure.') + b.panel.withQueries([ b.query.new('windows_memory_physical_total_bytes{job=~"$job", instance="$instance"}', 'A') + b.query.withInstant(), @@ -74,6 +77,7 @@ b.tab( }), 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'), ]) @@ -104,6 +108,7 @@ b.tab( }), b.panel.new(15, 'Memory used', 'stat') + + b.panel.withDescription('Percentage of physical memory in use, calculated as total minus available memory. This differs from commit charge, which measures promised virtual memory against the commit limit.') + b.panel.withQueries([ b.query.new('100 * (1 - windows_memory_physical_free_bytes{job=~"$job", instance="$instance"} / windows_memory_physical_total_bytes{job=~"$job", instance="$instance"})', 'A'), ]) @@ -186,6 +191,7 @@ b.tab( }), 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.withLegendFormat('CPU busy'), @@ -276,6 +282,7 @@ b.tab( ]), b.panel.new(20, 'Volumes', 'table') + + b.panel.withDescription('Size, available space and used percentage of each selected logical volume. Windows free-space counters can lag by 10 to 15 minutes; use trends rather than treating a single sample as immediate confirmation of reclaimed space.') + b.panel.withQueries([ b.query.new('windows_logical_disk_size_bytes{job=~"$job", instance="$instance", volume=~"$volume"}', 'A') + b.query.withInstant() diff --git a/contrib/mixin/dashboards/services.libsonnet b/contrib/mixin/dashboards/services.libsonnet index ebd28195..7e2142a1 100644 --- a/contrib/mixin/dashboards/services.libsonnet +++ b/contrib/mixin/dashboards/services.libsonnet @@ -12,6 +12,7 @@ b.tab( ]), [ b.panel.new(50, 'Running services', 'stat') + + b.panel.withDescription('Number of services currently in the running state, reported by the service collector. Compare unexpected drops with the stopped automatic services table and service change history.') + b.panel.withQueries([ b.query.new('sum(windows_service_state{job=~"$job", instance="$instance", state="running"})', 'A') + b.query.withInstant(), @@ -60,6 +61,7 @@ b.tab( }), b.panel.new(53, 'Disabled services', 'stat') + + b.panel.withDescription('Number of services configured with disabled startup. A disabled service cannot start until its startup mode changes; disabled services are not necessarily unhealthy.') + b.panel.withQueries([ b.query.new('sum(windows_service_start_mode{job=~"$job", instance="$instance", start_mode="disabled"})', 'A') + b.query.withInstant(), diff --git a/contrib/mixin/dashboards/time.libsonnet b/contrib/mixin/dashboards/time.libsonnet index d8291090..459ceeec 100644 --- a/contrib/mixin/dashboards/time.libsonnet +++ b/contrib/mixin/dashboards/time.libsonnet @@ -29,6 +29,7 @@ b.tab( }), b.panel.new(85, 'Clock sync source', 'stat') + + b.panel.withDescription('Active Windows Time synchronization provider. A non-NTP provider can be expected on virtual machines; this requires the optional time collector.') + b.panel.withQueries([ b.query.new('windows_time_clock_sync_source{job=~"$job", instance="$instance"} == 1', 'A') + b.query.withInstant() @@ -95,6 +96,7 @@ b.tab( }), b.panel.new(88, 'Clock offset and NTP round-trip delay', 'timeseries') + + b.panel.withDescription('Signed offset from the selected time source and the NTP request round-trip delay, in seconds. Persistent offset or increased delay can affect time-sensitive applications; this compares the host to its chosen source and does not independently verify that source.') + b.panel.withQueries([ b.query.new('windows_time_computed_time_offset_seconds{job=~"$job", instance="$instance"}', 'A') + b.query.withLegendFormat('clock offset'), diff --git a/contrib/mixin/dashboards/windows-exporter.libsonnet b/contrib/mixin/dashboards/windows-exporter.libsonnet index 498e7c3e..79c40fa2 100644 --- a/contrib/mixin/dashboards/windows-exporter.libsonnet +++ b/contrib/mixin/dashboards/windows-exporter.libsonnet @@ -14,6 +14,9 @@ local tabs = [ import 'exporter.libsonnet', ]; +local panelNames = std.flattenArrays([std.objectFields(tab.elements) for tab in tabs]); +assert std.length(panelNames) == std.length(std.set(panelNames)) : 'Panel IDs must be unique across tabs'; + dashboard.new('Kdaassddw', 'Windows Exporter') + dashboard.spec.withCursorSync('Crosshair') + dashboard.spec.withDescription('Fleet overview and per-host details for Windows hosts monitored by windows_exporter.') diff --git a/dashboard/README.md b/dashboard/README.md index ef076f19..4ec8aa14 100644 --- a/dashboard/README.md +++ b/dashboard/README.md @@ -8,8 +8,9 @@ and takes several ideas from Grafana's [windows-observ-lib](https://github.com/g - Grafana 13 or later with a Prometheus data source. The file uses the v2 dashboard schema, which Grafana needs for tabs. - windows_exporter with the default collectors (`cpu`, `logical_disk`, `memory`, `net`, `os`, `physical_disk`, `service`, `system`). - The GPU, Hyper-V and Time tabs need the `gpu`, `hyperv` and `time` collectors, which are not enabled by default. + The GPU, Hyper-V and Time tabs and the TCP and UDP rows of the Network tab need the `gpu`, `hyperv`, `time`, `tcp` and `udp` collectors, which are not enabled by default. The process names in the GPU tab need the `process` collector. + GPU temperature, fan, power and clock panels require WDDM 2.4 or newer and driver support; unsupported sensors are absent. Import the JSON file through **Dashboards > New > Import** and pick the Prometheus data source in the **Data source** variable. @@ -35,9 +36,9 @@ The **Reboots** annotation marks each reboot of the selected host on all graphs. | CPU | Utilization by mode and per core, processor queue length, context switches, interrupts, processes, threads, system calls and the effective CPU frequency. | | Memory | Used and available physical memory, commit charge, hard page faults, kernel pools and the system cache. | | Disk | Volume size and free space, usage, busy time, throughput, IOPS, latency and queue length. | -| Network | Throughput, utilization against the link speed, packets, errors and discards per interface. | +| Network | Throughput, utilization, packets, errors and discards per interface; TCP connection states and rates, segments and retransmissions; UDP datagrams and errors. | | Services | Running, pending and disabled services, automatic services that are not running, and services that started or stopped in the time range. | -| GPU | Utilization by engine type, dedicated and shared memory, and the processes that use the GPU most. | +| GPU | Utilization by engine type, memory capacity, commitment and locality, temperature, fans, power, clocks, and top processes by GPU utilization and memory. | | Hyper-V | VM count and health, Hyper-V WMI health, host CPU time, CPU and memory per VM, virtual disks, virtual switches and VM network adapters. | | Time | Time zone, clock sync source, NTP time sources, clock offset and NTP round-trip delay. | | Exporter | Scrape status and duration, exporter version and uptime, collector status, duration, failures and timeouts, and the exporter's CPU, memory, handles and Go runtime. | diff --git a/dashboard/windows-exporter-dashboard.json b/dashboard/windows-exporter-dashboard.json index e1b6fc83..5b06c7c7 100644 --- a/dashboard/windows-exporter-dashboard.json +++ b/dashboard/windows-exporter-dashboard.json @@ -94,7 +94,7 @@ "transformations": [] } }, - "description": "", + "description": "Windows product name and version reported by the os collector. Use this to distinguish hosts when investigating version-specific behavior.", "id": 10, "links": [], "title": "Operating system", @@ -1821,7 +1821,7 @@ "transformations": [] } }, - "description": "", + "description": "Number of logical processors available to Windows, including SMT threads. This is the logical CPU count rather than the number of physical sockets.", "id": 12, "links": [], "title": "CPUs", @@ -1869,6 +1869,1288 @@ } } }, + "panel-120": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "max by (luid, phys) (windows_gpu_temperature_celsius{job=~\"$job\", instance=\"$instance\"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} GPU {{phys}} temperature", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + }, + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "max by (luid, phys) (windows_gpu_temperature_warning_celsius{job=~\"$job\", instance=\"$instance\"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} GPU {{phys}} throttling threshold", + "range": true + }, + "version": "v0" + }, + "refId": "B" + } + }, + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "max by (luid, phys) (windows_gpu_temperature_max_celsius{job=~\"$job\", instance=\"$instance\"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} GPU {{phys}} maximum", + "range": true + }, + "version": "v0" + }, + "refId": "C" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Current GPU temperature, driver-reported throttling threshold and maximum temperature in degrees Celsius. Sustained readings near the warning threshold can indicate insufficient cooling. Requires the gpu collector, WDDM 2.4 or newer and driver support. Unsupported sensor values are absent, rather than zero.", + "id": 120, + "links": [], + "title": "GPU temperature", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "celsius" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-121": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "max by (luid, phys) (windows_gpu_fan_speed_rpm{job=~\"$job\", instance=\"$instance\"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} GPU {{phys}} fan", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + }, + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "max by (luid, phys) (windows_gpu_fan_speed_max_rpm{job=~\"$job\", instance=\"$instance\"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} GPU {{phys}} maximum", + "range": true + }, + "version": "v0" + }, + "refId": "B" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Current and maximum main-fan speed in revolutions per minute. A supported fan can report zero when stopped under light load. Requires the gpu collector, WDDM 2.4 or newer and driver support. Unsupported sensor values are absent, rather than zero.", + "id": 121, + "links": [], + "title": "GPU fan speed", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "rotrpm" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-122": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "max by (luid, phys) (windows_gpu_power_usage_ratio{job=~\"$job\", instance=\"$instance\"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} GPU {{phys}} power", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Current GPU power draw as a fraction of the driver-reported maximum power (TDP). This is a ratio, not an absolute measurement in watts. Requires the gpu collector, WDDM 2.4 or newer and driver support. Unsupported sensor values are absent, rather than zero.", + "id": 122, + "links": [], + "title": "GPU power usage", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-123": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "max by (luid, phys) (windows_gpu_memory_frequency_hertz{job=~\"$job\", instance=\"$instance\"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} GPU {{phys}} memory clock", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + }, + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "max by (luid, phys) (windows_gpu_memory_frequency_max_hertz{job=~\"$job\", instance=\"$instance\"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} GPU {{phys}} maximum", + "range": true + }, + "version": "v0" + }, + "refId": "B" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Current and maximum non-overclocked GPU memory clock in hertz. Clocks can fall at idle; correlate drops under load with temperature and power. Requires the gpu collector, WDDM 2.4 or newer and driver support. Unsupported sensor values are absent, rather than zero.", + "id": 123, + "links": [], + "title": "GPU memory clock", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "hertz" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-124": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "max by (luid, phys, eng) (windows_gpu_engine_frequency_hertz{job=~\"$job\", instance=\"$instance\"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} GPU {{phys}} engine {{eng}} clock", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + }, + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "max by (luid, phys, eng) (windows_gpu_engine_frequency_max_hertz{job=~\"$job\", instance=\"$instance\"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} GPU {{phys}} engine {{eng}} maximum", + "range": true + }, + "version": "v0" + }, + "refId": "B" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Current and maximum non-overclocked frequency per GPU engine in hertz. Only engines with a reported maximum clock are exposed, typically the 3D engine. Requires the gpu collector, WDDM 2.4 or newer and driver support. Unsupported sensor values are absent, rather than zero.", + "id": 124, + "links": [], + "title": "GPU engine clock", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "hertz" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-125": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "max by (luid, phys) (windows_gpu_adapter_memory_committed_bytes{job=~\"$job\", instance=\"$instance\"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} GPU {{phys}} committed", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Total committed GPU memory per physical GPU in bytes. Commitment is a separate accounting measure from dedicated or shared memory residency; do not add these series together.", + "id": 125, + "links": [], + "title": "GPU committed memory", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-126": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum by (luid, phys) (windows_gpu_local_adapter_memory_bytes{job=~\"$job\", instance=\"$instance\"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} GPU {{phys}} local", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + }, + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum by (luid, phys) (windows_gpu_non_local_adapter_memory_bytes{job=~\"$job\", instance=\"$instance\"}) * on (luid, phys) group_left (name) max by (luid, phys, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} GPU {{phys}} non-local", + "range": true + }, + "version": "v0" + }, + "refId": "B" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Local and non-local adapter memory usage in bytes, summed across memory partitions for each physical GPU. These describe memory locality and overlap the dedicated/shared accounting views.", + "id": 126, + "links": [], + "title": "GPU local and non-local memory", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-127": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "max by (luid) (windows_gpu_dedicated_system_memory_size_bytes{job=~\"$job\", instance=\"$instance\"}) * on (luid) group_left (name) max by (luid, name) (windows_gpu_info{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{name}} dedicated system capacity", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "System memory dedicated to each GPU in bytes. This capacity is distinct from dedicated video memory and the shared system memory pool; it can be zero on discrete adapters.", + "id": 127, + "links": [], + "title": "GPU dedicated system memory capacity", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-128": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "topk(10, (sum by (process_id) (windows_gpu_process_memory_shared_bytes{job=~\"$job\", instance=\"$instance\"}) * on (process_id) group_left (process) max by (process_id, process) (windows_process_info{job=~\"$job\", instance=\"$instance\"})) or on (process_id) sum by (process_id) (windows_gpu_process_memory_shared_bytes{job=~\"$job\", instance=\"$instance\"}))", + "instant": false, + "legendFormat": "{{process}} ({{process_id}})", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Top ten processes at each point in time by shared GPU memory in bytes, summed across GPUs. Membership can change over time. Process names require the process collector; otherwise the PID is shown. Memory accounting views overlap and should not be added together.", + "id": 128, + "links": [], + "title": "Top 10 processes by shared GPU memory", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-129": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "topk(10, (sum by (process_id) (windows_gpu_process_memory_committed_bytes{job=~\"$job\", instance=\"$instance\"}) * on (process_id) group_left (process) max by (process_id, process) (windows_process_info{job=~\"$job\", instance=\"$instance\"})) or on (process_id) sum by (process_id) (windows_gpu_process_memory_committed_bytes{job=~\"$job\", instance=\"$instance\"}))", + "instant": false, + "legendFormat": "{{process}} ({{process_id}})", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Top ten processes at each point in time by committed GPU memory in bytes, summed across GPUs. Membership can change over time. Process names require the process collector; otherwise the PID is shown. Memory accounting views overlap and should not be added together.", + "id": 129, + "links": [], + "title": "Top 10 processes by committed GPU memory", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, "panel-13": { "kind": "Panel", "spec": { @@ -1903,7 +3185,7 @@ "transformations": [] } }, - "description": "", + "description": "Total physical memory visible to Windows in bytes. Compare with used memory and commit charge when investigating memory pressure.", "id": 13, "links": [], "title": "RAM", @@ -1952,6 +3234,236 @@ } } }, + "panel-130": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "topk(10, (sum by (process_id) (windows_gpu_process_memory_local_bytes{job=~\"$job\", instance=\"$instance\"}) * on (process_id) group_left (process) max by (process_id, process) (windows_process_info{job=~\"$job\", instance=\"$instance\"})) or on (process_id) sum by (process_id) (windows_gpu_process_memory_local_bytes{job=~\"$job\", instance=\"$instance\"}))", + "instant": false, + "legendFormat": "{{process}} ({{process_id}})", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Top ten processes at each point in time by local GPU memory in bytes, summed across GPUs. Membership can change over time. Process names require the process collector; otherwise the PID is shown. Memory accounting views overlap and should not be added together.", + "id": 130, + "links": [], + "title": "Top 10 processes by local GPU memory", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-131": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "topk(10, (sum by (process_id) (windows_gpu_process_memory_non_local_bytes{job=~\"$job\", instance=\"$instance\"}) * on (process_id) group_left (process) max by (process_id, process) (windows_process_info{job=~\"$job\", instance=\"$instance\"})) or on (process_id) sum by (process_id) (windows_gpu_process_memory_non_local_bytes{job=~\"$job\", instance=\"$instance\"}))", + "instant": false, + "legendFormat": "{{process}} ({{process_id}})", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Top ten processes at each point in time by non-local GPU memory in bytes, summed across GPUs. Membership can change over time. Process names require the process collector; otherwise the PID is shown. Memory accounting views overlap and should not be added together.", + "id": 131, + "links": [], + "title": "Top 10 processes by non-local GPU memory", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, "panel-14": { "kind": "Panel", "spec": { @@ -1986,7 +3498,7 @@ "transformations": [] } }, - "description": "", + "description": "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.", "id": 14, "links": [], "title": "CPU busy", @@ -2045,6 +3557,940 @@ } } }, + "panel-140": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum by (state) (windows_tcp_connections_state_count{job=~\"$job\", instance=\"$instance\"})", + "instant": false, + "legendFormat": "{{state}}", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "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.", + "id": 140, + "links": [], + "title": "TCP connections by state", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-141": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum(rate(windows_tcp_connections_active_total{job=~\"$job\", instance=\"$instance\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "opened outgoing", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + }, + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum(rate(windows_tcp_connections_passive_total{job=~\"$job\", instance=\"$instance\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "accepted incoming", + "range": true + }, + "version": "v0" + }, + "refId": "B" + } + }, + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum(rate(windows_tcp_connection_failures_total{job=~\"$job\", instance=\"$instance\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "failed", + "range": true + }, + "version": "v0" + }, + "refId": "C" + } + }, + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum(rate(windows_tcp_connections_reset_total{job=~\"$job\", instance=\"$instance\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "reset", + "range": true + }, + "version": "v0" + }, + "refId": "D" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Outgoing (active) and incoming (passive) connections opened per second, connection attempts that failed, and established connections that were reset.", + "id": 141, + "links": [], + "title": "TCP connections opened, failed and reset", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "ops" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "failed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "reset" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "orange", + "mode": "fixed" + } + } + ] + } + ] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-142": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum(rate(windows_tcp_segments_sent_total{job=~\"$job\", instance=\"$instance\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "sent", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + }, + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum(rate(windows_tcp_segments_received_total{job=~\"$job\", instance=\"$instance\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "received", + "range": true + }, + "version": "v0" + }, + "refId": "B" + } + }, + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum(rate(windows_tcp_segments_retransmitted_total{job=~\"$job\", instance=\"$instance\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "retransmitted", + "range": true + }, + "version": "v0" + }, + "refId": "C" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Received segments are drawn below the axis.", + "id": 142, + "links": [], + "title": "TCP segments", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "received" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "retransmitted" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + } + ] + } + ] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-143": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum(rate(windows_tcp_segments_retransmitted_total{job=~\"$job\", instance=\"$instance\"}[$__rate_interval])) / sum(rate(windows_tcp_segments_sent_total{job=~\"$job\", instance=\"$instance\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "retransmitted", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Retransmitted segments as a share of sent segments. A rate that stays above a few percent points to packet loss on the network.", + "id": 143, + "links": [], + "title": "TCP retransmission rate", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "dashed" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "orange", + "value": 0.01 + }, + { + "color": "red", + "value": 0.05 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-144": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum(rate(windows_udp_datagram_sent_total{job=~\"$job\", instance=\"$instance\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "sent", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + }, + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum(rate(windows_udp_datagram_received_total{job=~\"$job\", instance=\"$instance\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "received", + "range": true + }, + "version": "v0" + }, + "refId": "B" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Needs the udp collector, which is not enabled by default. Received datagrams are drawn below the axis.", + "id": 144, + "links": [], + "title": "UDP datagrams", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "received" + }, + "properties": [ + { + "id": "custom.transform", + "value": "negative-Y" + } + ] + } + ] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, + "panel-145": { + "kind": "Panel", + "spec": { + "data": { + "kind": "QueryGroup", + "spec": { + "queries": [ + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum(rate(windows_udp_datagram_received_errors_total{job=~\"$job\", instance=\"$instance\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "received errors", + "range": true + }, + "version": "v0" + }, + "refId": "A" + } + }, + { + "kind": "PanelQuery", + "spec": { + "hidden": false, + "query": { + "datasource": { + "name": "${datasource}" + }, + "group": "prometheus", + "kind": "DataQuery", + "spec": { + "editorMode": "code", + "expr": "sum(rate(windows_udp_datagram_no_port_total{job=~\"$job\", instance=\"$instance\"}[$__rate_interval]))", + "instant": false, + "legendFormat": "no listening port", + "range": true + }, + "version": "v0" + }, + "refId": "B" + } + } + ], + "queryOptions": {}, + "transformations": [] + } + }, + "description": "Received datagrams that could not be delivered, and datagrams for a port that no application listens on.", + "id": 145, + "links": [], + "title": "UDP errors", + "vizConfig": { + "group": "timeseries", + "kind": "VizConfig", + "spec": { + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "pps" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "received errors" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + } + ] + } + ] + }, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "lastNotNull" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "desc" + } + } + }, + "version": "" + } + } + }, "panel-15": { "kind": "Panel", "spec": { @@ -2079,7 +4525,7 @@ "transformations": [] } }, - "description": "", + "description": "Percentage of physical memory in use, calculated as total minus available memory. This differs from commit charge, which measures promised virtual memory against the commit limit.", "id": 15, "links": [], "title": "Memory used", @@ -2351,7 +4797,7 @@ "transformations": [] } }, - "description": "", + "description": "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.", "id": 18, "links": [], "title": "CPU utilization", @@ -3563,7 +6009,7 @@ ] } }, - "description": "", + "description": "Size, available space and used percentage of each selected logical volume. Windows free-space counters can lag by 10 to 15 minutes; use trends rather than treating a single sample as immediate confirmation of reclaimed space.", "id": 20, "links": [], "title": "Volumes", @@ -4392,7 +6838,7 @@ "transformations": [] } }, - "description": "", + "description": "Context switches, hardware interrupts and deferred procedure calls per second across the host. High rates can reflect scheduling or driver activity; correlate changes with CPU usage and workload rather than assuming they are faults.", "id": 27, "links": [], "title": "Context switches and interrupts", @@ -4529,7 +6975,7 @@ "transformations": [] } }, - "description": "", + "description": "Current process and thread counts on the host. Sustained growth can help identify runaway process creation or thread leaks; thread counts use the right-hand axis.", "id": 28, "links": [], "title": "Processes and threads", @@ -4679,7 +7125,7 @@ "transformations": [] } }, - "description": "", + "description": "System calls and exception dispatches per second. Exception dispatches include handled exceptions and do not directly count application crashes; compare with application logs. Exceptions use the right-hand axis.", "id": 29, "links": [], "title": "System calls and exceptions", @@ -5833,7 +8279,7 @@ ] } }, - "description": "", + "description": "Size, available space and used percentage of each selected logical volume. Windows free-space counters can lag by 10 to 15 minutes; use trends rather than treating a single sample as immediate confirmation of reclaimed space.", "id": 37, "links": [], "title": "Volumes", @@ -6007,7 +8453,7 @@ "transformations": [] } }, - "description": "", + "description": "Used space as a percentage of each selected logical volume. Sustained growth toward full capacity can prevent writes and disrupt applications; Windows free-space counters can lag by 10 to 15 minutes.", "id": 38, "links": [], "title": "Volume usage", @@ -7464,7 +9910,7 @@ "transformations": [] } }, - "description": "", + "description": "Receive and transmit packet errors, discarded packets and received packets with unknown protocols per second for each selected interface. Errors can indicate link or driver problems; discards can reflect buffer pressure or filtering.", "id": 48, "links": [], "title": "Network errors and discards", @@ -7699,7 +10145,7 @@ "transformations": [] } }, - "description": "", + "description": "Number of services currently in the running state, reported by the service collector. Compare unexpected drops with the stopped automatic services table and service change history.", "id": 50, "links": [], "title": "Running services", @@ -7953,7 +10399,7 @@ "transformations": [] } }, - "description": "", + "description": "Number of services configured with disabled startup. A disabled service cannot start until its startup mode changes; disabled services are not necessarily unhealthy.", "id": 53, "links": [], "title": "Disabled services", @@ -9403,7 +11849,7 @@ "transformations": [] } }, - "description": "", + "description": "Number of Hyper-V virtual machines reporting critical health. Inspect the affected VM and Hyper-V event logs; this requires the optional hyperv collector.", "id": 64, "links": [], "title": "VMs in critical health", @@ -9590,7 +12036,7 @@ "transformations": [] } }, - "description": "", + "description": "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.", "id": 66, "links": [], "title": "Logical processors", @@ -11303,7 +13749,7 @@ "transformations": [] } }, - "description": "", + "description": "Incoming and outgoing packets dropped per second by each Hyper-V virtual switch. Correlate sustained drops with network load, resource pressure and switch policies; this requires the optional hyperv collector.", "id": 81, "links": [], "title": "Virtual switch dropped packets", @@ -11651,7 +14097,7 @@ "transformations": [] } }, - "description": "", + "description": "Active Windows Time synchronization provider. A non-NTP provider can be expected on virtual machines; this requires the optional time collector.", "id": 85, "links": [], "title": "Clock sync source", @@ -11931,7 +14377,7 @@ "transformations": [] } }, - "description": "", + "description": "Signed offset from the selected time source and the NTP request round-trip delay, in seconds. Persistent offset or increased delay can affect time-sensitive applications; this compares the host to its chosen source and does not independently verify that source.", "id": 88, "links": [], "title": "Clock offset and NTP round-trip delay", @@ -12491,7 +14937,7 @@ "transformations": [] } }, - "description": "", + "description": "Number of metric samples returned before Prometheus metric relabeling. Changes can reflect collector configuration or changing device/process counts; unexpected drops should be checked against scrape and collector success.", "id": 95, "links": [], "title": "Samples per scrape", @@ -12964,7 +15410,7 @@ ] } }, - "description": "", + "description": "Latest success, timeout and duration for each enabled collector. Success is 1 for a completed collection and 0 for a failure; timeout is 1 when the scrape budget was exceeded. Disabled collectors are absent.", "id": 99, "links": [], "title": "Collectors", @@ -13671,59 +16117,179 @@ "kind": "TabsLayoutTab", "spec": { "layout": { - "kind": "GridLayout", + "kind": "RowsLayout", "spec": { - "items": [ + "rows": [ { - "kind": "GridLayoutItem", + "kind": "RowsLayoutRow", "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-45" + "collapse": false, + "layout": { + "kind": "GridLayout", + "spec": { + "items": [ + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-45" + }, + "height": 8, + "width": 12, + "x": 0, + "y": 0 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-46" + }, + "height": 8, + "width": 12, + "x": 12, + "y": 0 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-47" + }, + "height": 8, + "width": 12, + "x": 0, + "y": 8 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-48" + }, + "height": 8, + "width": 12, + "x": 12, + "y": 8 + } + } + ] + } }, - "height": 8, - "width": 12, - "x": 0, - "y": 0 + "title": "Interfaces" } }, { - "kind": "GridLayoutItem", + "kind": "RowsLayoutRow", "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-46" + "collapse": false, + "layout": { + "kind": "GridLayout", + "spec": { + "items": [ + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-140" + }, + "height": 8, + "width": 12, + "x": 0, + "y": 0 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-141" + }, + "height": 8, + "width": 12, + "x": 12, + "y": 0 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-142" + }, + "height": 8, + "width": 12, + "x": 0, + "y": 8 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-143" + }, + "height": 8, + "width": 12, + "x": 12, + "y": 8 + } + } + ] + } }, - "height": 8, - "width": 12, - "x": 12, - "y": 0 + "title": "TCP" } }, { - "kind": "GridLayoutItem", + "kind": "RowsLayoutRow", "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-47" + "collapse": false, + "layout": { + "kind": "GridLayout", + "spec": { + "items": [ + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-144" + }, + "height": 8, + "width": 12, + "x": 0, + "y": 0 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-145" + }, + "height": 8, + "width": 12, + "x": 12, + "y": 0 + } + } + ] + } }, - "height": 8, - "width": 12, - "x": 0, - "y": 8 - } - }, - { - "kind": "GridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-48" - }, - "height": 8, - "width": 12, - "x": 12, - "y": 8 + "title": "UDP" } } ] @@ -13894,6 +16460,162 @@ "x": 12, "y": 13 } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-120" + }, + "height": 8, + "width": 12, + "x": 0, + "y": 21 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-121" + }, + "height": 8, + "width": 12, + "x": 12, + "y": 21 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-122" + }, + "height": 8, + "width": 12, + "x": 0, + "y": 29 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-123" + }, + "height": 8, + "width": 12, + "x": 12, + "y": 29 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-124" + }, + "height": 8, + "width": 12, + "x": 0, + "y": 37 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-125" + }, + "height": 8, + "width": 12, + "x": 12, + "y": 37 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-126" + }, + "height": 8, + "width": 12, + "x": 0, + "y": 45 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-127" + }, + "height": 8, + "width": 12, + "x": 12, + "y": 45 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-128" + }, + "height": 8, + "width": 12, + "x": 0, + "y": 53 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-129" + }, + "height": 8, + "width": 12, + "x": 12, + "y": 53 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-130" + }, + "height": 8, + "width": 12, + "x": 0, + "y": 61 + } + }, + { + "kind": "GridLayoutItem", + "spec": { + "element": { + "kind": "ElementReference", + "name": "panel-131" + }, + "height": 8, + "width": 12, + "x": 12, + "y": 61 + } } ] }