diff --git a/README.md b/README.md index 2e15065..170c6ea 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ via code. This can then be deployed on any Grafana instance! ## Deployment -There's a helper `deploy.py` script that can deploy the dashboard to any grafana installation. +There's a helper `deploy.py` script that can deploy the dashboards to any grafana installation. ```bash export GRAFANA_TOKEN=" @@ -48,6 +48,15 @@ export GRAFANA_TOKEN=" This creates a folder called 'JupyterHub Default Dashboards' in your grafana, and adds a couple of dashboards to it. +If your Grafana deployment supports more than one datasource, then apart from the default dashboards in the [`dashboards` directory](https://github.com/jupyterhub/grafana-dashboards/tree/main/dashboards), you should also consider deploying apart the dashboards in [`global-dashboards` directory](https://github.com/jupyterhub/grafana-dashboards/tree/main/global-dashboards). + +```bash +export GRAFANA_TOKEN=" +./deploy.py --dashboards-dir global-dashboards +``` + +The gloabal dashboards will use the list of available dashboards in your Grafana provided to them and will build dashboards across all of them. + **NOTE: ANY CHANGES YOU MAKE VIA THE GRAFANA UI WILL BE OVERWRITTEN NEXT TIME YOU RUN deploy.bash. TO MAKE CHANGES, EDIT THE JSONNET FILE AND DEPLOY AGAIN** diff --git a/deploy.py b/deploy.py index 2aa8a2c..f20a7ff 100755 --- a/deploy.py +++ b/deploy.py @@ -43,11 +43,19 @@ def ensure_folder(name, uid, api): -def build_dashboard(dashboard_path): - return json.loads(subprocess.check_output([ - 'jsonnet', '-J', 'vendor', - dashboard_path - ]).decode()) +def build_dashboard(dashboard_path, api, global_dash=False): + + datasources = api("/datasources") + datasources_names = [ds["name"] for ds in datasources] + + # We pass the list of all datasources because the global dashboards + # use this information to show info about all datasources in the same panel + return json.loads(subprocess.check_output( + [ + "jsonnet", "-J", "vendor", dashboard_path, + "--tla-code", f"datasources={datasources_names}" + ] + ).decode()) def layout_dashboard(dashboard): @@ -80,8 +88,12 @@ def layout_dashboard(dashboard): return dashboard -def deploy_dashboard(dashboard_path, folder_uid, api): - db = build_dashboard(dashboard_path) +def deploy_dashboard(dashboard_path, folder_uid, api, global_dash=False): + db = build_dashboard(dashboard_path, api, global_dash) + + if not db: + return + db = layout_dashboard(db) db = populate_template_variables(api, db) diff --git a/global-dashboards/README.md b/global-dashboards/README.md new file mode 100644 index 0000000..d318d65 --- /dev/null +++ b/global-dashboards/README.md @@ -0,0 +1,3 @@ +# Dashboards across all datasources + +Contains "global" dashboards with useful stats computed across all datasources. \ No newline at end of file diff --git a/global-dashboards/global-usage-stats.jsonnet b/global-dashboards/global-usage-stats.jsonnet new file mode 100644 index 0000000..1794a62 --- /dev/null +++ b/global-dashboards/global-usage-stats.jsonnet @@ -0,0 +1,56 @@ +// Deploys one dashboard - "Global usage dashboard", +// with useful stats about usage across all datasources +local grafana = import '../vendor/grafonnet/grafana.libsonnet'; +local dashboard = grafana.dashboard; +local barGaugePanel = grafana.barGaugePanel; +local prometheus = grafana.prometheus; + +function(datasources) + local weeklyActiveUsers = barGaugePanel.new( + 'Active users (over 7 days)', + datasource='-- Mixed --', + thresholds=[ + { + value: 0, + color: 'green', + }, + ], + ).addTargets([ + prometheus.target( + // Removes any pods caused by stress testing + ||| + count( + sum( + min_over_time( + kube_pod_labels{ + label_app="jupyterhub", + label_component="singleuser-server", + label_hub_jupyter_org_username!~"(service|perf|hubtraf)-", + }[7d] + ) + ) by (pod) + ) + |||, + legendFormat=x, + interval='7d', + datasource=x + ) + // Create a target for each datasource + for x in datasources + ]); + + dashboard.new( + 'Global Usage Dashboard', + uid='global-usage-dashboard', + tags=['jupyterhub', 'global'], + editable=true, + time_from='now-7d', + ).addPanel( + weeklyActiveUsers, + gridPos={ + x: 0, + y: 0, + w: 25, + h: 10, + }, + )