-
Notifications
You must be signed in to change notification settings - Fork 599
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #930 from grafana/rjg/grafana11-pvusage
fix(dashboards): Port persistentvolumesusage.json dashboard to new grafonnet library
- Loading branch information
Showing
1 changed file
with
188 additions
and
158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,173 +1,203 @@ | ||
local grafana = import 'github.com/grafana/grafonnet-lib/grafonnet/grafana.libsonnet'; | ||
local dashboard = grafana.dashboard; | ||
local row = grafana.row; | ||
local prometheus = grafana.prometheus; | ||
local template = grafana.template; | ||
local graphPanel = grafana.graphPanel; | ||
local promgrafonnet = import '../lib/promgrafonnet/promgrafonnet.libsonnet'; | ||
local gauge = promgrafonnet.gauge; | ||
local g = import 'github.com/grafana/grafonnet/gen/grafonnet-latest/main.libsonnet'; | ||
local prometheus = g.query.prometheus; | ||
local gauge = g.panel.gauge; | ||
local timeSeries = g.panel.timeSeries; | ||
local var = g.dashboard.variable; | ||
|
||
{ | ||
local gaugePanel(title, unit, query) = | ||
gauge.new(title) | ||
+ gauge.standardOptions.withUnit(unit) | ||
+ gauge.queryOptions.withInterval($._config.grafanaK8s.minimumTimeInterval) | ||
+ gauge.queryOptions.withTargets([ | ||
prometheus.new('${datasource}', query) | ||
+ prometheus.withInstant(true), | ||
]), | ||
|
||
local tsPanel = | ||
timeSeries { | ||
new(title): | ||
timeSeries.new(title) | ||
+ timeSeries.options.legend.withShowLegend() | ||
+ timeSeries.options.legend.withAsTable() | ||
+ timeSeries.options.legend.withDisplayMode('table') | ||
+ timeSeries.options.legend.withPlacement('right') | ||
+ timeSeries.options.legend.withCalcs(['lastNotNull']) | ||
+ timeSeries.options.tooltip.withMode('single') | ||
+ timeSeries.fieldConfig.defaults.custom.withShowPoints('never') | ||
+ timeSeries.fieldConfig.defaults.custom.withFillOpacity(10) | ||
+ timeSeries.fieldConfig.defaults.custom.withSpanNulls(true) | ||
+ timeSeries.queryOptions.withInterval($._config.grafanaK8s.minimumTimeInterval), | ||
}, | ||
|
||
grafanaDashboards+:: { | ||
'persistentvolumesusage.json': | ||
local sizeGraph = graphPanel.new( | ||
'Volume Space Usage', | ||
datasource='$datasource', | ||
format='bytes', | ||
min=0, | ||
span=9, | ||
stack=true, | ||
legend_show=true, | ||
legend_values=true, | ||
legend_min=true, | ||
legend_max=true, | ||
legend_current=true, | ||
legend_total=false, | ||
legend_avg=true, | ||
legend_alignAsTable=true, | ||
legend_rightSide=false, | ||
).addTarget(prometheus.target( | ||
||| | ||
( | ||
sum without(instance, node) (topk(1, (kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}))) | ||
- | ||
sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}))) | ||
local variables = { | ||
datasource: | ||
var.datasource.new('datasource', 'prometheus') | ||
+ var.datasource.withRegex($._config.datasourceFilterRegex) | ||
+ var.datasource.generalOptions.showOnDashboard.withLabelAndValue() | ||
+ var.datasource.generalOptions.withLabel('Data source') | ||
+ { | ||
current: { | ||
selected: true, | ||
text: $._config.datasourceName, | ||
value: $._config.datasourceName, | ||
}, | ||
}, | ||
|
||
cluster: | ||
var.query.new('cluster') | ||
+ var.query.withDatasourceFromVariable(self.datasource) | ||
+ var.query.queryTypes.withLabelValues( | ||
$._config.clusterLabel, | ||
'kubelet_volume_stats_capacity_bytes{%(kubeletSelector)s}' % $._config, | ||
) | ||
+ var.query.generalOptions.withLabel('cluster') | ||
+ var.query.refresh.onTime() | ||
+ ( | ||
if $._config.showMultiCluster | ||
then var.query.generalOptions.showOnDashboard.withLabelAndValue() | ||
else var.query.generalOptions.showOnDashboard.withNothing() | ||
) | ||
+ var.query.withSort(type='alphabetical'), | ||
|
||
namespace: | ||
var.query.new('namespace') | ||
+ var.query.withDatasourceFromVariable(self.datasource) | ||
+ var.query.queryTypes.withLabelValues( | ||
'namespace', | ||
'kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s}' % $._config, | ||
) | ||
||| % $._config, | ||
legendFormat='Used Space', | ||
intervalFactor=1, | ||
)).addTarget(prometheus.target( | ||
||| | ||
sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}))) | ||
||| % $._config, | ||
legendFormat='Free Space', | ||
intervalFactor=1, | ||
)); | ||
+ var.query.generalOptions.withLabel('Namespace') | ||
+ var.query.refresh.onTime() | ||
+ var.query.generalOptions.showOnDashboard.withLabelAndValue() | ||
+ var.query.withSort(type='alphabetical'), | ||
|
||
local sizeGauge = gauge.new( | ||
'Volume Space Usage', | ||
||| | ||
max without(instance,node) ( | ||
( | ||
topk(1, kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}) | ||
- | ||
topk(1, kubelet_volume_stats_available_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}) | ||
volume: | ||
var.query.new('volume') | ||
+ var.query.withDatasourceFromVariable(self.datasource) | ||
+ var.query.queryTypes.withLabelValues( | ||
'persistentvolumeclaim', | ||
'kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace"}' % $._config, | ||
) | ||
/ | ||
topk(1, kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}) | ||
* 100) | ||
||| % $._config, | ||
).withLowerBeingBetter(); | ||
+ var.query.generalOptions.withLabel('PersistentVolumeClaim') | ||
+ var.query.refresh.onTime() | ||
+ var.query.generalOptions.showOnDashboard.withLabelAndValue() | ||
+ var.query.withSort(type='alphabetical'), | ||
}; | ||
|
||
local panels = { | ||
tsUsage: | ||
tsPanel.new('Volume Space Usage') | ||
+ tsPanel.standardOptions.withUnit('bytes') | ||
+ tsPanel.queryOptions.withTargets([ | ||
prometheus.new('${datasource}', ||| | ||
( | ||
sum without(instance, node) (topk(1, (kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}))) | ||
- | ||
sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}))) | ||
) | ||
||| % $._config) | ||
+ prometheus.withLegendFormat('Used Space'), | ||
|
||
local inodesGraph = graphPanel.new( | ||
'Volume inodes Usage', | ||
datasource='$datasource', | ||
format='none', | ||
min=0, | ||
span=9, | ||
stack=true, | ||
legend_show=true, | ||
legend_values=true, | ||
legend_min=true, | ||
legend_max=true, | ||
legend_current=true, | ||
legend_total=false, | ||
legend_avg=true, | ||
legend_alignAsTable=true, | ||
legend_rightSide=false, | ||
).addTarget(prometheus.target( | ||
||| | ||
sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}))) | ||
||| % $._config, | ||
legendFormat='Used inodes', | ||
intervalFactor=1, | ||
)).addTarget(prometheus.target( | ||
||| | ||
( | ||
sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}))) | ||
- | ||
sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}))) | ||
prometheus.new('${datasource}', ||| | ||
sum without(instance, node) (topk(1, (kubelet_volume_stats_available_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}))) | ||
||| % $._config) | ||
+ prometheus.withLegendFormat('Free Space'), | ||
]), | ||
gaugeUsage: | ||
gaugePanel( | ||
'Volume Space Usage', | ||
'percent', | ||
||| | ||
max without(instance,node) ( | ||
( | ||
topk(1, kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}) | ||
- | ||
topk(1, kubelet_volume_stats_available_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}) | ||
) | ||
/ | ||
topk(1, kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}) | ||
* 100) | ||
||| % $._config | ||
) | ||
||| % $._config, | ||
legendFormat=' Free inodes', | ||
intervalFactor=1, | ||
)); | ||
+ gauge.standardOptions.withMin(0) | ||
+ gauge.standardOptions.withMax(100) | ||
+ gauge.standardOptions.color.withMode('thresholds') | ||
+ gauge.standardOptions.thresholds.withMode('absolute') | ||
+ gauge.standardOptions.thresholds.withSteps( | ||
[ | ||
gauge.thresholdStep.withColor('green') | ||
+ gauge.thresholdStep.withValue(0), | ||
|
||
local inodeGauge = gauge.new( | ||
'Volume inodes Usage', | ||
||| | ||
max without(instance,node) ( | ||
topk(1, kubelet_volume_stats_inodes_used{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}) | ||
/ | ||
topk(1, kubelet_volume_stats_inodes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}) | ||
* 100) | ||
||| % $._config, | ||
).withLowerBeingBetter(); | ||
gauge.thresholdStep.withColor('orange') | ||
+ gauge.thresholdStep.withValue(80), | ||
|
||
gauge.thresholdStep.withColor('red') | ||
+ gauge.thresholdStep.withValue(90), | ||
] | ||
), | ||
|
||
dashboard.new( | ||
'%(dashboardNamePrefix)sPersistent Volumes' % $._config.grafanaK8s, | ||
time_from='now-7d', | ||
uid=($._config.grafanaDashboardIDs['persistentvolumesusage.json']), | ||
tags=($._config.grafanaK8s.dashboardTags), | ||
).addTemplate( | ||
{ | ||
current: { | ||
selected: true, | ||
text: $._config.datasourceName, | ||
value: $._config.datasourceName, | ||
}, | ||
hide: 0, | ||
label: 'Data source', | ||
name: 'datasource', | ||
options: [], | ||
query: 'prometheus', | ||
refresh: 1, | ||
regex: $._config.datasourceFilterRegex, | ||
type: 'datasource', | ||
}, | ||
) | ||
.addTemplate( | ||
template.new( | ||
'cluster', | ||
'$datasource', | ||
'label_values(kubelet_volume_stats_capacity_bytes{%(kubeletSelector)s}, %(clusterLabel)s)' % $._config, | ||
label='cluster', | ||
refresh='time', | ||
hide=if $._config.showMultiCluster then '' else 'variable', | ||
sort=1, | ||
) | ||
) | ||
.addTemplate( | ||
template.new( | ||
'namespace', | ||
'$datasource', | ||
'label_values(kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s}, namespace)' % $._config, | ||
label='Namespace', | ||
refresh='time', | ||
sort=1, | ||
) | ||
) | ||
.addTemplate( | ||
template.new( | ||
'volume', | ||
'$datasource', | ||
'label_values(kubelet_volume_stats_capacity_bytes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace"}, persistentvolumeclaim)' % $._config, | ||
label='PersistentVolumeClaim', | ||
refresh='time', | ||
sort=1, | ||
) | ||
) | ||
.addRow( | ||
row.new() | ||
.addPanel(sizeGraph) | ||
.addPanel(sizeGauge) | ||
) | ||
.addRow( | ||
row.new() | ||
.addPanel(inodesGraph) | ||
.addPanel(inodeGauge) | ||
), | ||
tsInodes: | ||
tsPanel.new('Volume inodes Usage') | ||
+ tsPanel.standardOptions.withUnit('none') | ||
+ tsPanel.queryOptions.withTargets([ | ||
prometheus.new('${datasource}', 'sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"})))' % $._config) | ||
+ prometheus.withLegendFormat('Used inodes'), | ||
|
||
prometheus.new('${datasource}', ||| | ||
( | ||
sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}))) | ||
- | ||
sum without(instance, node) (topk(1, (kubelet_volume_stats_inodes_used{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}))) | ||
) | ||
||| % $._config) | ||
+ prometheus.withLegendFormat('Free inodes'), | ||
]), | ||
gaugeInodes: | ||
gaugePanel( | ||
'Volume inodes Usage', | ||
'percent', | ||
||| | ||
max without(instance,node) ( | ||
topk(1, kubelet_volume_stats_inodes_used{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}) | ||
/ | ||
topk(1, kubelet_volume_stats_inodes{%(clusterLabel)s="$cluster", %(kubeletSelector)s, namespace="$namespace", persistentvolumeclaim="$volume"}) | ||
* 100) | ||
||| % $._config | ||
) | ||
+ gauge.standardOptions.withMin(0) | ||
+ gauge.standardOptions.withMax(100) | ||
+ gauge.standardOptions.color.withMode('thresholds') | ||
+ gauge.standardOptions.thresholds.withMode('absolute') | ||
+ gauge.standardOptions.thresholds.withSteps( | ||
[ | ||
gauge.thresholdStep.withColor('green') | ||
+ gauge.thresholdStep.withValue(0), | ||
|
||
gauge.thresholdStep.withColor('orange') | ||
+ gauge.thresholdStep.withValue(80), | ||
|
||
gauge.thresholdStep.withColor('red') | ||
+ gauge.thresholdStep.withValue(90), | ||
] | ||
), | ||
}; | ||
|
||
g.dashboard.new('%(dashboardNamePrefix)sPersistent Volumes' % $._config.grafanaK8s) | ||
+ g.dashboard.withUid($._config.grafanaDashboardIDs['persistentvolumesusage.json']) | ||
+ g.dashboard.withTags($._config.grafanaK8s.dashboardTags) | ||
+ g.dashboard.withEditable(false) | ||
+ g.dashboard.time.withFrom('now-1h') | ||
+ g.dashboard.time.withTo('now') | ||
+ g.dashboard.withRefresh($._config.grafanaK8s.refresh) | ||
+ g.dashboard.withVariables([variables.datasource, variables.cluster, variables.namespace, variables.volume]) | ||
+ g.dashboard.withPanels([ | ||
panels.tsUsage { gridPos+: { w: 18, h: 7, y: 0 } }, | ||
panels.gaugeUsage { gridPos+: { w: 6, h: 7, x: 18, y: 0 } }, | ||
panels.tsInodes { gridPos+: { w: 18, h: 7, y: 7 } }, | ||
panels.gaugeInodes { gridPos+: { w: 6, h: 7, x: 18, y: 7 } }, | ||
]), | ||
}, | ||
} |