Files
windows_exporter/contrib/mixin/dashboards/windows-exporter.libsonnet
T
2026-10-11 16:29:56 +02:00

185 lines
7.9 KiB
Jsonnet

local b = import 'builders.libsonnet';
local dashboard = b.dashboard;
// Descriptions of the dashboards of single tabs, by tab title.
local descriptions = {
Fleet: 'Health, utilization and stopped services of all Windows hosts monitored by windows_exporter.',
Overview: 'Operating system, uptime, CPU, memory, volumes, disk and network throughput of one Windows host.',
CPU: 'CPU utilization by mode and core, scheduling, system calls and frequency of one Windows host.',
Memory: 'Physical memory, commit charge, paging and kernel memory of one Windows host.',
Disk: 'Volumes, physical disks, drives and Storage Spaces of one Windows host.',
Network: 'Interface throughput, errors and discards, TCP and UDP of one Windows host.',
SMB: 'SMB shares served and used by one Windows host.',
Processes: 'CPU, memory, I/O, threads and handles per process of one Windows host.',
Services: 'Service states and automatic services that are not running on one Windows host.',
'Scheduled tasks': 'Scheduled task states, results and missed runs of one Windows host.',
Updates: 'Pending Windows updates and the last update check of one Windows host.',
GPU: 'GPU utilization, memory, sensors and top processes of one Windows host.',
'Hyper-V': 'Hyper-V virtual machines, virtual disks, switches and network adapters of one Windows host.',
Time: 'Clock synchronization, NTP sources and clock offset of one Windows host.',
Exporter: 'Scrape status, collector health and resource usage of windows_exporter on one host.',
};
local wordChar(c) = std.member('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_', c);
// The leading identifier of text.
local identifier(text) =
local chars = std.stringChars(std.substr(text, 0, 32));
local length = std.foldl(function(acc, c) if acc.done || !wordChar(c) then acc { done: true } else acc { n+: 1 }, chars, { n: 0, done: false }).n;
std.substr(text, 0, length);
// The variable names that value references as $name or ${name...}.
local references(value) = std.set([
identifier(if std.startsWith(part, '{') then std.substr(part, 1, 33) else part)
for part in std.split(std.manifestJsonMinified(value), '$')[1:]
]);
// config.collectors selects the collectors the dashboards render,
// config.enableFleetTab and config.enableOverviewTab the tabs across
// collectors, and config.dashboard* their UIDs, titles, description and tags,
// see config.libsonnet. Returns the full dashboard with all tabs and, with
// config.enableTabDashboards, a dashboard per tab by its file name.
function(config)
local known = std.objectFields((import '../config.libsonnet')._config.collectors);
local unknown = std.setDiff(std.objectFields(config.collectors), known);
assert std.length(unknown) == 0 : 'Unknown collectors in _config.collectors: ' + std.join(', ', unknown);
// A collector missing from a replaced collectors object counts as disabled.
local on(collector) =
assert std.member(known, collector) : 'Unknown collector ' + collector;
std.get(config.collectors, collector, false);
// All variables select hosts through windows_os_hostname.
assert on('os') : 'The dashboard requires the os collector';
local slug(title) = std.strReplace(std.asciiLower(title), ' ', '-');
local uid(title) = config.dashboardUIDPrefix + '-' + slug(title);
// overview is the UID of the Overview dashboard that Fleet links hosts to,
// or null for the Overview tab of the same dashboard.
local tabs(overview) = [
tab
for tab in [
if config.enableFleetTab then (import 'fleet.libsonnet')(on, config, overview),
if config.enableOverviewTab then (import 'overview.libsonnet')(on),
(import 'cpu.libsonnet')(on),
(import 'memory.libsonnet')(on),
(import 'disk.libsonnet')(on),
(import 'network.libsonnet')(on),
(import 'smb.libsonnet')(on),
(import 'processes.libsonnet')(on),
(import 'services.libsonnet')(on),
(import 'scheduled_tasks.libsonnet')(on),
(import 'updates.libsonnet')(on),
(import 'gpu.libsonnet')(on),
(import 'hyper_v.libsonnet')(on),
(import 'time.libsonnet')(on),
(import 'exporter.libsonnet')(on),
]
if tab != null && !tab.empty
];
local fullTabs = tabs(null);
local panelNames = std.flattenArrays([std.objectFields(tab.elements) for tab in fullTabs]);
assert std.length(panelNames) == std.length(std.set(panelNames)) : 'Panel IDs must be unique across tabs';
local variables = (import 'variables.libsonnet')(on);
local annotations = (import 'annotations.libsonnet')(on);
// Tab dashboards link to each other through a dropdown of the dashboards
// with the same tags; the full dashboard has the tabs instead.
local new(uid, title, description, elements, layout, dropdown=true) =
// Grafana rejects longer dashboard UIDs.
assert std.length(uid) <= 40 : 'Dashboard UID ' + uid + ' is longer than 40 characters; shorten dashboardUIDPrefix or dashboardUID';
// Keeps the variables that the panels reference, directly or through
// other variables, and the annotations whose variables are kept.
// Variables only reference variables defined before them.
local kept = std.foldl(
function(used, variable)
if std.setMember(variable.spec.name, used)
then std.setUnion(used, references(variable))
else used,
std.reverse(variables),
references(elements),
);
local dropped = std.set([variable.spec.name for variable in variables if !std.setMember(variable.spec.name, kept)]);
dashboard.new(uid, title)
+ dashboard.spec.withCursorSync('Crosshair')
+ dashboard.spec.withDescription(description)
+ dashboard.spec.withEditable(true)
+ dashboard.spec.withLinks([
link
for link in [
if dropdown then {
asDropdown: true,
icon: 'external link',
includeVars: true,
keepTime: true,
tags: config.dashboardTags,
targetBlank: false,
title: config.dashboardTitlePrefix,
tooltip: 'Dashboards for windows_exporter',
type: 'dashboards',
url: '',
},
{
asDropdown: false,
icon: 'doc',
includeVars: false,
keepTime: false,
tags: [],
targetBlank: true,
title: 'windows_exporter',
tooltip: '',
type: 'link',
url: 'https://github.com/prometheus-community/windows_exporter',
},
]
if link != null
])
+ dashboard.spec.withLiveNow(false)
+ dashboard.spec.withPreload(false)
+ dashboard.spec.withTags(config.dashboardTags)
+ dashboard.spec.withTimeSettings({
autoRefresh: '1m',
autoRefreshIntervals: [
'5s',
'10s',
'30s',
'1m',
'5m',
'15m',
'30m',
'1h',
'2h',
'1d',
],
fiscalYearStartMonth: 0,
from: 'now-3h',
hideTimepicker: false,
to: 'now',
})
+ dashboard.spec.withAnnotations([
annotation
for annotation in annotations
if std.length(std.setInter(references(annotation), dropped)) == 0
])
+ dashboard.spec.withVariables([variable for variable in variables if std.setMember(variable.spec.name, kept)])
+ dashboard.spec.withElements(elements)
+ dashboard.spec.withLayout(layout);
{
full: new(
config.dashboardUID,
config.dashboardTitle,
config.dashboardDescription,
std.foldl(function(elements, tab) elements + tab.elements, fullTabs, {}),
b.tabs([tab.layout for tab in fullTabs]),
dropdown=false,
),
tabs: if config.enableTabDashboards then {
['windows-exporter-' + slug(tab.layout.spec.title) + '.json']: new(
uid(tab.layout.spec.title),
config.dashboardTitlePrefix + ' / ' + tab.layout.spec.title,
descriptions[tab.layout.spec.title],
tab.elements,
tab.layout.spec.layout,
)
for tab in tabs(if config.enableOverviewTab then uid('Overview'))
} else {},
}