mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-10-20 11:39:04 +02:00
mixin: add an MSSQL dashboard (#2725)
Signed-off-by: Claude <noreply@anthropic.com> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
8c33aba631
commit
d6c4c6fa46
+17
-2
@@ -264,8 +264,8 @@ queries, IDs, variables, annotations, transformations, and tab/row layout.
|
||||
`mise run check-dashboards` regenerates them, marks new dashboard files with
|
||||
`git add --intent-to-add` 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`,
|
||||
`enableFleetTab`, `enableOverviewTab`, `enableTabDashboards` and the dashboard
|
||||
metadata below.
|
||||
`enableFleetTab`, `enableOverviewTab`, `enableTabDashboards`,
|
||||
`separateDashboardTabs` and the dashboard metadata below.
|
||||
|
||||
### Metadata
|
||||
|
||||
@@ -298,6 +298,21 @@ instead of replacing them:
|
||||
In the Fleet dashboard, a hostname links to the Overview dashboard; in the full
|
||||
dashboard, it links to the Overview tab.
|
||||
|
||||
`separateDashboardTabs` lists tabs, by the slug in their UID, that render only
|
||||
as dashboards of their own and are left out of the full dashboard. They render
|
||||
even with `enableTabDashboards: false`. It defaults to `['mssql']`, so the MSSQL
|
||||
dashboard (`windows-exporter-mssql`) is separate. Set it to `[]` to add the MSSQL
|
||||
tab to the full dashboard:
|
||||
|
||||
```jsonnet
|
||||
(import 'mixin.libsonnet') {
|
||||
_config+:: {
|
||||
collectors+: { mssql: true },
|
||||
separateDashboardTabs: [],
|
||||
},
|
||||
}.grafanaDashboards['windows-exporter.json']
|
||||
```
|
||||
|
||||
### Collectors
|
||||
|
||||
`_config.collectors` lists the windows_exporter collectors by their exporter
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
// for a compact dashboard with only the collector tabs.
|
||||
enableFleetTab: true,
|
||||
enableOverviewTab: true,
|
||||
// Tabs, by the slug in their UID, that render only as dashboards of their
|
||||
// own, even with enableTabDashboards: false, and not in the full
|
||||
// dashboard. Set it to [] to add them to the full dashboard.
|
||||
separateDashboardTabs: ['mssql'],
|
||||
|
||||
// Collectors enabled on the windows_exporter targets, by collector name.
|
||||
// The dashboard only renders the tabs, rows and panels of enabled
|
||||
@@ -41,6 +45,7 @@
|
||||
hyperv: false,
|
||||
logical_disk: true,
|
||||
memory: true,
|
||||
mssql: false,
|
||||
net: true,
|
||||
os: true,
|
||||
physical_disk: true,
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
local b = import 'builders.libsonnet';
|
||||
local metric(name, labels='') = 'windows_mssql_' + name + '{job=~"$job", instance="$instance", mssql_instance="$mssql_instance"' + (if labels == '' then '' else ', ' + labels) + '}';
|
||||
local rate(name, labels='') = 'rate(' + metric(name, labels) + '[$__rate_interval])';
|
||||
local database(name) = metric('databases_' + name, 'database=~"$database"');
|
||||
local databaseRate(name) = rate('databases_' + name, 'database=~"$database"');
|
||||
local requirement = ' Requires the mssql collector, which is not enabled by default.';
|
||||
// Buffer pool pages are 8 KiB.
|
||||
local pageBytes = '8192';
|
||||
// Wait classes of the Wait Statistics object, by metric name suffix.
|
||||
local waitClasses = [
|
||||
['lock_waits', 'lock'],
|
||||
['memory_grant_queue_waits', 'memory grant queue'],
|
||||
['thread_safe_memory_objects_waits', 'thread-safe memory objects'],
|
||||
['log_write_waits', 'log write'],
|
||||
['log_buffer_waits', 'log buffer'],
|
||||
['network_io_waits', 'network I/O'],
|
||||
['page_io_latch_waits', 'page I/O latch'],
|
||||
['page_latch_waits', 'page latch'],
|
||||
['nonpage_latch_waits', 'non-page latch'],
|
||||
['wait_for_the_worker_waits', 'wait for the worker'],
|
||||
['workspace_synchronization_waits', 'workspace synchronization'],
|
||||
['transaction_ownership_waits', 'transaction ownership'],
|
||||
];
|
||||
local bytes(names) = [{ matcher: { id: 'byName', options: name }, properties: [{ id: 'unit', value: 'bytes' }] } for name in names];
|
||||
|
||||
function(on)
|
||||
b.tab(
|
||||
'MSSQL',
|
||||
b.rows([
|
||||
if on('mssql') then b.summary([256, 257, 258, 259, 260, 261, 262, 263]),
|
||||
if on('mssql') then b.row('Activity', b.flow([[264, 12, 8], [265, 12, 8], [266, 8, 8], [267, 8, 8], [268, 8, 8]])),
|
||||
if on('mssql') then b.row('Waits and locks', b.flow([[269, 24, 9], [270, 8, 8], [271, 8, 8], [272, 8, 8]])),
|
||||
if on('mssql') then b.row('Memory and buffer pool', b.flow([[273, 12, 8], [274, 12, 8], [275, 8, 8], [276, 8, 8], [277, 8, 8]])),
|
||||
if on('mssql') then b.row('Databases', b.flow([[278, 24, 8], [279, 12, 8], [280, 12, 8], [281, 8, 8], [282, 8, 8], [283, 8, 8]])),
|
||||
if on('mssql') then b.row('tempdb and transactions', b.flow([[284, 8, 8], [285, 8, 8], [286, 8, 8]])),
|
||||
if on('mssql') then b.row('Availability groups', b.flow([[287, 12, 8], [288, 12, 8]])),
|
||||
]),
|
||||
[
|
||||
b.stat(256, 'Sub-collector failures', 'mssql sub-collectors that failed at the last scrape for this SQL Server instance. The Exporter tab shows the scrape errors.' + requirement, 'count(' + metric('collector_success') + ' == 0) or (0 * count(' + metric('collector_success') + '))', steps=[{ color: 'green', value: null }, { color: 'red', value: 1 }]),
|
||||
b.stat(257, 'User connections', 'Users connected to the instance. Each user can have several connections.' + requirement, metric('genstats_user_connections')),
|
||||
b.stat(258, 'Batch requests', 'Transact-SQL command batches received per second.' + requirement, rate('sqlstats_batch_requests'), 'reqps'),
|
||||
b.stat(259, 'Blocked processes', 'Processes currently blocked by another process.' + requirement, metric('genstats_blocked_processes'), steps=[{ color: 'green', value: null }, { color: 'orange', value: 1 }]),
|
||||
b.stat(260, 'Deadlocks', 'Lock requests per minute that resulted in a deadlock, across all lock resource types.' + requirement, '60 * sum(' + rate('locks_deadlocks') + ')', 'opm', steps=b.levels(0.1, 1))
|
||||
+ b.panel.withDefaults({ decimals: 1 }),
|
||||
b.stat(261, 'Pending memory grants', 'Processes waiting for a workspace memory grant to run a query. Values above zero mean queries wait for memory.' + requirement, metric('memmgr_pending_memory_grants'), steps=[{ color: 'green', value: null }, { color: 'orange', value: 1 }]),
|
||||
b.stat(262, 'Page life expectancy', 'Seconds a page stays in the buffer pool without references. A falling value means the buffer pool is under memory pressure.' + requirement, metric('bufman_page_life_expectancy_seconds'), 's'),
|
||||
b.stat(263, 'Buffer cache hit ratio', 'Share of page lookups found in the buffer pool without a disk read, over the most recent SQL Server sampling interval.' + requirement, metric('bufman_buffer_cache_hits') + ' / (' + metric('bufman_buffer_cache_lookups') + ' > 0)', 'percentunit')
|
||||
+ b.panel.withDefaults({ decimals: 1, max: 1, min: 0 }),
|
||||
|
||||
b.graph(264, 'Batch requests and compilations', 'Transact-SQL batches, query compilations and recompilations per second. Many compilations per batch can indicate plans that are not reused.' + requirement, 'ops', [
|
||||
[rate('sqlstats_batch_requests'), 'batch requests'],
|
||||
[rate('sqlstats_sql_compilations'), 'compilations'],
|
||||
[rate('sqlstats_sql_recompilations'), 'recompilations'],
|
||||
[rate('sqlstats_sql_attentions'), 'attentions'],
|
||||
]),
|
||||
b.graph(265, 'Connections', 'Users connected to the instance, and logical connections to it. Each user can have several connections.' + requirement, 'short', [
|
||||
[metric('genstats_user_connections'), 'users'],
|
||||
[metric('genstats_logical_connections'), 'logical connections'],
|
||||
]),
|
||||
b.graph(266, 'Access methods', 'Index searches, unrestricted full scans and page splits per second. Full scans of large tables and many page splits can indicate missing indexes or a low fill factor.' + requirement, 'ops', [
|
||||
[rate('accessmethods_index_searches'), 'index searches'],
|
||||
[rate('accessmethods_full_scans'), 'full scans'],
|
||||
[rate('accessmethods_page_splits'), 'page splits'],
|
||||
]),
|
||||
b.graph(267, 'SQL errors', 'Errors per second by error class.' + requirement, 'ops', [
|
||||
['sum by (resource) (' + rate('sql_errors_total') + ')', '{{resource}}'],
|
||||
]),
|
||||
b.graph(268, 'Logins and logouts', 'Logins, logouts and connection resets from the connection pool per second. Logouts are drawn below the axis.' + requirement, 'ops', [
|
||||
[rate('genstats_logins'), 'logins'],
|
||||
[rate('genstats_logouts'), 'logouts'],
|
||||
[rate('genstats_connection_resets'), 'connection resets'],
|
||||
], below='logouts'),
|
||||
|
||||
b.graph(269, 'Wait time by wait class', 'Time sessions spent waiting per second, by wait class, over the most recent SQL Server sampling interval. 2 s means two sessions waited the whole second on average.' + requirement, 's', [
|
||||
[metric('waitstats_' + class[0], 'item="Cumulative wait time (ms) per second"') + ' / 1000', class[1]]
|
||||
for class in waitClasses
|
||||
])
|
||||
+ b.panel.withDefaults({ custom: { fillOpacity: 40, stacking: { mode: 'normal' } } })
|
||||
+ b.panel.withOptions({ legend: { placement: 'right' } }),
|
||||
b.graph(270, 'Lock waits', 'Lock requests per second that had to wait, by lock resource type.' + requirement, 'ops', [
|
||||
['sum by (resource) (' + rate('locks_lock_waits') + ')', '{{resource}}'],
|
||||
]),
|
||||
b.graph(271, 'Average lock wait', 'Average wait time of the lock requests that waited, by lock resource type.' + requirement, 's', [
|
||||
['sum by (resource) (' + rate('locks_wait_time_seconds_total') + ') / (sum by (resource) (' + rate('locks_count_total') + ') > 0)', '{{resource}}'],
|
||||
]),
|
||||
b.graph(272, 'Deadlocks and lock timeouts', 'Lock requests per second that resulted in a deadlock or timed out, across all lock resource types. Timeouts exclude NOWAIT requests.' + requirement, 'ops', [
|
||||
['sum(' + rate('locks_deadlocks') + ')', 'deadlocks'],
|
||||
['sum(' + rate('locks_lock_timeouts_excluding_NOWAIT') + ')', 'timeouts'],
|
||||
]),
|
||||
|
||||
b.graph(273, 'Server memory', 'Memory the memory manager has committed, against the memory it can use. The total stays below the target when SQL Server needs no more memory.' + requirement, 'bytes', [
|
||||
[metric('memmgr_total_server_memory_bytes'), 'total'],
|
||||
[metric('memmgr_target_server_memory_bytes'), 'target'],
|
||||
[metric('memmgr_stolen_server_memory_bytes'), 'stolen'],
|
||||
])
|
||||
+ b.panel.withOverrides([
|
||||
{
|
||||
matcher: { id: 'byName', options: 'target' },
|
||||
properties: [
|
||||
{ id: 'color', value: { fixedColor: 'red', mode: 'fixed' } },
|
||||
{ id: 'custom.fillOpacity', value: 0 },
|
||||
{ id: 'custom.lineStyle', value: { dash: [10, 10], fill: 'dash' } },
|
||||
],
|
||||
},
|
||||
]),
|
||||
b.graph(274, 'Memory by consumer', 'Server memory used for cached database pages, the plan cache, the query optimizer, locks, the log pool and connections, and memory not in use.' + requirement, 'bytes', [
|
||||
[metric('memmgr_database_cache_memory_bytes'), 'database cache'],
|
||||
[metric('memmgr_sql_cache_memory_bytes'), 'plan cache'],
|
||||
[metric('memmgr_optimizer_memory_bytes'), 'optimizer'],
|
||||
[metric('memmgr_lock_memory_bytes'), 'locks'],
|
||||
[metric('memmgr_log_pool_memory_bytes'), 'log pool'],
|
||||
[metric('memmgr_connection_memory_bytes'), 'connections'],
|
||||
[metric('memmgr_free_memory_bytes'), 'free'],
|
||||
])
|
||||
+ b.panel.withDefaults({ custom: { fillOpacity: 40, stacking: { mode: 'normal' } } }),
|
||||
b.graph(275, 'Page life expectancy', 'Seconds a page stays in the buffer pool without references. Sudden drops mean pages are evicted to make room, for example for a large scan.' + requirement, 's', [
|
||||
[metric('bufman_page_life_expectancy_seconds'), 'page life expectancy'],
|
||||
]),
|
||||
b.graph(276, 'Buffer pool I/O', 'Bytes per second of all physical page writes and the parts written by checkpoints and the lazy writer, and of all page reads and the part read ahead. Reads are drawn below the axis.' + requirement, 'Bps', [
|
||||
[pageBytes + ' * ' + rate('bufman_page_writes'), 'writes'],
|
||||
[pageBytes + ' * ' + rate('bufman_checkpoint_pages'), 'checkpoint writes'],
|
||||
[pageBytes + ' * ' + rate('bufman_lazywrites'), 'lazy writes'],
|
||||
[pageBytes + ' * ' + rate('bufman_page_reads'), 'reads'],
|
||||
[pageBytes + ' * ' + rate('bufman_read_ahead_pages'), 'read-ahead reads'],
|
||||
], below='.*reads'),
|
||||
b.graph(277, 'Memory grants', 'Processes that received a workspace memory grant, and processes waiting for one.' + requirement, 'short', [
|
||||
[metric('memmgr_outstanding_memory_grants'), 'granted'],
|
||||
[metric('memmgr_pending_memory_grants'), 'pending'],
|
||||
]),
|
||||
|
||||
b.joinedTable(278, 'Databases', 'Size, log usage and activity of each selected database.' + requirement, 'database', [
|
||||
'max by (database) (' + database('data_files_size_bytes') + ')',
|
||||
'max by (database) (' + database('log_files_size_bytes') + ')',
|
||||
'max by (database) (' + database('log_used_percent') + ')',
|
||||
'max by (database) (' + database('active_transactions') + ')',
|
||||
'max by (database) (' + databaseRate('transactions') + ')',
|
||||
'max by (database) (' + databaseRate('write_transactions') + ')',
|
||||
], [['database', 'Database'], ['Value #A', 'Data size'], ['Value #B', 'Log size'], ['Value #C', 'Log used'], ['Value #D', 'Active transactions'], ['Value #E', 'Transactions/s'], ['Value #F', 'Writes/s']], [
|
||||
{
|
||||
matcher: { id: 'byName', options: 'Log used' },
|
||||
properties: [
|
||||
{ id: 'unit', value: 'percent' },
|
||||
{ id: 'min', value: 0 },
|
||||
{ id: 'max', value: 100 },
|
||||
{ id: 'decimals', value: 1 },
|
||||
{ id: 'custom.cellOptions', value: { mode: 'basic', type: 'gauge', valueDisplayMode: 'text' } },
|
||||
],
|
||||
},
|
||||
{ matcher: { id: 'byRegexp', options: '.*/s' }, properties: [{ id: 'unit', value: 'ops' }] },
|
||||
] + bytes(['Data size', 'Log size']))
|
||||
+ b.panel.withDefaults({ custom: { filterable: true } }),
|
||||
b.graph(279, 'Data file size', 'Size of the data files of each selected database.' + requirement, 'bytes', [
|
||||
['max by (database) (' + database('data_files_size_bytes') + ')', '{{database}}'],
|
||||
]),
|
||||
b.graph(280, 'Log used', 'Share of the log files of each selected database in use. A log that stays full needs a log backup, a checkpoint or more space.' + requirement, 'percent', [
|
||||
['max by (database) (' + database('log_used_percent') + ')', '{{database}}'],
|
||||
])
|
||||
+ b.panel.withDefaults({ max: 100 }),
|
||||
b.graph(281, 'Transactions', 'Transactions started per second in each selected database.' + requirement, 'ops', [
|
||||
['max by (database) (' + databaseRate('transactions') + ')', '{{database}}'],
|
||||
]),
|
||||
b.graph(282, 'Log flushes', 'Bytes per second written to the transaction log of each selected database.' + requirement, 'Bps', [
|
||||
['max by (database) (' + databaseRate('log_flushed_bytes') + ')', '{{database}}'],
|
||||
]),
|
||||
b.graph(283, 'Log flush write time', 'Average time to write a log flush to disk in each selected database. Commits wait for this write, so slow log storage slows every write transaction.' + requirement, 's', [
|
||||
['max by (database) (' + databaseRate('log_flush_write_seconds_total') + ' / (' + databaseRate('log_flushes') + ' > 0))', '{{database}}'],
|
||||
]),
|
||||
|
||||
b.graph(284, 'tempdb space', 'Free space in tempdb and the size of the version store kept in it for snapshot isolation and online index operations.' + requirement, 'bytes', [
|
||||
[metric('transactions_tempdb_free_space_bytes'), 'free space'],
|
||||
[metric('transactions_version_store_size_bytes'), 'version store'],
|
||||
]),
|
||||
b.graph(285, 'Longest running transaction', 'Seconds since the start of the oldest active transaction that uses row versioning. A long transaction keeps the version store from shrinking.' + requirement, 's', [
|
||||
[metric('transactions_longest_transaction_running_seconds'), 'longest transaction'],
|
||||
]),
|
||||
b.graph(286, 'Active transactions', 'Active transactions, and the ones among them that use snapshot isolation or generate row versions.' + requirement, 'short', [
|
||||
[metric('transactions_active'), 'active'],
|
||||
[metric('transactions_snapshot_active'), 'snapshot'],
|
||||
[metric('transactions_update_snapshot_active'), 'update snapshot'],
|
||||
[metric('transactions_nonsnapshot_version_active'), 'non-snapshot version'],
|
||||
]),
|
||||
|
||||
b.graph(287, 'Replica queues', 'Log of each availability database on this secondary replica not yet received from the primary (send queue), and received but not yet redone (redo queue). The replica label holds the database name. Only secondary replicas of an Always On availability group report these.' + requirement, 'bytes', [
|
||||
['max by (replica) (' + metric('dbreplica_log_send_queue_bytes') + ')', '{{replica}} send queue'],
|
||||
['max by (replica) (' + metric('dbreplica_recovery_queue_bytes') + ')', '{{replica}} redo queue'],
|
||||
]),
|
||||
b.graph(288, 'Replica traffic', 'Bytes per second sent to and received from each availability replica. Received bytes are drawn below the axis.' + requirement, 'Bps', [
|
||||
['max by (replica) (' + rate('availreplica_sent_to_replica_bytes') + ')', '{{replica}} sent'],
|
||||
['max by (replica) (' + rate('availreplica_received_from_replica_bytes') + ')', '{{replica}} received'],
|
||||
], below='.* received'),
|
||||
]
|
||||
)
|
||||
@@ -123,4 +123,18 @@ function(on) [variable for variable in [
|
||||
hide: 'dontHide',
|
||||
skipUrlSync: false,
|
||||
}),
|
||||
if on('mssql') then new('mssql_instance', 'label_values(windows_mssql_collector_success{job=~"$job", instance="$instance"}, mssql_instance)')
|
||||
+ query.spec.withLabel('SQL Server instance'),
|
||||
if on('mssql') then new('database', 'label_values(windows_mssql_databases_data_files_size_bytes{job=~"$job", instance="$instance", mssql_instance="$mssql_instance"}, database)')
|
||||
+ query.spec.withCurrent({
|
||||
text: [
|
||||
'All',
|
||||
],
|
||||
value: [
|
||||
'$__all',
|
||||
],
|
||||
})
|
||||
+ query.spec.withIncludeAll(true)
|
||||
+ query.spec.withLabel('Database')
|
||||
+ query.spec.withMulti(true),
|
||||
] if variable != null]
|
||||
|
||||
@@ -17,6 +17,7 @@ local descriptions = {
|
||||
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.',
|
||||
MSSQL: 'Activity, waits, locks, memory, databases and availability replicas of one SQL Server instance on a Windows host.',
|
||||
Exporter: 'Scrape status, collector health and resource usage of windows_exporter on one host.',
|
||||
};
|
||||
|
||||
@@ -35,8 +36,10 @@ local references(value) = std.set([
|
||||
// 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.
|
||||
// see config.libsonnet. Returns the full dashboard with all tabs except
|
||||
// config.separateDashboardTabs and, with config.enableTabDashboards, a
|
||||
// dashboard per tab by its file name. Separate tabs always render as
|
||||
// dashboards of their own.
|
||||
function(config)
|
||||
local known = std.objectFields((import '../config.libsonnet')._config.collectors);
|
||||
local unknown = std.setDiff(std.objectFields(config.collectors), known);
|
||||
@@ -51,7 +54,13 @@ function(config)
|
||||
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) = [
|
||||
local knownSlugs = [slug(title) for title in std.objectFields(descriptions)];
|
||||
local unknownSeparate = std.setDiff(std.set(config.separateDashboardTabs), std.set(knownSlugs));
|
||||
assert std.length(unknownSeparate) == 0 : 'Unknown tabs in _config.separateDashboardTabs: ' + std.join(', ', unknownSeparate);
|
||||
// The Fleet tab of the full dashboard links hosts to its Overview tab.
|
||||
assert !std.member(config.separateDashboardTabs, 'fleet') && !std.member(config.separateDashboardTabs, 'overview') : 'The Fleet and Overview tabs cannot be in _config.separateDashboardTabs';
|
||||
local separate(tab) = std.member(config.separateDashboardTabs, slug(tab.layout.spec.title));
|
||||
local allTabs(overview) = [
|
||||
tab
|
||||
for tab in [
|
||||
if config.enableFleetTab then (import 'fleet.libsonnet')(on, config, overview),
|
||||
@@ -68,13 +77,14 @@ function(config)
|
||||
(import 'gpu.libsonnet')(on),
|
||||
(import 'hyper_v.libsonnet')(on),
|
||||
(import 'time.libsonnet')(on),
|
||||
(import 'mssql.libsonnet')(on),
|
||||
(import 'exporter.libsonnet')(on),
|
||||
]
|
||||
if tab != null && !tab.empty
|
||||
];
|
||||
local fullTabs = tabs(null);
|
||||
local fullTabs = [tab for tab in allTabs(null) if !separate(tab)];
|
||||
|
||||
local panelNames = std.flattenArrays([std.objectFields(tab.elements) for tab in fullTabs]);
|
||||
local panelNames = std.flattenArrays([std.objectFields(tab.elements) for tab in allTabs(null)]);
|
||||
assert std.length(panelNames) == std.length(std.set(panelNames)) : 'Panel IDs must be unique across tabs';
|
||||
|
||||
local variables = (import 'variables.libsonnet')(on);
|
||||
@@ -171,7 +181,7 @@ function(config)
|
||||
b.tabs([tab.layout for tab in fullTabs]),
|
||||
dropdown=false,
|
||||
),
|
||||
tabs: if config.enableTabDashboards then {
|
||||
tabs: {
|
||||
['windows-exporter-' + slug(tab.layout.spec.title) + '.json']: new(
|
||||
uid(tab.layout.spec.title),
|
||||
config.dashboardTitlePrefix + ' / ' + tab.layout.spec.title,
|
||||
@@ -179,6 +189,7 @@ function(config)
|
||||
tab.elements,
|
||||
tab.layout.spec.layout,
|
||||
)
|
||||
for tab in tabs(if config.enableOverviewTab then uid('Overview'))
|
||||
} else {},
|
||||
for tab in allTabs(if config.enableOverviewTab then uid('Overview'))
|
||||
if config.enableTabDashboards || separate(tab)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -110,6 +110,15 @@ assert custom['windows-exporter.json'].metadata.name == 'win-full' : 'custom pre
|
||||
assert std.objectFields(dashboards(function(collectors) collectors, { enableTabDashboards: false })) == ['windows-exporter.json'] : 'enableTabDashboards: false renders tab dashboards';
|
||||
|
||||
assert std.length(std.objectFields(results.all)) == 15 : 'all: got ' + std.join(', ', std.objectFields(results.all));
|
||||
// MSSQL renders only as a dashboard of its own unless separateDashboardTabs drops it.
|
||||
local withMSSQL = dashboards(only({ mssql: true }));
|
||||
assert !std.objectHas(results.all, 'MSSQL') : 'all: the full dashboard has the MSSQL tab';
|
||||
assert std.objectHas(withMSSQL, 'windows-exporter-mssql.json') : 'mssql: got no MSSQL dashboard';
|
||||
assert withMSSQL['windows-exporter-mssql.json'].metadata.name == 'windows-exporter-mssql' : 'mssql: got UID ' + withMSSQL['windows-exporter-mssql.json'].metadata.name;
|
||||
assert variableNames(withMSSQL['windows-exporter-mssql.json']) == ['datasource', 'job', 'hostname', 'instance', 'mssql_instance', 'database'] : 'mssql: got variables ' + std.join(', ', variableNames(withMSSQL['windows-exporter-mssql.json']));
|
||||
assert std.objectFields(dashboards(only({ mssql: true }), { enableTabDashboards: false })) == ['windows-exporter-mssql.json', 'windows-exporter.json'] : 'enableTabDashboards: false drops the separate MSSQL dashboard';
|
||||
local mssqlInFull = summary(render(only({ mssql: true }), { separateDashboardTabs: [] }));
|
||||
assert mssqlInFull.MSSQL == ['Summary', 'Activity', 'Waits and locks', 'Memory and buffer pool', 'Databases', 'tempdb and transactions', 'Availability groups'] : 'mssql in full: got ' + std.manifestJson(mssqlInFull);
|
||||
assert expect('defaults', {
|
||||
CPU: ['Summary', 'Utilization', 'Scheduling', 'System calls and frequency'],
|
||||
Disk: ['Summary', 'Volumes', 'Volume I/O', 'Physical disks'],
|
||||
|
||||
Reference in New Issue
Block a user