Skip to content

Commit 27c8a48

Browse files
authored
Merge pull request #930 from grafana/rjg/grafana11-pvusage
fix(dashboards): Port persistentvolumesusage.json dashboard to new grafonnet library
2 parents 3549ceb + 1f2610c commit 27c8a48

File tree

1 file changed

+188
-158
lines changed

1 file changed

+188
-158
lines changed
Lines changed: 188 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,203 @@
1-
local grafana = import 'github.com/grafana/grafonnet-lib/grafonnet/grafana.libsonnet';
2-
local dashboard = grafana.dashboard;
3-
local row = grafana.row;
4-
local prometheus = grafana.prometheus;
5-
local template = grafana.template;
6-
local graphPanel = grafana.graphPanel;
7-
local promgrafonnet = import '../lib/promgrafonnet/promgrafonnet.libsonnet';
8-
local gauge = promgrafonnet.gauge;
1+
local g = import 'github.com/grafana/grafonnet/gen/grafonnet-latest/main.libsonnet';
2+
local prometheus = g.query.prometheus;
3+
local gauge = g.panel.gauge;
4+
local timeSeries = g.panel.timeSeries;
5+
local var = g.dashboard.variable;
96

107
{
8+
local gaugePanel(title, unit, query) =
9+
gauge.new(title)
10+
+ gauge.standardOptions.withUnit(unit)
11+
+ gauge.queryOptions.withInterval($._config.grafanaK8s.minimumTimeInterval)
12+
+ gauge.queryOptions.withTargets([
13+
prometheus.new('${datasource}', query)
14+
+ prometheus.withInstant(true),
15+
]),
16+
17+
local tsPanel =
18+
timeSeries {
19+
new(title):
20+
timeSeries.new(title)
21+
+ timeSeries.options.legend.withShowLegend()
22+
+ timeSeries.options.legend.withAsTable()
23+
+ timeSeries.options.legend.withDisplayMode('table')
24+
+ timeSeries.options.legend.withPlacement('right')
25+
+ timeSeries.options.legend.withCalcs(['lastNotNull'])
26+
+ timeSeries.options.tooltip.withMode('single')
27+
+ timeSeries.fieldConfig.defaults.custom.withShowPoints('never')
28+
+ timeSeries.fieldConfig.defaults.custom.withFillOpacity(10)
29+
+ timeSeries.fieldConfig.defaults.custom.withSpanNulls(true)
30+
+ timeSeries.queryOptions.withInterval($._config.grafanaK8s.minimumTimeInterval),
31+
},
32+
1133
grafanaDashboards+:: {
1234
'persistentvolumesusage.json':
13-
local sizeGraph = graphPanel.new(
14-
'Volume Space Usage',
15-
datasource='$datasource',
16-
format='bytes',
17-
min=0,
18-
span=9,
19-
stack=true,
20-
legend_show=true,
21-
legend_values=true,
22-
legend_min=true,
23-
legend_max=true,
24-
legend_current=true,
25-
legend_total=false,
26-
legend_avg=true,
27-
legend_alignAsTable=true,
28-
legend_rightSide=false,
29-
).addTarget(prometheus.target(
30-
|||
31-
(
32-
sum without(instance, node) (topk(1, (kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})))
33-
-
34-
sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})))
35+
local variables = {
36+
datasource:
37+
var.datasource.new('datasource', 'prometheus')
38+
+ var.datasource.withRegex($._config.datasourceFilterRegex)
39+
+ var.datasource.generalOptions.showOnDashboard.withLabelAndValue()
40+
+ var.datasource.generalOptions.withLabel('Data source')
41+
+ {
42+
current: {
43+
selected: true,
44+
text: $._config.datasourceName,
45+
value: $._config.datasourceName,
46+
},
47+
},
48+
49+
cluster:
50+
var.query.new('cluster')
51+
+ var.query.withDatasourceFromVariable(self.datasource)
52+
+ var.query.queryTypes.withLabelValues(
53+
$._config.clusterLabel,
54+
'kubelet_volume_stats_capacity_bytes{%(kubeletSelector)s}' % $._config,
55+
)
56+
+ var.query.generalOptions.withLabel('cluster')
57+
+ var.query.refresh.onTime()
58+
+ (
59+
if $._config.showMultiCluster
60+
then var.query.generalOptions.showOnDashboard.withLabelAndValue()
61+
else var.query.generalOptions.showOnDashboard.withNothing()
62+
)
63+
+ var.query.withSort(type='alphabetical'),
64+
65+
namespace:
66+
var.query.new('namespace')
67+
+ var.query.withDatasourceFromVariable(self.datasource)
68+
+ var.query.queryTypes.withLabelValues(
69+
'namespace',
70+
'kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s}' % $._config,
3571
)
36-
||| % $._config,
37-
legendFormat='Used Space',
38-
intervalFactor=1,
39-
)).addTarget(prometheus.target(
40-
|||
41-
sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})))
42-
||| % $._config,
43-
legendFormat='Free Space',
44-
intervalFactor=1,
45-
));
72+
+ var.query.generalOptions.withLabel('Namespace')
73+
+ var.query.refresh.onTime()
74+
+ var.query.generalOptions.showOnDashboard.withLabelAndValue()
75+
+ var.query.withSort(type='alphabetical'),
4676

47-
local sizeGauge = gauge.new(
48-
'Volume Space Usage',
49-
|||
50-
max without(instance,node) (
51-
(
52-
topk(1, kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})
53-
-
54-
topk(1, kubelet_volume_stats_available_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})
77+
volume:
78+
var.query.new('volume')
79+
+ var.query.withDatasourceFromVariable(self.datasource)
80+
+ var.query.queryTypes.withLabelValues(
81+
'persistentvolumeclaim',
82+
'kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace"}' % $._config,
5583
)
56-
/
57-
topk(1, kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})
58-
* 100)
59-
||| % $._config,
60-
).withLowerBeingBetter();
84+
+ var.query.generalOptions.withLabel('PersistentVolumeClaim')
85+
+ var.query.refresh.onTime()
86+
+ var.query.generalOptions.showOnDashboard.withLabelAndValue()
87+
+ var.query.withSort(type='alphabetical'),
88+
};
6189

90+
local panels = {
91+
tsUsage:
92+
tsPanel.new('Volume Space Usage')
93+
+ tsPanel.standardOptions.withUnit('bytes')
94+
+ tsPanel.queryOptions.withTargets([
95+
prometheus.new('${datasource}', |||
96+
(
97+
sum without(instance, node) (topk(1, (kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})))
98+
-
99+
sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})))
100+
)
101+
||| % $._config)
102+
+ prometheus.withLegendFormat('Used Space'),
62103

63-
local inodesGraph = graphPanel.new(
64-
'Volume inodes Usage',
65-
datasource='$datasource',
66-
format='none',
67-
min=0,
68-
span=9,
69-
stack=true,
70-
legend_show=true,
71-
legend_values=true,
72-
legend_min=true,
73-
legend_max=true,
74-
legend_current=true,
75-
legend_total=false,
76-
legend_avg=true,
77-
legend_alignAsTable=true,
78-
legend_rightSide=false,
79-
).addTarget(prometheus.target(
80-
|||
81-
sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})))
82-
||| % $._config,
83-
legendFormat='Used inodes',
84-
intervalFactor=1,
85-
)).addTarget(prometheus.target(
86-
|||
87-
(
88-
sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})))
89-
-
90-
sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})))
104+
prometheus.new('${datasource}', |||
105+
sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})))
106+
||| % $._config)
107+
+ prometheus.withLegendFormat('Free Space'),
108+
]),
109+
gaugeUsage:
110+
gaugePanel(
111+
'Volume Space Usage',
112+
'percent',
113+
|||
114+
max without(instance,node) (
115+
(
116+
topk(1, kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})
117+
-
118+
topk(1, kubelet_volume_stats_available_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})
119+
)
120+
/
121+
topk(1, kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})
122+
* 100)
123+
||| % $._config
91124
)
92-
||| % $._config,
93-
legendFormat=' Free inodes',
94-
intervalFactor=1,
95-
));
125+
+ gauge.standardOptions.withMin(0)
126+
+ gauge.standardOptions.withMax(100)
127+
+ gauge.standardOptions.color.withMode('thresholds')
128+
+ gauge.standardOptions.thresholds.withMode('absolute')
129+
+ gauge.standardOptions.thresholds.withSteps(
130+
[
131+
gauge.thresholdStep.withColor('green')
132+
+ gauge.thresholdStep.withValue(0),
96133

97-
local inodeGauge = gauge.new(
98-
'Volume inodes Usage',
99-
|||
100-
max without(instance,node) (
101-
topk(1, kubelet_volume_stats_inodes_used{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})
102-
/
103-
topk(1, kubelet_volume_stats_inodes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})
104-
* 100)
105-
||| % $._config,
106-
).withLowerBeingBetter();
134+
gauge.thresholdStep.withColor('orange')
135+
+ gauge.thresholdStep.withValue(80),
107136

137+
gauge.thresholdStep.withColor('red')
138+
+ gauge.thresholdStep.withValue(90),
139+
]
140+
),
108141

109-
dashboard.new(
110-
'%(dashboardNamePrefix)sPersistent Volumes' % $._config.grafanaK8s,
111-
time_from='now-7d',
112-
uid=($._config.grafanaDashboardIDs['persistentvolumesusage.json']),
113-
tags=($._config.grafanaK8s.dashboardTags),
114-
).addTemplate(
115-
{
116-
current: {
117-
selected: true,
118-
text: $._config.datasourceName,
119-
value: $._config.datasourceName,
120-
},
121-
hide: 0,
122-
label: 'Data source',
123-
name: 'datasource',
124-
options: [],
125-
query: 'prometheus',
126-
refresh: 1,
127-
regex: $._config.datasourceFilterRegex,
128-
type: 'datasource',
129-
},
130-
)
131-
.addTemplate(
132-
template.new(
133-
'cluster',
134-
'$datasource',
135-
'label_values(kubelet_volume_stats_capacity_bytes{%(kubeletSelector)s}, %(clusterLabel)s)' % $._config,
136-
label='cluster',
137-
refresh='time',
138-
hide=if $._config.showMultiCluster then '' else 'variable',
139-
sort=1,
140-
)
141-
)
142-
.addTemplate(
143-
template.new(
144-
'namespace',
145-
'$datasource',
146-
'label_values(kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s}, namespace)' % $._config,
147-
label='Namespace',
148-
refresh='time',
149-
sort=1,
150-
)
151-
)
152-
.addTemplate(
153-
template.new(
154-
'volume',
155-
'$datasource',
156-
'label_values(kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace"}, persistentvolumeclaim)' % $._config,
157-
label='PersistentVolumeClaim',
158-
refresh='time',
159-
sort=1,
160-
)
161-
)
162-
.addRow(
163-
row.new()
164-
.addPanel(sizeGraph)
165-
.addPanel(sizeGauge)
166-
)
167-
.addRow(
168-
row.new()
169-
.addPanel(inodesGraph)
170-
.addPanel(inodeGauge)
171-
),
142+
tsInodes:
143+
tsPanel.new('Volume inodes Usage')
144+
+ tsPanel.standardOptions.withUnit('none')
145+
+ tsPanel.queryOptions.withTargets([
146+
prometheus.new('${datasource}', 'sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})))' % $._config)
147+
+ prometheus.withLegendFormat('Used inodes'),
148+
149+
prometheus.new('${datasource}', |||
150+
(
151+
sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})))
152+
-
153+
sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})))
154+
)
155+
||| % $._config)
156+
+ prometheus.withLegendFormat('Free inodes'),
157+
]),
158+
gaugeInodes:
159+
gaugePanel(
160+
'Volume inodes Usage',
161+
'percent',
162+
|||
163+
max without(instance,node) (
164+
topk(1, kubelet_volume_stats_inodes_used{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})
165+
/
166+
topk(1, kubelet_volume_stats_inodes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})
167+
* 100)
168+
||| % $._config
169+
)
170+
+ gauge.standardOptions.withMin(0)
171+
+ gauge.standardOptions.withMax(100)
172+
+ gauge.standardOptions.color.withMode('thresholds')
173+
+ gauge.standardOptions.thresholds.withMode('absolute')
174+
+ gauge.standardOptions.thresholds.withSteps(
175+
[
176+
gauge.thresholdStep.withColor('green')
177+
+ gauge.thresholdStep.withValue(0),
178+
179+
gauge.thresholdStep.withColor('orange')
180+
+ gauge.thresholdStep.withValue(80),
181+
182+
gauge.thresholdStep.withColor('red')
183+
+ gauge.thresholdStep.withValue(90),
184+
]
185+
),
186+
};
187+
188+
g.dashboard.new('%(dashboardNamePrefix)sPersistent Volumes' % $._config.grafanaK8s)
189+
+ g.dashboard.withUid($._config.grafanaDashboardIDs['persistentvolumesusage.json'])
190+
+ g.dashboard.withTags($._config.grafanaK8s.dashboardTags)
191+
+ g.dashboard.withEditable(false)
192+
+ g.dashboard.time.withFrom('now-1h')
193+
+ g.dashboard.time.withTo('now')
194+
+ g.dashboard.withRefresh($._config.grafanaK8s.refresh)
195+
+ g.dashboard.withVariables([variables.datasource, variables.cluster, variables.namespace, variables.volume])
196+
+ g.dashboard.withPanels([
197+
panels.tsUsage { gridPos+: { w: 18, h: 7, y: 0 } },
198+
panels.gaugeUsage { gridPos+: { w: 6, h: 7, x: 18, y: 0 } },
199+
panels.tsInodes { gridPos+: { w: 18, h: 7, y: 7 } },
200+
panels.gaugeInodes { gridPos+: { w: 6, h: 7, x: 18, y: 7 } },
201+
]),
172202
},
173203
}

0 commit comments

Comments
 (0)