diff --git a/README.md b/README.md index 383a6a2..a8293f3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # docker-speedtest-grafana -![](https://i.imgur.com/cvfhIDH.png) +![](https://i.imgur.com/z3glk2W.png) Docker setup consisting out of Grafana incl. a pre-configured dashboard, InfluxDB and a [speedtest.net CLI test](https://www.speedtest.net/apps/cli) runner. @@ -10,7 +10,7 @@ Docker setup consisting out of Grafana incl. a pre-configured dashboard, InfluxD 2. Clone this repository: ```shell -git clone https://github.com/frdmn/docker-speedtest-grafana +git clone https://github.com/iamk3/docker-speedtest-grafana ``` 3. Create a copy of the sample `.env` file and adjust it at will: diff --git a/docker-compose.yml b/docker-compose.yml index 358d19a..5299594 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,8 @@ version: '2' services: influxdb: restart: always - image: influxdb:1.8 + image: influxdb:1.8.10 + container_name: docker-speedtest-grafana_influxdb ports: - "8086:8086" volumes: @@ -15,7 +16,8 @@ services: grafana: restart: always - image: grafana/grafana:6.7.2 + image: grafana/grafana:8.2.6 + container_name: docker-speedtest-grafana_grafana volumes: - "./docker/grafana/provisioning:/etc/grafana/provisioning" ports: @@ -29,8 +31,8 @@ services: speedtest: restart: always - image: frdmn/speedtest-grafana:latest - container_name: speedtest + image: iamk3/docker-speedtest-grafana:latest + container_name: docker-speedtest-grafana_speedtest environment: - "SPEEDTEST_INTERVAL=${SPEEDTEST_SPEEDTEST_INTERVAL}" - "SPEEDTEST_HOST=${SPEEDTEST_HOST}" diff --git a/docker/grafana/provisioning/dashboards/speedtest.json b/docker/grafana/provisioning/dashboards/speedtest.json index ab78e0a..90ddc38 100644 --- a/docker/grafana/provisioning/dashboards/speedtest.json +++ b/docker/grafana/provisioning/dashboards/speedtest.json @@ -9,20 +9,55 @@ "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, "type": "dashboard" } ] }, "description": "Display speedtest.net results (ping, upload and download speed)", "editable": true, + "fiscalYearStartMonth": 0, "gnetId": null, "graphTooltip": 2, - "iteration": 1587492187733, + "id": 1, + "iteration": 1686685001779, "links": [], + "liveNow": false, "panels": [ { "cacheTimeout": null, "datasource": "InfluxDB", + "fieldConfig": { + "defaults": { + "mappings": [], + "max": 250, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "#EAB839", + "value": 100 + }, + { + "color": "dark-green", + "value": 200 + } + ] + }, + "unit": "Mbits" + }, + "overrides": [] + }, "gridPos": { "h": 8, "w": 8, @@ -33,42 +68,19 @@ "id": 10, "links": [], "options": { - "fieldOptions": { + "orientation": "horizontal", + "reduceOptions": { "calcs": [ "mean" ], - "defaults": { - "mappings": [], - "max": 250, - "min": 0, - "nullValueMode": "connected", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "dark-red", - "value": null - }, - { - "color": "#EAB839", - "value": 100 - }, - { - "color": "dark-green", - "value": 200 - } - ] - }, - "unit": "Mbits" - }, - "overrides": [], + "fields": "", "values": false }, - "orientation": "horizontal", "showThresholdLabels": true, - "showThresholdMarkers": true + "showThresholdMarkers": true, + "text": {} }, - "pluginVersion": "6.7.2", + "pluginVersion": "8.2.6", "repeat": null, "repeatDirection": "h", "targets": [ @@ -128,6 +140,32 @@ { "cacheTimeout": null, "datasource": "InfluxDB", + "fieldConfig": { + "defaults": { + "mappings": [], + "max": 50, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "semi-dark-red", + "value": null + }, + { + "color": "#EAB839", + "value": 17.5 + }, + { + "color": "semi-dark-green", + "value": 35 + } + ] + }, + "unit": "Mbits" + }, + "overrides": [] + }, "gridPos": { "h": 8, "w": 8, @@ -137,42 +175,19 @@ "id": 8, "links": [], "options": { - "fieldOptions": { + "orientation": "horizontal", + "reduceOptions": { "calcs": [ "mean" ], - "defaults": { - "mappings": [], - "max": 50, - "min": 0, - "nullValueMode": "connected", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "semi-dark-red", - "value": null - }, - { - "color": "#EAB839", - "value": 17.5 - }, - { - "color": "semi-dark-green", - "value": 35 - } - ] - }, - "unit": "Mbits" - }, - "overrides": [], + "fields": "", "values": false }, - "orientation": "horizontal", "showThresholdLabels": true, - "showThresholdMarkers": true + "showThresholdMarkers": true, + "text": {} }, - "pluginVersion": "6.7.2", + "pluginVersion": "8.2.6", "targets": [ { "$$hashKey": "object:187", @@ -230,9 +245,29 @@ { "cacheTimeout": null, "datasource": "InfluxDB", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 30 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, "gridPos": { "h": 8, - "w": 8, + "w": 4, "x": 16, "y": 0 }, @@ -240,36 +275,20 @@ "links": [], "options": { "colorMode": "value", - "fieldOptions": { + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { "calcs": [ "mean" ], - "defaults": { - "mappings": [], - "nullValueMode": "connected", - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 30 - } - ] - }, - "unit": "ms" - }, - "overrides": [], + "fields": "", "values": false }, - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal" + "text": {}, + "textMode": "auto" }, - "pluginVersion": "6.7.2", + "pluginVersion": "8.2.6", "targets": [ { "$$hashKey": "object:187", @@ -324,12 +343,119 @@ "title": "Average ping latency / week", "type": "stat" }, + { + "cacheTimeout": null, + "datasource": "InfluxDB", + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 30 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 4, + "x": 20, + "y": 0 + }, + "id": 14, + "links": [], + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.2.6", + "targets": [ + { + "$$hashKey": "object:187", + "alias": "Jitter", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "hide": false, + "measurement": "jitter", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"download\" WHERE $timeFilter GROUP BY time($__interval) fill(null)", + "rawQuery": false, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "timeFrom": "1w", + "timeShift": null, + "title": "Average Jitter latency / week", + "type": "stat" + }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": "InfluxDB", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, "fill": 1, "fillGradient": 0, "gridPos": { @@ -355,9 +481,10 @@ "links": [], "nullPointMode": "connected", "options": { - "dataLinks": [] + "alertThreshold": true }, "percentage": false, + "pluginVersion": "8.2.6", "pointradius": 5, "points": false, "renderer": "flot", @@ -518,6 +645,12 @@ "dashLength": 10, "dashes": false, "datasource": "InfluxDB", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, "fill": 1, "fillGradient": 0, "gridPos": { @@ -543,9 +676,10 @@ "links": [], "nullPointMode": "connected", "options": { - "dataLinks": [] + "alertThreshold": true }, "percentage": false, + "pluginVersion": "8.2.6", "pointradius": 5, "points": false, "renderer": "flot", @@ -643,9 +777,148 @@ "align": false, "alignLevel": null } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "InfluxDB", + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 24 + }, + "hiddenSeries": false, + "id": 13, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.2.6", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "$$hashKey": "object:256", + "alias": "Jitter", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "jitter", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"ping\" WHERE $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": false, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Jitter", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:318", + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:319", + "format": "Mbits", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } } ], - "schemaVersion": 22, + "schemaVersion": 32, "style": "dark", "tags": [], "templating": { @@ -653,15 +926,16 @@ { "allValue": null, "current": { - "tags": [], - "text": "tatooine", - "value": "tatooine" + "selected": false, + "text": "local", + "value": "local" }, "datasource": "InfluxDB", "definition": "show tag values from download with key=\"host\"", + "description": null, + "error": null, "hide": 0, "includeAll": false, - "index": -1, "label": null, "multi": false, "name": "host", @@ -672,7 +946,6 @@ "skipUrlSync": false, "sort": 0, "tagValuesQuery": "", - "tags": [], "tagsQuery": "", "type": "query", "useTags": false @@ -711,8 +984,5 @@ "timezone": "", "title": "Speedtest results", "uid": "0A6hxROiz", - "variables": { - "list": [] - }, - "version": 0 + "version": 4 } \ No newline at end of file diff --git a/docker/speedtest/Dockerfile b/docker/speedtest/Dockerfile index 9c259b5..c955927 100644 --- a/docker/speedtest/Dockerfile +++ b/docker/speedtest/Dockerfile @@ -1,10 +1,9 @@ -FROM debian:10-slim AS get-speedtest - -RUN apt-get update && apt-get install gnupg1 apt-transport-https dirmngr lsb-release -y -RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 379CE192D401AB61 -RUN echo "deb https://ookla.bintray.com/debian $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/speedtest.list +FROM debian:11-slim AS get-speedtest +RUN apt-get update && apt-get install -y curl gnupg apt-transport-https dirmngr lsb-release +RUN apt-get install -y debian-archive-keyring &> /dev/null +RUN curl -s https://packagecloud.io/install/repositories/ookla/speedtest-cli/script.deb.sh | bash RUN apt-get update -RUN apt-get install speedtest +RUN apt-get install -y speedtest FROM alpine as install-dependencies RUN apk add --no-cache npm @@ -14,7 +13,6 @@ RUN npm ci FROM alpine as prod-stage RUN apk add --no-cache nodejs -LABEL maintainer="Jonas Friedmann " WORKDIR /usr/src/app diff --git a/docker/speedtest/index.js b/docker/speedtest/index.js index 41bc124..f6bb58d 100644 --- a/docker/speedtest/index.js +++ b/docker/speedtest/index.js @@ -8,6 +8,7 @@ process.env.INFLUXDB_USERNAME = (process.env.INFLUXDB_USERNAME) ? process.env.IN process.env.INFLUXDB_PASSWORD = (process.env.INFLUXDB_PASSWORD) ? process.env.INFLUXDB_PASSWORD : 'root'; process.env.SPEEDTEST_HOST = (process.env.SPEEDTEST_HOST) ? process.env.SPEEDTEST_HOST : 'local'; process.env.SPEEDTEST_INTERVAL = (process.env.SPEEDTEST_INTERVAL) ? process.env.SPEEDTEST_INTERVAL : 3600; +process.env.SPEEDTEST_SERVER = (process.env.SPEEDTEST_SERVER); const bitToMbps = bit => (bit / 1000 / 1000) * 8; @@ -24,7 +25,8 @@ const getSpeedMetrics = async () => { return { upload: bitToMbps(result.upload.bandwidth), download: bitToMbps(result.download.bandwidth), - ping: result.ping.latency + ping: result.ping.latency, + jitter: result.ping.jitter }; }; @@ -51,7 +53,7 @@ const pushToInflux = async (influx, metrics) => { log("Starting speedtest..."); const speedMetrics = await getSpeedMetrics(); log( - `Speedtest results - Download: ${speedMetrics.download}, Upload: ${speedMetrics.upload}, Ping: ${speedMetrics.ping}` + `Speedtest results - Download: ${speedMetrics.download}, Upload: ${speedMetrics.upload}, Ping: ${speedMetrics.ping}, Jitter: ${speedMetrics.jitter}` ); await pushToInflux(influx, speedMetrics);