diff --git a/examples/grafana-dashboards/Makefile b/examples/grafana-dashboards/Makefile new file mode 100644 index 0000000000..2cfa7de9d0 --- /dev/null +++ b/examples/grafana-dashboards/Makefile @@ -0,0 +1,62 @@ +# Copyright 2021 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +current_dir := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + + +# setup grafana, prometheus and the charts +setup: setup-prometheus setup-grafana install-dashboards + +# clean up the cluster +clean: clean-prometheus clean-grafana clean-dashboards + +# install prometheus in the cluster +setup-prometheus: SCRAPE_INTERVAL ?= 30s +setup-prometheus: + helm repo add prometheus-community https://prometheus-community.github.io/helm-charts + helm repo update + helm upgrade prometheus prometheus-community/prometheus --install --wait \ + --namespace metrics --create-namespace \ + --set server.global.scrape_interval=$(SCRAPE_INTERVAL) $(HELM_ARGS) + +clean-prometheus: + helm uninstall prometheus --namespace=metrics + +# install grafana in the cluster +setup-grafana: PASSWORD ?= admin +setup-grafana: + helm repo add grafana https://grafana.github.io/helm-charts + helm repo update + helm upgrade grafana grafana/grafana --install --wait \ + --namespace=metrics --create-namespace \ + --set adminPassword=$(PASSWORD) $(HELM_ARGS) -f $(current_dir)/grafana.yaml + +clean-grafana: + helm uninstall grafana --namespace=metrics + +install-dashboards: + kubectl apply -f $(current_dir)/dashboards/ + +clean-dashboards: + kubectl delete -f $(current_dir)/dashboards/ + +# portforward prometheus web ui +prometheus-portforward: DOCKER_RUN_ARGS+=--network=host +prometheus-portforward: + kubectl port-forward deployments/prometheus-server 9090 -n metrics + +# portforward grafana web ui +grafana-portforward: DOCKER_RUN_ARGS+=--network=host +grafana-portforward: + kubectl port-forward deployments/grafana 3000 -n metrics diff --git a/examples/grafana-dashboards/README.md b/examples/grafana-dashboards/README.md new file mode 100644 index 0000000000..e6fd66067a --- /dev/null +++ b/examples/grafana-dashboards/README.md @@ -0,0 +1,29 @@ +# Grafana Dashboards + +This folder provides example [Grafana][grafana] dashboards for Quilkin metrics. + +![example general dashboard](./quilkin-general.png) + +## Importing the dashboards + +If you are hosting Grafana on a Kubernetes cluster, and have the +[Sidecar for dashboard](https://github.com/grafana/helm-charts/blob/main/charts/grafana/README.md#sidecar-for-datasources) +enabled, run: + +`kubectl apply -f ./dashboards/` to apply all the ConfigMaps for the dashboards to your cluster into the `metrics` +namespace. + +If you are running Grafana in an alternative environement, copy and paste the JSON from the yaml files +into the [Import Dashboard](https://grafana.com/docs/grafana/latest/dashboards/export-import/#import-dashboard) utility. + +## Makefile for convenience + +A sample [Makefile](./Makefile) with convenience targets for installing [Prometheus](https://prometheus.io/) and +[Grafana][grafana] in a Kubernetes cluster, along with charts is also available in the [dashboards](./dashboards) +folder. + +This installs all the components in a `metrics` namespace. + +Run `make setup grafana-portforward` to install everything, and forward the Grafana service to the local port 3000. + +[grafana]: https://grafana.com/ diff --git a/examples/grafana-dashboards/dashboards/dashboard-gameservers.yaml b/examples/grafana-dashboards/dashboards/dashboard-gameservers.yaml new file mode 100644 index 0000000000..670da0f933 --- /dev/null +++ b/examples/grafana-dashboards/dashboards/dashboard-gameservers.yaml @@ -0,0 +1,593 @@ +# Copyright 2021 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# configs map used by grafana +apiVersion: v1 +kind: ConfigMap +metadata: + name: quilkin-general + namespace: metrics + labels: + grafana_dashboard: "1" +data: + dashboard-agones-gameservers.json: | + { + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "iteration": 1624403841448, + "links": [], + "panels": [ + { + "datasource": null, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 5, + "x": 0, + "y": 0 + }, + "id": 11, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.0.3", + "repeat": null, + "targets": [ + { + "exemplar": true, + "expr": "sum(increase(quilkin_session_tx_bytes_total[$interval]))", + "instant": false, + "interval": "", + "legendFormat": "Transmit", + "refId": "A" + }, + { + "exemplar": true, + "expr": "sum(increase(quilkin_session_rx_bytes_total[$interval]))", + "hide": false, + "instant": false, + "interval": "", + "legendFormat": "Receive", + "refId": "B" + } + ], + "title": "Network Traffic [$interval]", + "type": "stat" + }, + { + "datasource": null, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 20 + }, + { + "color": "red", + "value": 50 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 4, + "x": 5, + "y": 0 + }, + "id": 8, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.0.3", + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(quilkin_session_tx_errors_total[$interval]))", + "instant": true, + "interval": "", + "legendFormat": "Transmit", + "refId": "A" + }, + { + "exemplar": true, + "expr": "sum(rate(quilkin_session_rx_errors_total[$interval]))", + "hide": false, + "instant": true, + "interval": "", + "legendFormat": "Receive", + "refId": "B" + } + ], + "title": "Errors [$interval]", + "type": "stat" + }, + { + "datasource": null, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 3, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 15, + "x": 9, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "pluginVersion": "8.0.3", + "targets": [ + { + "exemplar": true, + "expr": "count(sum(quilkin_cluster_active{}) by (instance))", + "format": "time_series", + "interval": "", + "legendFormat": "instances", + "refId": "A" + }, + { + "exemplar": true, + "expr": "sum(quilkin_cluster_active_endpoints)", + "hide": false, + "interval": "", + "legendFormat": "endpoints", + "refId": "B" + }, + { + "exemplar": true, + "expr": "sum(quilkin_session_active)", + "hide": false, + "interval": "", + "legendFormat": "active_sessions", + "refId": "C" + } + ], + "title": "Quilkin Instances & Sessions", + "type": "timeseries" + }, + { + "datasource": null, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 3, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "exemplar": true, + "expr": "sum(rate(quilkin_session_tx_bytes_total[$__rate_interval]))", + "interval": "", + "legendFormat": "transmit rate", + "refId": "A" + }, + { + "exemplar": true, + "expr": "sum(rate(quilkin_session_rx_bytes_total[$__rate_interval]))", + "hide": false, + "interval": "", + "legendFormat": "receive rate", + "refId": "B" + }, + { + "exemplar": true, + "expr": "sum(rate(quilkin_proxy_packets_dropped_total[$__rate_interval]))", + "hide": false, + "interval": "", + "legendFormat": "dropped packet rate", + "refId": "C" + }, + { + "exemplar": true, + "expr": "sum(rate(quilkin_session_rx_errors_total[$__rate_interval]))", + "hide": false, + "interval": "", + "legendFormat": "receive error rate", + "refId": "D" + }, + { + "exemplar": true, + "expr": "sum(rate(quilkin_session_tx_errors_total[$__rate_interval]))", + "hide": false, + "interval": "", + "legendFormat": "transmit error rate", + "refId": "E" + } + ], + "title": "Network Traffic Rates", + "type": "timeseries" + }, + { + "datasource": null, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 3, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom" + }, + "tooltip": { + "mode": "single" + } + }, + "targets": [ + { + "exemplar": true, + "expr": " histogram_quantile(0.5,sum(rate(quilkin_session_duration_secs_bucket[$__rate_interval])) by (le))", + "interval": "", + "legendFormat": "50%", + "refId": "A" + }, + { + "exemplar": true, + "expr": " histogram_quantile(0.9,sum(rate(quilkin_session_duration_secs_bucket[$__rate_interval])) by (le))", + "hide": false, + "interval": "", + "legendFormat": "90%", + "refId": "B" + }, + { + "exemplar": true, + "expr": " histogram_quantile(0.99,sum(rate(quilkin_session_duration_secs_bucket[$__rate_interval])) by (le))", + "hide": false, + "interval": "", + "legendFormat": "99%", + "refId": "C" + } + ], + "title": "Session Length", + "type": "timeseries" + } + ], + "refresh": "10s", + "schemaVersion": 30, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "auto": false, + "auto_count": 30, + "auto_min": "10s", + "current": { + "selected": false, + "text": "30m", + "value": "30m" + }, + "description": null, + "error": null, + "hide": 0, + "label": null, + "name": "interval", + "options": [ + { + "selected": false, + "text": "1m", + "value": "1m" + }, + { + "selected": false, + "text": "10m", + "value": "10m" + }, + { + "selected": true, + "text": "30m", + "value": "30m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + }, + { + "selected": false, + "text": "6h", + "value": "6h" + }, + { + "selected": false, + "text": "12h", + "value": "12h" + }, + { + "selected": false, + "text": "1d", + "value": "1d" + }, + { + "selected": false, + "text": "7d", + "value": "7d" + }, + { + "selected": false, + "text": "14d", + "value": "14d" + }, + { + "selected": false, + "text": "30d", + "value": "30d" + } + ], + "query": "1m,10m,30m,1h,6h,12h,1d,7d,14d,30d", + "queryValue": "", + "refresh": 2, + "skipUrlSync": false, + "type": "interval" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Quilkin General Metrics", + "uid": "QAbeZjgnk", + "version": 1 + } \ No newline at end of file diff --git a/examples/grafana-dashboards/grafana.yaml b/examples/grafana-dashboards/grafana.yaml new file mode 100644 index 0000000000..9c10fe7451 --- /dev/null +++ b/examples/grafana-dashboards/grafana.yaml @@ -0,0 +1,26 @@ +# Copyright 2021 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +sidecar: + dashboards: + enabled: true +datasources: + datasources.yaml: + apiVersion: 1 + datasources: + - name: Prometheus + type: prometheus + url: http://prometheus-server.metrics.svc.cluster.local:80/ + access: proxy + isDefault: true \ No newline at end of file diff --git a/examples/grafana-dashboards/quilkin-general.png b/examples/grafana-dashboards/quilkin-general.png new file mode 100644 index 0000000000..5cae6416f2 Binary files /dev/null and b/examples/grafana-dashboards/quilkin-general.png differ