Skip to content

Commit 525c48c

Browse files
authored
Merge pull request #135 from yuvipanda/homedirs
Add homedirectory reporting grafana dashboard
2 parents 9fa4891 + af69423 commit 525c48c

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

dashboards/homedirs.jsonnet

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#!/usr/bin/env -S jsonnet -J ../vendor
2+
local grafonnet = import 'grafonnet/main.libsonnet';
3+
local dashboard = grafonnet.dashboard;
4+
local prometheus = grafonnet.query.prometheus;
5+
local table = grafonnet.panel.table;
6+
7+
local common = import './common.libsonnet';
8+
9+
local homedirUsage =
10+
table.new('Home directory usage')
11+
+ table.panelOptions.withDescription(
12+
|||
13+
Home directory usage by various users on the hub.
14+
15+
Requires an installation of https://github.com/yuvipanda/prometheus-dirsize-exporter to work.
16+
If this table is empty, your infrastructure administrator needs to deploy that exporter correctly.
17+
|||
18+
)
19+
+ table.queryOptions.withTargets([
20+
// Last Modified
21+
prometheus.new(
22+
'$PROMETHEUS_DS',
23+
|||
24+
min(dirsize_latest_mtime{namespace=~"$hub"}) by (directory) * 1000
25+
|||
26+
)
27+
+ prometheus.withInstant(true) // Only fetch latest value
28+
+ prometheus.withFormat('table')
29+
,
30+
// Total Size
31+
prometheus.new(
32+
'$PROMETHEUS_DS',
33+
|||
34+
max(dirsize_total_size_bytes{namespace=~"$hub"}) by (directory)
35+
|||
36+
)
37+
+ prometheus.withInstant(true)
38+
+ prometheus.withFormat('table'),
39+
// % of total usage
40+
prometheus.new(
41+
'$PROMETHEUS_DS',
42+
|||
43+
max(dirsize_total_size_bytes{namespace=~"$hub"}) by (directory)
44+
/
45+
ignoring (directory) group_left sum(dirsize_total_size_bytes{namespace=~"$hub"})
46+
|||
47+
)
48+
+ prometheus.withInstant(true)
49+
+ prometheus.withFormat('table'),
50+
// Total number of files
51+
prometheus.new(
52+
'$PROMETHEUS_DS',
53+
|||
54+
max(dirsize_entries_count{namespace=~"$hub"}) by (directory)
55+
|||
56+
)
57+
+ prometheus.withInstant(true)
58+
+ prometheus.withFormat('table'),
59+
])
60+
// Transform table from multiple series with same key to one unified table with shared key 'directory'
61+
+ table.queryOptions.withTransformations([
62+
table.queryOptions.transformation.withId('joinByField')
63+
+ table.queryOptions.transformation.withOptions({
64+
byField: 'directory',
65+
mode: 'outer',
66+
}),
67+
68+
table.queryOptions.transformation.withId('organize')
69+
+ table.queryOptions.transformation.withOptions({
70+
// Grafana adds an individual 'Time #N' column for each timeseries we get.
71+
// They all display the same time. We don't care about time *at all*, since
72+
// all these are instant data query targets that only display latest
73+
// values. So we hide all the time values.
74+
excludeByName: {
75+
'Time 1': true,
76+
'Time 2': true,
77+
'Time 3': true,
78+
'Time 4': true,
79+
},
80+
// Tables do not use the legend keys, and show Value #N for each Time #N. We
81+
// explicitly rename these here. This depends on the ordering of these series
82+
// above, so if the ordering changes, so must this.
83+
renameByName: {
84+
'Value #A': 'Last Modified',
85+
'Value #B': 'Size',
86+
'Value #C': '% of total space usage',
87+
'Value #D': 'Number of Entries',
88+
},
89+
}),
90+
])
91+
+ {
92+
fieldConfig: {
93+
// Set units for all the columns. These can not be set elsewhere for tables
94+
overrides: [
95+
{
96+
matcher: {
97+
id: 'byName',
98+
// This is name provided by the `renameByName` transform
99+
options: 'Size',
100+
},
101+
properties: [
102+
{
103+
id: 'unit',
104+
value: 'bytes',
105+
},
106+
],
107+
},
108+
{
109+
matcher: {
110+
id: 'byName',
111+
// This is name provided by the `renameByName` transform
112+
options: 'Last Modified',
113+
},
114+
properties: [
115+
{
116+
id: 'unit',
117+
value: 'dateTimeFromNow',
118+
},
119+
],
120+
},
121+
{
122+
matcher: {
123+
id: 'byName',
124+
// This is name provided by the `renameByName` transform
125+
options: 'Number of Entries',
126+
},
127+
properties: [
128+
{
129+
id: 'unit',
130+
value: 'short',
131+
},
132+
],
133+
},
134+
{
135+
matcher: {
136+
id: 'byName',
137+
// This is name provided by the `renameByName` transform
138+
options: '% of total space usage',
139+
},
140+
properties: [
141+
{
142+
id: 'unit',
143+
value: 'percentunit',
144+
},
145+
],
146+
},
147+
],
148+
},
149+
};
150+
151+
dashboard.new('Home Directory Usage Dashboard')
152+
+ dashboard.withTags(['jupyterhub'])
153+
+ dashboard.withEditable(true)
154+
+ dashboard.withVariables([
155+
common.variables.prometheus,
156+
common.variables.hub,
157+
])
158+
+ dashboard.withPanels(
159+
grafonnet.util.grid.makeGrid([
160+
homedirUsage,
161+
], panelWidth=24, panelHeight=24)
162+
)

docs/tutorials/deploy.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ spec:
221221

222222
You will likely only need to adjust the `claimName` above to use this example.
223223

224+
This is required for the "Home directory usage" dashboard.
225+
224226
## Deploy the dashbaords
225227

226228
There's a helper `deploy.py` script that can deploy the dashboards to any grafana installation.

0 commit comments

Comments
 (0)