diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..11e59c4 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,12 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.2.0 # Use the ref you want to point at + hooks: + - id: trailing-whitespace + - id: detect-private-key + - id: check-symlinks + - id: check-yaml + - id: mixed-line-ending + - id: pretty-format-json + args: ["--autofix"] + - id: forbid-new-submodules diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8eb5aba --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..361f12e --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +# ISP-Checker + +`docker-compose` stack to run a set of ISP controls in a [Raspberry Pi](https://www.raspberrypi.org/). + +[![Linkedin](https://i.stack.imgur.com/gVE0j.png) LinkedIn](https://www.linkedin.com/in/fmdlc) [![GitHub](https://i.stack.imgur.com/tskMh.png) GitHub](https://github.com/fmdlc) +### Configuration + +Make sure you have [Docker-CE](https://phoenixnap.com/kb/docker-on-raspberry-pi) installed in your *Raspberry Pi*. If you don't, install it. +```bash +$ curl -fsSL https://get.docker.com -o get-docker.sh | bash - +``` + +Configure the InfluxDB credentials using Environment variables in the `./docker-compose.yaml` file. +```yaml +services: + influxdb: + container_name: influxdb + image: influxdb:latest + expose: + - 8086 + user: root + restart: on-failure + volumes: + - "influxdb-storage:/var/influxdb/data" + environment: + - INFLUXDB_DB="db1" + - INFLUXDB_ADMIN_USER="telegraf" + - INFLUXDB_ADMIN_PASSWORD="VerySecurePassword" + - INFLUXDB_READ_USER="grafana" + - INFLUXDB_READ_USER_PASSWORD="VerySecurePassword" +``` + +### Start +1. Create the Docker persistent volumes running the `./create-volumes.sh`. +2. Start the stack running `docker-compose up -d`. +3. Monitor the log status with `docker-compose logs -f`. + +### Login +1. Open your browser and point to `http://:3000/` and login with username `admin` and password `admin`. _Change it inmediately after the first login_. +2. Configure the _InfluxDB_ datasource to point to your local InfluxDB database. +3. Import the JSON Dashboard located in the `./grafana` directory. +![InfluxDB](./img/InfluxDB-config.png.png) + +## Contributing +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. + +Please make sure to update tests as appropriate. + +## License +[Apache 2](https://www.apache.org/licenses/LICENSE-2.0) diff --git a/create-volumes.sh b/create-volumes.sh new file mode 100755 index 0000000..6f0ba43 --- /dev/null +++ b/create-volumes.sh @@ -0,0 +1,6 @@ +#!/bin/bash + + docker volume create --name=influxdb-storage + docker volume create --name=grafana-storage + + exit $? diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..f40f2d9 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,52 @@ +version: "3.3" +services: + influxdb: + container_name: influxdb + image: influxdb:latest + expose: + - 8086 + user: root + restart: on-failure + volumes: + - "influxdb-storage:/var/influxdb/data" + environment: + - INFLUXDB_DB="db1" + - INFLUXDB_ADMIN_USER="root" + - INFLUXDB_ADMIN_PASSWORD="VerySecurePassword" + - INFLUXDB_READ_USER="grafana" + - INFLUXDB_READ_USER_PASSWORD="VerySecurePassword" + ports: + - 8086:8086 + telegraf: + container_name: telegraf + image: tty0/isp_telegraf:latest + user: root + restart: on-failure + volumes: + - "./telegraf/conf/telegraf.conf:/etc/telegraf/telegraf.conf:ro" + links: + - "influxdb" + depends_on: + - "influxdb" + grafana: + container_name: grafana + image: grafana/grafana:latest + environment: + - GF_INSTALL_PLUGINS=https://grafana.com/api/plugins/gowee-traceroutemap-panel/versions/0.2.3/download;gowee-traceroutemap-panel + expose: + - 3000 + ports: + - 3000:3000 + restart: on-failure + volumes: + - "grafana-storage:/var/lib/grafana" + links: + - "influxdb" + depends_on: + - "influxdb" + - "telegraf" +volumes: + grafana-storage: + external: true + influxdb-storage: + external: true diff --git a/grafana/network-dashboad.json b/grafana/network-dashboad.json new file mode 100644 index 0000000..453ca0e --- /dev/null +++ b/grafana/network-dashboad.json @@ -0,0 +1,1910 @@ +{ + "__inputs": [ + { + "description": "", + "label": "InfluxDB", + "name": "DS_INFLUXDB", + "pluginId": "influxdb", + "pluginName": "InfluxDB", + "type": "datasource" + } + ], + "__requires": [ + { + "id": "bargauge", + "name": "Bar gauge", + "type": "panel", + "version": "" + }, + { + "id": "gauge", + "name": "Gauge", + "type": "panel", + "version": "" + }, + { + "id": "gowee-traceroutemap-panel", + "name": "Traceroute Map Panel", + "type": "panel", + "version": "0.2.3" + }, + { + "id": "grafana", + "name": "Grafana", + "type": "grafana", + "version": "7.2.0" + }, + { + "id": "graph", + "name": "Graph", + "type": "panel", + "version": "" + }, + { + "id": "heatmap", + "name": "Heatmap", + "type": "panel", + "version": "" + }, + { + "id": "influxdb", + "name": "InfluxDB", + "type": "datasource", + "version": "1.0.0" + }, + { + "id": "stat", + "name": "Stat", + "type": "panel", + "version": "" + }, + { + "id": "table", + "name": "Table", + "type": "panel", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Network latencies and availability", + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "links": [], + "panels": [ + { + "datasource": "${DS_INFLUXDB}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "light-green", + "value": 1 + }, + { + "color": "semi-dark-green", + "value": 30 + }, + { + "color": "dark-green", + "value": 40 + }, + { + "color": "semi-dark-yellow", + "value": 50 + }, + { + "color": "semi-dark-orange", + "value": 60 + }, + { + "color": "dark-orange", + "value": 70 + }, + { + "color": "semi-dark-red", + "value": 80 + }, + { + "color": "dark-red", + "value": 90 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 26, + "options": { + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": true, + "showThresholdMarkers": true + }, + "pluginVersion": "7.2.0", + "targets": [ + { + "groupBy": [ + { + "params": [ + "5m" + ], + "type": "time" + }, + { + "params": [ + "previous" + ], + "type": "fill" + } + ], + "measurement": "speedtest", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "Ping" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Speedtest (Ping)", + "transparent": true, + "type": "gauge" + }, + { + "datasource": "${DS_INFLUXDB}", + "description": "Download bandwidth", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "light-red", + "value": 5 + }, + { + "color": "dark-orange", + "value": 10 + }, + { + "color": "super-light-orange", + "value": 20 + }, + { + "color": "super-light-green", + "value": 30 + }, + { + "color": "light-green", + "value": 40 + }, + { + "color": "semi-dark-green", + "value": 50 + } + ] + }, + "unit": "Mbits" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 5, + "x": 6, + "y": 0 + }, + "id": 20, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.0", + "targets": [ + { + "groupBy": [ + { + "params": [ + "5m" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "speedtest", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "Download" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + }, + { + "params": [ + " / 1000000" + ], + "type": "math" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Bandwidth (Download)", + "transparent": true, + "type": "stat" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB}", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 2, + "gridPos": { + "h": 9, + "w": 13, + "x": 11, + "y": 0 + }, + "hiddenSeries": false, + "id": 24, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.2.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "Download", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "previous" + ], + "type": "fill" + } + ], + "measurement": "speedtest", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "Download" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + }, + { + "params": [ + " / 1000000" + ], + "type": "math" + } + ] + ], + "tags": [] + }, + { + "alias": "Upload", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "previous" + ], + "type": "fill" + } + ], + "measurement": "speedtest", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "Upload" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + }, + { + "params": [ + " / 1000000" + ], + "type": "math" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Speedtest TX/RX", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transparent": true, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:401", + "format": "Mbits", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:402", + "decimals": 2, + "format": "MBs", + "label": "Download (MB/s)", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "datasource": "${DS_INFLUXDB}", + "description": "Uptime bandwidth", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "red", + "value": 0.5 + }, + { + "color": "dark-orange", + "value": 1 + }, + { + "color": "light-yellow", + "value": 2 + }, + { + "color": "super-light-green", + "value": 3 + }, + { + "color": "light-green", + "value": 4 + }, + { + "color": "semi-dark-green", + "value": 5 + }, + { + "color": "dark-green", + "value": 6 + } + ] + }, + "unit": "Mbits" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 6, + "y": 5 + }, + "id": 22, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.0", + "targets": [ + { + "groupBy": [ + { + "params": [ + "5m" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "speedtest", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "Upload" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + }, + { + "params": [ + " / 1000000" + ], + "type": "math" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Bandwidth (uptime)", + "type": "stat" + }, + { + "datasource": "${DS_INFLUXDB}", + "description": "DNS resolution average query time", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "max": 1000, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "semi-dark-green", + "value": 200 + }, + { + "color": "dark-green", + "value": 300 + }, + { + "color": "super-light-orange", + "value": 400 + }, + { + "color": "#EAB839", + "value": 500 + }, + { + "color": "light-red", + "value": 700 + }, + { + "color": "red", + "value": 900 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 11, + "x": 0, + "y": 9 + }, + "id": 6, + "options": { + "displayMode": "lcd", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "showUnfilled": true + }, + "pluginVersion": "7.2.0", + "targets": [ + { + "alias": "$tag_domain", + "groupBy": [ + { + "params": [ + "domain" + ], + "type": "tag" + } + ], + "measurement": "dns_query", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "query_time_ms" + ], + "type": "field" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "DNS AVG Query time", + "transparent": true, + "type": "bargauge" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB}", + "description": "Percentage of package lost ", + "fieldConfig": { + "defaults": { + "custom": {}, + "unit": "percent" + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 13, + "x": 11, + "y": 9 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.2.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:405" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "groupBy": [], + "measurement": "ping", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "percent_packet_loss" + ], + "type": "field" + } + ] + ], + "tags": [] + } + ], + "thresholds": [ + { + "$$hashKey": "object:387", + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 20, + "yaxis": "left" + }, + { + "$$hashKey": "object:393", + "colorMode": "warning", + "fill": true, + "line": true, + "op": "gt", + "value": 2, + "yaxis": "left" + }, + { + "$$hashKey": "object:399", + "colorMode": "ok", + "fill": false, + "line": false, + "op": "lt", + "value": 0, + "yaxis": "left" + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "ICMP Packet loss (%)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transparent": true, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:416", + "format": "percent", + "label": "Packet lost %", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:417", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB}", + "description": "HTTP GET request response time (ms)", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 18 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideEmpty": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.2.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "$tag_server", + "groupBy": [ + { + "params": [ + "server" + ], + "type": "tag" + } + ], + "measurement": "http_response", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "response_time" + ], + "type": "field" + } + ] + ], + "tags": [ + { + "key": "method", + "operator": "=", + "value": "GET" + } + ] + } + ], + "thresholds": [ + { + "$$hashKey": "object:1216", + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 10, + "yaxis": "left" + }, + { + "$$hashKey": "object:1222", + "colorMode": "warning", + "fill": false, + "line": false, + "op": "gt", + "value": 5, + "yaxis": "left" + }, + { + "$$hashKey": "object:1228", + "colorMode": "ok", + "fill": true, + "line": true, + "op": "lt", + "value": 2, + "yaxis": "left" + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "HTTP GET response time (ms)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transparent": true, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1019", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:1020", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB}", + "description": "ICMP echo requests average latency.", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 2, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 28 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.2.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "$tag_url", + "groupBy": [ + { + "params": [ + "url" + ], + "type": "tag" + } + ], + "measurement": "ping", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "average_response_ms" + ], + "type": "field" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [ + { + "$$hashKey": "object:150", + "colorMode": "background6", + "fill": true, + "fillColor": "rgba(234, 112, 112, 0.12)", + "line": false, + "lineColor": "rgba(237, 46, 24, 0.60)", + "op": "time" + } + ], + "timeShift": null, + "title": "ICMP average response", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "transparent": true, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:100", + "format": "short", + "label": "average (ms)", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:101", + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "datasource": "${DS_INFLUXDB}", + "description": "Average response time for External Ping in ms.", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "max": 700, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "semi-dark-green", + "value": 30 + }, + { + "color": "#EAB839", + "value": 50 + }, + { + "color": "semi-dark-orange", + "value": 70 + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 6, + "x": 2, + "y": 38 + }, + "id": 4, + "options": { + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "/^ping\\.average_response_ms$/", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "7.2.0", + "targets": [ + { + "groupBy": [], + "hide": false, + "limit": "", + "measurement": "ping", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT \"average_response_ms\" FROM \"ping\" ", + "rawQuery": false, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "average_response_ms" + ], + "type": "field" + } + ] + ], + "tags": [ + { + "key": "url", + "operator": "=", + "value": "4.2.2.1" + } + ] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Ping AVG response time (external)", + "transparent": true, + "type": "gauge" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 10, + "w": 15, + "x": 9, + "y": 38 + }, + "hiddenSeries": false, + "id": 16, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": false, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "alertThreshold": false + }, + "percentage": false, + "pluginVersion": "7.2.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Tx (Bytes)", + "groupBy": [ + { + "params": [ + "1m" + ], + "type": "time" + } + ], + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "bytes_sent" + ], + "type": "field" + }, + { + "params": [], + "type": "integral" + } + ] + ], + "tags": [ + { + "key": "interface", + "operator": "=", + "value": "eth0" + } + ] + }, + { + "alias": "Rx (Bytes)", + "groupBy": [ + { + "params": [ + "1m" + ], + "type": "time" + } + ], + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "bytes_recv" + ], + "type": "field" + }, + { + "params": [], + "type": "integral" + } + ] + ], + "tags": [ + { + "key": "interface", + "operator": "=", + "value": "eth0" + } + ] + }, + { + "alias": "Drop In", + "groupBy": [ + { + "params": [ + "1m" + ], + "type": "time" + } + ], + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "drop_in" + ], + "type": "field" + }, + { + "params": [], + "type": "integral" + } + ] + ], + "tags": [ + { + "key": "interface", + "operator": "=", + "value": "eth0" + } + ] + }, + { + "alias": "Drop Out", + "groupBy": [ + { + "params": [ + "1m" + ], + "type": "time" + } + ], + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "refId": "D", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "drop_out" + ], + "type": "field" + }, + { + "params": [], + "type": "integral" + } + ] + ], + "tags": [ + { + "key": "interface", + "operator": "=", + "value": "eth0" + } + ] + } + ], + "thresholds": [ + { + "$$hashKey": "object:1747", + "colorMode": "warning", + "fill": true, + "line": true, + "op": "lt", + "value": 0, + "yaxis": "left" + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Interface: eth0 Tx/Rx", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "transparent": true, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "series", + "name": null, + "show": true, + "values": [ + "total" + ] + }, + "yaxes": [ + { + "$$hashKey": "object:1468", + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:1469", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cards": { + "cardPadding": null, + "cardRound": null + }, + "color": { + "cardColor": "#b4ff00", + "colorScale": "sqrt", + "colorScheme": "interpolateCool", + "exponent": 0.5, + "max": null, + "min": null, + "mode": "spectrum" + }, + "dataFormat": "timeseries", + "datasource": "${DS_INFLUXDB}", + "description": "Standard Deviation (ms) heatmap", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 12, + "x": 0, + "y": 48 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 10, + "legend": { + "show": true + }, + "pluginVersion": "7.2.0", + "reverseYBuckets": false, + "targets": [ + { + "groupBy": [ + { + "params": [ + "url" + ], + "type": "tag" + } + ], + "measurement": "ping", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "standard_deviation_ms" + ], + "type": "field" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Ping Standard Deviation (ms)", + "tooltip": { + "show": true, + "showHistogram": true + }, + "tooltipDecimals": 2, + "transparent": true, + "type": "heatmap", + "xAxis": { + "show": true + }, + "xBucketNumber": null, + "xBucketSize": "10s", + "yAxis": { + "decimals": 2, + "format": "none", + "logBase": 1, + "max": "3", + "min": "-0.2", + "show": true, + "splitFactor": null + }, + "yBucketBound": "auto", + "yBucketNumber": 10, + "yBucketSize": null + }, + { + "datasource": "${DS_INFLUXDB}", + "fieldConfig": { + "defaults": { + "custom": { + "align": null, + "displayMode": "color-text", + "filterable": true + }, + "mappings": [], + "max": 500, + "min": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "super-light-blue", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.width", + "value": 230 + }, + { + "id": "custom.displayMode", + "value": "color-text" + }, + { + "id": "unit", + "value": "dateTimeAsLocal" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "server" + }, + "properties": [ + { + "id": "custom.width", + "value": 617 + }, + { + "id": "mappings", + "value": [] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "last" + }, + "properties": [ + { + "id": "custom.width", + "value": 145 + }, + { + "id": "displayName", + "value": "Response code" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "light-red", + "value": null + }, + { + "color": "light-green", + "value": 100 + }, + { + "color": "light-green", + "value": 200 + }, + { + "color": "semi-dark-green", + "value": 300 + }, + { + "color": "super-light-yellow", + "value": 400 + }, + { + "color": "super-light-red", + "value": 500 + } + ] + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Response code" + }, + "properties": [ + { + "id": "custom.width", + "value": 385 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 48 + }, + "id": 14, + "options": { + "showHeader": true, + "sortBy": [ + { + "desc": false, + "displayName": "Time" + } + ] + }, + "pluginVersion": "7.2.0", + "targets": [ + { + "alias": "$tag_server", + "groupBy": [ + { + "params": [ + "server" + ], + "type": "tag" + } + ], + "measurement": "http_response", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "table", + "select": [ + [ + { + "params": [ + "http_response_code" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "HTTP response codes", + "type": "table" + }, + { + "datasource": "${DS_INFLUXDB}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 24, + "x": 0, + "y": 59 + }, + "id": 18, + "options": { + "geoIPProviders": { + "active": "ipsb", + "custom-api": { + "kind": "custom-api" + }, + "custom-function": { + "kind": "custom-function" + }, + "ipinfo": { + "kind": "ipinfo" + }, + "ipsb": { + "kind": "ipsb" + } + }, + "hostnameLabelWidth": 8, + "longitude360": false, + "mapClusterRadius": 15, + "simplifyHostname": false + }, + "pluginVersion": "7.2.0", + "targets": [ + { + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(avg) as rtt, mean(loss) as loss from mtr WHERE now() - 5m < time group by hop, ip, host, dest\n", + "rawQuery": true, + "refId": "A", + "resultFormat": "table", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "TraceRoute", + "transparent": true, + "type": "gowee-traceroutemap-panel" + } + ], + "refresh": "5s", + "schemaVersion": 26, + "style": "dark", + "tags": [ + "networking" + ], + "templating": { + "list": [] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Network", + "uid": "zLFZEuWRk", + "version": 6 +} diff --git a/img/InfluxDB-config.png b/img/InfluxDB-config.png new file mode 100644 index 0000000..6c5513c Binary files /dev/null and b/img/InfluxDB-config.png differ diff --git a/telegraf/Dockerfile b/telegraf/Dockerfile new file mode 100644 index 0000000..456e55e --- /dev/null +++ b/telegraf/Dockerfile @@ -0,0 +1,17 @@ +FROM telegraf:latest + +LABEL mantainer="Facu de la Cruz" +LABEL PROJECT="ISP_monitor" + +COPY ./bin/entrypoint.sh /entrypoint.sh + +RUN apt-get update && apt-get install -y --no-install-recommends \ + mtr \ + speedtest-cli && \ + rm -rf /var/lib/apt/lists/* + +EXPOSE 8125/udp 8092/udp 8094 + +ENTRYPOINT ["/entrypoint.sh"] + +CMD ["telegraf"] diff --git a/telegraf/bin/entrypoint.sh b/telegraf/bin/entrypoint.sh new file mode 100755 index 0000000..6e7580b --- /dev/null +++ b/telegraf/bin/entrypoint.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +if [ "${1:0:1}" = '-' ]; then + set -- telegraf "$@" +fi + +exec "$@" diff --git a/telegraf/conf/telegraf.conf b/telegraf/conf/telegraf.conf new file mode 100644 index 0000000..8d63b43 --- /dev/null +++ b/telegraf/conf/telegraf.conf @@ -0,0 +1,110 @@ +[global_tags] + +[agent] + interval = "10s" + round_interval = true + metric_batch_size = 1000 + metric_buffer_limit = 10000 + collection_jitter = "0s" + flush_interval = "10s" + flush_jitter = "0s" + precision = "" + hostname = "" + omit_hostname = false + debug = true + +[[outputs.influxdb]] + urls = ["http://influxdb:8086"] + database = "telegraf" + timeout = "60s" + username = "telegraf" + password = "VerySecurePassword" + user_agent = "telegraf" + +[[inputs.cpu]] + percpu = true + totalcpu = true + collect_cpu_time = false + report_active = false + +[[inputs.disk]] + ignore_fs = ["tmpfs", "devtmpfs", "devfs", "iso9660", "overlay", "aufs", "squashfs"] + +[[inputs.diskio]] + +[[inputs.kernel]] + +[[inputs.mem]] + +[[inputs.processes]] + +[[inputs.swap]] + +[[inputs.system]] + +[[inputs.dns_query]] + servers = ["8.8.8.8", "4.2.2.1"] + domains = [ + "www.google.com", + "kernel.org", + "facebook.com", + "www.lanacion.com.ar", + "www.cablevision.com.ar" + ] + record_type = "A" + port = 53 + timeout = 2 + + [[inputs.http_response]] + urls = [ + "http://192.168.0.1", + "http://www.wikipedia.org", + "http://github.com", + "http://www.cablevision.com.ar", + "https://www.google.com", + "https://www.facebook.com" + ] + response_timeout = "5s" + method = "GET" + follow_redirects = true + +[[inputs.internal]] + collect_memstats = true + +[[inputs.linux_sysctl_fs]] + +[[inputs.net]] + +[[inputs.netstat]] + +[[inputs.ping]] + urls = ["192.168.0.1", "190.216.88.1", "4.2.2.1", "8.8.8.8", "kernel.org"] + method = "exec" + count = 1 + ping_interval = 1.0 + timeout = 5.0 + deadline = 10 + interface = "eth0" + binary = "ping" + ipv6 = false + +[[inputs.exec]] + commands=["mtr -C -n 4.2.2.1"] + timeout = "2m" + interval = "5m" + data_format = "csv" + csv_skip_rows = 1 + csv_column_names=[ "", "", "status","dest","hop","ip","loss","snt","", "","avg","best","worst","stdev"] + name_override = "mtr" + csv_tag_columns = ["dest", "hop", "ip"] + +[[inputs.exec]] + commands = ["/usr/bin/speedtest-cli --csv --bytes --no-pre-allocate"] + name_override = "speedtest" + timeout = "3m" + interval = "5m" + data_format = "csv" + csv_column_names = ['Server ID','Sponsor','Server Name','Timestamp','Distance','Ping','Download','Upload','Share','IP Address'] + csv_timestamp_column = "Timestamp" + csv_timestamp_format = "2006-01-02T15:04:05Z07:00" +