mixin: explain "not in Go" goroutines, allow a compact dashboard (#2671)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
Jan-Otto Kröpke
2026-10-11 02:53:43 +00:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 515fbc6fbd
commit 4e6cbf864c
6 changed files with 35 additions and 9 deletions
+14 -1
View File
@@ -257,7 +257,8 @@ The checked-in JSON remains the reference for the rendered dashboard, including
queries, IDs, variables, annotations, transformations, and tab/row layout.
`mise run check-dashboards` regenerates it and runs `git diff --exit-code`, displaying
any drift. CI runs that check before the mixin tests. The dashboard uses its own
variables for selectors; from `_config` it reads only `collectors`.
variables for selectors; from `_config` it reads only `collectors`,
`enableFleetTab` and `enableOverviewTab`.
### Collectors
@@ -279,6 +280,18 @@ object with `collectors:` enables only the listed collectors:
}.grafanaDashboards['windows-exporter.json']
```
The Fleet and Overview tabs combine several collectors. For a compact
dashboard with only the collector tabs and the Exporter tab, turn them off:
```jsonnet
(import 'mixin.libsonnet') {
_config+:: {
enableFleetTab: false,
enableOverviewTab: false,
},
}.grafanaDashboards['windows-exporter.json']
```
The committed sample dashboard enables every collector. The Fleet hosts table
always queries the default collectors; its columns stay empty for collectors
that are turned off. Tab sources are
+5
View File
@@ -11,6 +11,11 @@
// Requires the time collector with its ntp subcollector enabled.
enableTime: false,
// Dashboard tabs that don't belong to a single collector. Turn them off
// for a compact dashboard with only the collector tabs.
enableFleetTab: true,
enableOverviewTab: true,
// Collectors enabled on the windows_exporter targets, by collector name.
// The dashboard only renders the tabs, rows and panels of enabled
// collectors. The defaults match the exporter's default collectors.
+1 -1
View File
@@ -495,7 +495,7 @@ function(on)
}),
b.panel.new(107, 'Goroutines by state', 'timeseries')
+ b.panel.withDescription('Steady growth of goroutines points to a goroutine leak. Goroutines that stay "not in Go" sit in a system call, for example a collector waiting on WMI or PDH. The states need an exporter build with the Go scheduler metrics; the total line works with every build.')
+ b.panel.withDescription('Steady growth of goroutines points to a goroutine leak. Goroutines that stay "not in Go" sit in a system call, for example a collector waiting on WMI or PDH. The states need an exporter build with the Go scheduler metrics; the total line works with every build. Since 0.32, "not in Go" keeps growing even without a leak: a Go runtime bug (golang/go#82136) counts each WMI callback from a Windows thread once and never subtracts it. Use the total line to spot a leak instead.')
+ b.panel.withQueries([
b.query.new('go_sched_goroutines_running_goroutines{job=~"$job", instance="$instance"}', 'A')
+ b.query.withLegendFormat('running'),
@@ -1,7 +1,9 @@
local b = import 'builders.libsonnet';
local dashboard = b.dashboard;
// config.collectors selects the collectors the dashboard renders, see config.libsonnet.
// config.collectors selects the collectors the dashboard renders, and
// config.enableFleetTab and config.enableOverviewTab the tabs across
// collectors, see config.libsonnet.
function(config)
local known = std.objectFields((import '../config.libsonnet')._config.collectors);
local unknown = std.setDiff(std.objectFields(config.collectors), known);
@@ -15,8 +17,8 @@ function(config)
local tabs = [
tab
for tab in [
(import 'fleet.libsonnet')(on, config),
(import 'overview.libsonnet')(on),
if config.enableFleetTab then (import 'fleet.libsonnet')(on, config),
if config.enableOverviewTab then (import 'overview.libsonnet')(on),
(import 'cpu.libsonnet')(on),
(import 'memory.libsonnet')(on),
(import 'disk.libsonnet')(on),
@@ -31,7 +33,7 @@ function(config)
(import 'time.libsonnet')(on),
(import 'exporter.libsonnet')(on),
]
if !tab.empty
if tab != null && !tab.empty
];
local panelNames = std.flattenArrays([std.objectFields(tab.elements) for tab in tabs]);
+8 -2
View File
@@ -3,8 +3,8 @@
// empty. Run with jsonnet -J vendor tests/dashboard.test.jsonnet.
local mixin = import '../mixin.libsonnet';
local render(collectors) =
(mixin { _config+:: { collectors: collectors(super.collectors) } }).grafanaDashboards['windows-exporter.json'];
local render(collectors, config={}) =
(mixin { _config+:: { collectors: collectors(super.collectors) } + config }).grafanaDashboards['windows-exporter.json'];
local all(value) = function(collectors) { [name]: value for name in std.objectFields(collectors) };
local placed(layout) =
@@ -36,6 +36,8 @@ local results = {
storageSpacesOnly: summary(render(only({ storage_spaces: true }))).Disk,
// A collectors object given without +: enables only the listed collectors.
replaced: summary(render(function(_) { os: true, cpu: true })),
// Only collector tabs, for a compact dashboard.
collectorTabsOnly: summary(render(function(_) { os: true, cpu: true }, { enableFleetTab: false, enableOverviewTab: false })),
};
local expect(name, want) =
@@ -64,5 +66,9 @@ assert expect('replaced', {
Fleet: ['Summary', 'Hosts', 'Utilization'],
Overview: ['Summary', 'CPU and memory'],
});
assert expect('collectorTabsOnly', {
CPU: ['Summary', 'Utilization', 'System calls and frequency'],
Exporter: exporter,
});
results
+1 -1
View File
@@ -1031,7 +1031,7 @@
"transformations": []
}
},
"description": "Steady growth of goroutines points to a goroutine leak. Goroutines that stay \"not in Go\" sit in a system call, for example a collector waiting on WMI or PDH. The states need an exporter build with the Go scheduler metrics; the total line works with every build.",
"description": "Steady growth of goroutines points to a goroutine leak. Goroutines that stay \"not in Go\" sit in a system call, for example a collector waiting on WMI or PDH. The states need an exporter build with the Go scheduler metrics; the total line works with every build. Since 0.32, \"not in Go\" keeps growing even without a leak: a Go runtime bug (golang/go#82136) counts each WMI callback from a Windows thread once and never subtracts it. Use the total line to spot a leak instead.",
"id": 107,
"links": [],
"title": "Goroutines by state",