From c8e251d18dc4bdff67f325709d2ec5972751f20a Mon Sep 17 00:00:00 2001 From: HitLuca Date: Mon, 22 Aug 2022 09:03:59 +0200 Subject: [PATCH 1/2] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20moved=20users=20task?= =?UTF-8?q?=20to=20proper=20role?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nas.yml | 9 +++++---- .../users.yml => roles/ansible-nas-users/tasks/main.yml | 0 2 files changed, 5 insertions(+), 4 deletions(-) rename tasks/users.yml => roles/ansible-nas-users/tasks/main.yml (100%) diff --git a/nas.yml b/nas.yml index ee0f7e6d..fea30fcd 100644 --- a/nas.yml +++ b/nas.yml @@ -1,14 +1,15 @@ --- - hosts: all - pre_tasks: - - import_tasks: tasks/users.yml - tags: users - roles: ### ### Requirements ### + - role: ansible-nas-users + tags: + - ansible-nas-users + - ansible-nas + - role: bertvv.samba tags: - samba diff --git a/tasks/users.yml b/roles/ansible-nas-users/tasks/main.yml similarity index 100% rename from tasks/users.yml rename to roles/ansible-nas-users/tasks/main.yml From 53b17c88119833f2ca0c82fb0b7264a6dbe6d292 Mon Sep 17 00:00:00 2001 From: David Stephens Date: Tue, 23 Aug 2022 00:56:02 +0100 Subject: [PATCH 2/2] :chart_with_upwards_trend: Re-add updated and fixed stats role. Goodbye influx, hello Prometheus --- README.md | 5 +- docs/applications/stats.md | 14 + nas.yml | 5 + roles/stats/defaults/main.yml | 34 + .../dashboards/ansible-nas-overview.json | 2532 +++++++++++++++++ roles/stats/files/dashboards/ansible-nas.yml | 9 + roles/stats/tasks/exporters.yml | 22 + roles/stats/tasks/grafana.yml | 52 + roles/stats/tasks/main.yml | 5 + roles/stats/tasks/prometheus.yml | 46 + roles/stats/tasks/telegraf.yml | 49 + .../templates/datasources/ansible-nas.yml | 18 + roles/stats/templates/prometheus.yml | 45 + .../stats/templates/telegraf.conf.j2 | 95 +- .../provisioning/datasources/ansible-nas.yml | 25 - 15 files changed, 2854 insertions(+), 102 deletions(-) create mode 100644 docs/applications/stats.md create mode 100644 roles/stats/defaults/main.yml create mode 100644 roles/stats/files/dashboards/ansible-nas-overview.json create mode 100644 roles/stats/files/dashboards/ansible-nas.yml create mode 100644 roles/stats/tasks/exporters.yml create mode 100644 roles/stats/tasks/grafana.yml create mode 100644 roles/stats/tasks/main.yml create mode 100644 roles/stats/tasks/prometheus.yml create mode 100644 roles/stats/tasks/telegraf.yml create mode 100644 roles/stats/templates/datasources/ansible-nas.yml create mode 100644 roles/stats/templates/prometheus.yml rename templates/telegraf/telegraf.conf => roles/stats/templates/telegraf.conf.j2 (82%) delete mode 100644 templates/grafana/provisioning/datasources/ansible-nas.yml diff --git a/README.md b/README.md index 181508cf..d87e323e 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,8 @@ If you have a spare domain name you can configure applications to be accessible * [Gitea](https://gitea.io/en-us/) - Simple self-hosted GitHub clone * [GitLab](https://about.gitlab.com/features/) - Self-hosted GitHub clone of the highest order * [Glances](https://nicolargo.github.io/glances/) - for seeing the state of your system via a web browser -* [Gotify](https://gotify.net/) Self-hosted server for sending push notifications +* [Gotify](https://gotify.net/) - Self-hosted server for sending push notifications +* [Grafana](https://grafana.com/) - Query, visualize, alert on, and understand your data no matter where it’s stored (via stats role). * [Guacamole](https://guacamole.apache.org/) - Web based remote desktop gateway, supports VNC, RDP and SSH * [healthchecks.io](https://healthchecks.io/) - Ensure your NAS is online and get notified otherwise * [Heimdall](https://heimdall.site/) - Home server dashboard @@ -70,6 +71,7 @@ If you have a spare domain name you can configure applications to be accessible * [Piwigo](https://piwigo.org/) - Photo Gallery Software * [Plex](https://www.plex.tv/) - Plex Media Server * [Portainer](https://portainer.io/) - for managing Docker and running custom images +* [Prometheus](https://prometheus.io/) - Time series database and monitoring system (via stats role). * [Prowlarr](https://github.com/Prowlarr/Prowlarr) - Indexer aggregator for Sonarr, Radarr, Lidarr, etc. * [pyLoad](https://pyload.net/) - A download manager with a friendly web-interface * [PyTivo](http://pytivo.org) - An HMO and GoBack server for TiVos. @@ -80,6 +82,7 @@ If you have a spare domain name you can configure applications to be accessible * [Sickchill](https://sickchill.github.io/) - for managing TV episodes * [Sonarr](https://sonarr.tv/) - for downloading and managing TV episodes * [Speedtest-Tracker](https://github.com/henrywhitaker3/Speedtest-Tracker) - Continuously track your internet speed +* Stats - Monitor and visualise metrics about your NAS and internet connection using Grafana, Prometheus, Telegraf and more. * [Syncthing](https://syncthing.net/) - sync directories with another device * [Tautulli](http://tautulli.com/) - Monitor Your Plex Media Server * [The Lounge](https://thelounge.chat) - Web based always-on IRC client diff --git a/docs/applications/stats.md b/docs/applications/stats.md new file mode 100644 index 00000000..5316e62f --- /dev/null +++ b/docs/applications/stats.md @@ -0,0 +1,14 @@ +# Stats + +The stats role uses Prometheus, Grafana, Telegraf and a number of metrics exporters to collect and record lots of metrics about your NAS. + +Telegraf also exposes an InfluxDB endpoint for applications that require it. + +## Usage + +Set `stats_enabled: true` in your `inventories//nas.yml` file. If you want to gather metrics on your internet connection, enable `stats_internet_speed_test_enabled` too. + +If you want to access Grafana externally, set `stats_grafana_available_externally: true` in your `inventories//nas.yml` file. If you want to access Promethehus externally, set `stats_prometheus_available_externally: true` in your `inventories//nas.yml` file. + +The Grafana web interface can be found at , Prometheus can be found at + diff --git a/nas.yml b/nas.yml index ee0f7e6d..cc53eb1c 100644 --- a/nas.yml +++ b/nas.yml @@ -365,6 +365,11 @@ - speedtest-tracker when: (speedtest_tracker_enabled | default(False)) + - role: stats + tags: + - stats + when: (stats_enabled | default(False)) + - role: syncthing tags: - syncthing diff --git a/roles/stats/defaults/main.yml b/roles/stats/defaults/main.yml new file mode 100644 index 00000000..a0bd81f9 --- /dev/null +++ b/roles/stats/defaults/main.yml @@ -0,0 +1,34 @@ +--- +stats_enabled: false +stats_internet_speed_test_enabled: false +stats_prometheus_available_externally: false +stats_grafana_available_externally: false + +# directories +stats_telegraf_config_directory: "{{ docker_home }}/stats/telegraf/config" +stats_prometheus_data_directory: "{{ docker_home }}/stats/prometheus/data" +stats_prometheus_config_directory: "{{ docker_home }}/stats/prometheus/config" +stats_grafana_data_directory: "{{ docker_home }}/stats/grafana/data" +stats_grafana_config_directory: "{{ docker_home }}/stats/grafana/config" + +# network +stats_prometheus_port: "9090" +stats_telegraf_port: "9273" +stats_telegraf_influxdb_port: "8086" +stats_prometheus_smartctl_port: "9902" +stats_speedtest_exporter_port: "9798" +stats_prometheus_hostname: "prometheus" +stats_grafana_port: "3000" +stats_grafana_hostname: "grafana" + +# specs +stats_telegraf_memory: 1g +stats_prometheus_memory: 1g +stats_prometheus_smartctl_memory: 1g +stats_speedtest_exporter_memory: 256m +stats_grafana_memory: 1g + +# config +stats_prometheus_retention_time: 365d +stats_prometheus_retention_size: 30GB +stats_collection_interval: 15s diff --git a/roles/stats/files/dashboards/ansible-nas-overview.json b/roles/stats/files/dashboards/ansible-nas-overview.json new file mode 100644 index 00000000..c4c9abf9 --- /dev/null +++ b/roles/stats/files/dashboards/ansible-nas-overview.json @@ -0,0 +1,2532 @@ +{ + "annotations": { + "list": [ + { + "$$hashKey": "object:933", + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 12, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 0, + "y": 0 + }, + "id": 2, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "expr": "system_uptime{host=\"$server\"}", + "refId": "A" + } + ], + "title": "Uptime", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 2, + "x": 4, + "y": 0 + }, + "id": 24, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "expr": "system_n_cpus{host=\"$server\"}", + "refId": "A" + } + ], + "title": "CPUs", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "$$hashKey": "object:3148", + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#299c46", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 70 + }, + { + "color": "#d44a3a", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 6, + "y": 0 + }, + "id": 4, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "expr": "100 - cpu_usage_idle{host=\"$server\",cpu=\"cpu-total\"}", + "refId": "A" + } + ], + "title": "CPU usage", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 9, + "y": 0 + }, + "id": 25, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "expr": "mem_total{host=\"$server\"}", + "refId": "A" + } + ], + "title": "Memory", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "$$hashKey": "object:3098", + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#299c46", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 70 + }, + { + "color": "#d44a3a", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 12, + "y": 0 + }, + "id": 6, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "expr": "mem_used_percent{host=\"$server\"}", + "refId": "A" + } + ], + "title": "Memory Usage", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "mappings": [ + { + "$$hashKey": "object:438", + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 70 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 15, + "y": 0 + }, + "id": 30, + "links": [], + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "exemplar": false, + "expr": "disk_used_percent{host=\"$server\",path=\"/\"}", + "instant": false, + "range": true, + "refId": "A" + } + ], + "title": "RootFS used", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "$$hashKey": "object:488", + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#299c46", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 50 + }, + { + "color": "#d44a3a", + "value": 70 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 18, + "y": 0 + }, + "id": 8, + "links": [], + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "expr": "swap_used_percent{host=\"$server\"}", + "refId": "A" + } + ], + "title": "Swap Usage", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "rgb(31, 120, 193)", + "mode": "fixed" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 21, + "y": 0 + }, + "id": 10, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "expr": "docker_n_containers_running{host=\"$server\"}", + "refId": "A" + } + ], + "title": "Running Containers", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "influxdb", + "uid": "P951FEA4DE68E13C5" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 4 + }, + "id": 52, + "panels": [], + "title": "System", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 5 + }, + "hiddenSeries": false, + "id": 17, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "cpu_usage_user{host=\"$server\",cpu=\"cpu-total\"}", + "legendFormat": "user", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "cpu_usage_system{host=\"$server\",cpu=\"cpu-total\"}", + "hide": false, + "legendFormat": "system", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "cpu_usage_iowait{host=\"$server\",cpu=\"cpu-total\"}", + "hide": false, + "legendFormat": "iowait", + "range": true, + "refId": "C" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "CPU Utilisation", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:4658", + "format": "short", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:4659", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 5 + }, + "hiddenSeries": false, + "id": 16, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "system_load1{host=\"$server\"}", + "legendFormat": "load1", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "system_load5{host=\"$server\"}", + "hide": false, + "legendFormat": "load5", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "system_load15{host=\"$server\"}", + "hide": false, + "legendFormat": "load15", + "range": true, + "refId": "C" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "CPU Load", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:4658", + "format": "short", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:4659", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 13 + }, + "hiddenSeries": false, + "id": 33, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "mem_used{host=\"$server\"}", + "legendFormat": "Used", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "mem_cached{host=\"$server\"}", + "hide": false, + "legendFormat": "Cached", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "mem_buffered{host=\"$server\"}", + "hide": false, + "legendFormat": "Buffered", + "range": true, + "refId": "C" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Memory Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:3940", + "format": "decbytes", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:3941", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "influxdb", + "uid": "P951FEA4DE68E13C5" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 60, + "panels": [], + "title": "Docker", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 22 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "docker_container_cpu_usage_percent{host=\"$server\",cpu=\"cpu-total\"}", + "legendFormat": "{{container_name}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Container CPU Usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:3503", + "format": "percent", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:3504", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 2, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 22 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.0", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "docker_container_mem_usage{host=\"$server\"}", + "legendFormat": "{{container_name}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Container Memory usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:3943", + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:3944", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "influxdb", + "uid": "P951FEA4DE68E13C5" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 30 + }, + "id": 58, + "panels": [], + "title": "Temperature", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "id": 22, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "sensors_temp_input{host=\"$server\"}", + "legendFormat": "{{chip}} {{feature}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "System Temperature", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:7729", + "format": "celsius", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:7730", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 31 + }, + "hiddenSeries": false, + "id": 27, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "hideZero": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "hddtemp_temperature{host=\"$server\",device=~\"$physical_disk\"}", + "legendFormat": "{{device}} - {{model}}", + "range": true, + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Disk Temperature", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:7729", + "format": "celsius", + "logBase": 1, + "min": "0", + "show": true + }, + { + "$$hashKey": "object:7730", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "influxdb", + "uid": "P951FEA4DE68E13C5" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 43, + "panels": [], + "title": "ZFS", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 41 + }, + "hiddenSeries": false, + "id": 19, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "zfs_pool", + "repeatDirection": "v", + "seriesOverrides": [ + { + "$$hashKey": "object:6518", + "alias": "Data Written", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "rate(zfs_pool_nread{host=\"$server\"}[$__rate_interval])", + "legendFormat": "Read", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "rate(zfs_pool_nwritten{host=\"$server\"}[$__rate_interval]) * -1", + "hide": false, + "legendFormat": "Write", + "range": true, + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Pool $zfs_pool Data I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:5924", + "format": "decbytes", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:5925", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 41 + }, + "hiddenSeries": false, + "id": 62, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "zfs_pool", + "repeatDirection": "v", + "seriesOverrides": [ + { + "$$hashKey": "object:6518", + "alias": "Data Written", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "rate(zfs_pool_reads{host=\"$server\"}[$__rate_interval])", + "legendFormat": "Read", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "rate(zfs_pool_writes{host=\"$server\"}[$__rate_interval]) * -1\n", + "hide": false, + "legendFormat": "Write", + "range": true, + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Pool $zfs_pool Iops", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:5924", + "format": "iops", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:5925", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "influxdb", + "uid": "P951FEA4DE68E13C5" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 48 + }, + "id": 50, + "panels": [], + "title": "Physical Disks", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 49 + }, + "hiddenSeries": false, + "id": 36, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "physical_disk", + "repeatDirection": "v", + "seriesOverrides": [ + { + "$$hashKey": "object:1210", + "alias": "Write", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "rate(diskio_read_bytes{host=\"$server\",name=~\"$physical_disk\"}[$__rate_interval])", + "legendFormat": "read", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "rate(diskio_write_bytes{host=\"$server\",name=~\"$physical_disk\"}[$__rate_interval]) * -1", + "hide": false, + "legendFormat": "write", + "range": true, + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "$physical_disk Data I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:566", + "format": "decbytes", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:567", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 49 + }, + "hiddenSeries": false, + "id": 61, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.0", + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "physical_disk", + "repeatDirection": "v", + "seriesOverrides": [ + { + "$$hashKey": "object:1210", + "alias": "Write", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "rate(diskio_reads{host=\"$server\",name=\"$physical_disk\"}[$__rate_interval])", + "legendFormat": "Reads", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "rate(diskio_writes{host=\"$server\",name=\"$physical_disk\"}[$__rate_interval]) * -1", + "hide": false, + "legendFormat": "Writes", + "range": true, + "refId": "B" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "$physical_disk Disk Iops", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:566", + "format": "iops", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:567", + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 91 + }, + "id": 74, + "panels": [], + "title": "Disk SMART", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "h" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 92 + }, + "id": 88, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.1.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "smartprom_power_on_hours_raw", + "legendFormat": "{{drive}}", + "range": true, + "refId": "A" + } + ], + "title": "Power On Hours", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "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": 12, + "x": 0, + "y": 97 + }, + "id": 86, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "smartprom_load_cycle_count_raw", + "legendFormat": "{{drive}}", + "range": true, + "refId": "A" + } + ], + "title": "Power Cycle Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "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": 12, + "x": 12, + "y": 97 + }, + "id": 87, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "smartprom_start_stop_count_raw", + "legendFormat": "{{drive}}", + "range": true, + "refId": "A" + } + ], + "title": "Start Stop Count", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 105 + }, + "id": 100, + "panels": [], + "title": "Internet Connectivity", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 9, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 106 + }, + "id": 102, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "exemplar": false, + "expr": "speedtest_download_bits_per_second", + "instant": false, + "interval": "", + "legendFormat": "Download", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "speedtest_upload_bits_per_second", + "hide": false, + "legendFormat": "Upload", + "range": true, + "refId": "B" + } + ], + "title": "Internet Speed", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "stepAfter", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 106 + }, + "id": 103, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "editorMode": "code", + "expr": "speedtest_ping_latency_milliseconds", + "hide": false, + "legendFormat": "Latency", + "range": true, + "refId": "B" + } + ], + "title": "Internet Latency", + "type": "timeseries" + } + ], + "refresh": "1m", + "schemaVersion": 37, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": "bender", + "value": "bender" + }, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "definition": "label_values(system_uptime,host)", + "hide": 0, + "includeAll": false, + "label": "Server", + "multi": false, + "name": "server", + "options": [], + "query": { + "query": "label_values(system_uptime,host)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "definition": "label_values(zfs_pool_reads,pool)", + "hide": 0, + "includeAll": true, + "label": "ZFS Pool", + "multi": false, + "name": "zfs_pool", + "options": [], + "query": { + "query": "label_values(zfs_pool_reads,pool)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "ansible_nas" + }, + "definition": "label_values(diskio_reads,name)", + "hide": 0, + "includeAll": true, + "label": "Physical Disk", + "multi": false, + "name": "physical_disk", + "options": [], + "query": { + "query": "label_values(diskio_reads,name)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "[a-z]{3}", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Ansible-NAS Overview v2", + "uid": "LCZ9YkQnz", + "version": 20, + "weekStart": "" +} \ No newline at end of file diff --git a/roles/stats/files/dashboards/ansible-nas.yml b/roles/stats/files/dashboards/ansible-nas.yml new file mode 100644 index 00000000..d6699664 --- /dev/null +++ b/roles/stats/files/dashboards/ansible-nas.yml @@ -0,0 +1,9 @@ +apiVersion: 1 + +providers: + - name: dashboards + type: file + updateIntervalSeconds: 60 + options: + path: /etc/dashboards + foldersFromFilesStructure: true diff --git a/roles/stats/tasks/exporters.yml b/roles/stats/tasks/exporters.yml new file mode 100644 index 00000000..79965817 --- /dev/null +++ b/roles/stats/tasks/exporters.yml @@ -0,0 +1,22 @@ +--- +- name: Smartctl Exporter Docker Container + docker_container: + name: stats-smartctl + image: matusnovak/prometheus-smartctl:latest + pull: true + privileged: true + ports: + - "{{ stats_prometheus_smartctl_port }}:9902" + restart_policy: unless-stopped + memory: "{{ stats_prometheus_smartctl_memory }}" + +- name: Speedtest Exporter Docker Container + docker_container: + name: stats-speedtest + image: miguelndecarvalho/speedtest-exporter + pull: true + ports: + "{{ stats_speedtest_exporter_port }}:9798" + restart_policy: unless-stopped + memory: "{{ stats_speedtest_exporter_memory }}" + when: stats_internet_speed_test_enabled diff --git a/roles/stats/tasks/grafana.yml b/roles/stats/tasks/grafana.yml new file mode 100644 index 00000000..78aab599 --- /dev/null +++ b/roles/stats/tasks/grafana.yml @@ -0,0 +1,52 @@ +--- +- name: Create Grafana Directories + file: + path: "{{ item }}" + state: directory + owner: "472" + recurse: yes + with_items: + - "{{ stats_grafana_data_directory }}" + - "{{ stats_grafana_config_directory }}" + - "{{ stats_grafana_config_directory }}/dashboards" + - "{{ stats_grafana_config_directory }}/provisioning/datasources" + - "{{ stats_grafana_config_directory }}/provisioning/dashboards" + +- name: Template Grafana data source + template: + src: datasources/ansible-nas.yml + dest: "{{ stats_grafana_config_directory }}/provisioning/datasources/ansible-nas.yml" + +- name: Copy Grafana dashboards configuration + copy: + src: dashboards/ansible-nas.yml + dest: "{{ stats_grafana_config_directory }}/provisioning/dashboards/ansible-nas.yml" + +- name: Copy Grafana Ansible-NAS dashboard + copy: + src: dashboards/ansible-nas-overview.json + dest: "{{ stats_grafana_config_directory }}/dashboards/ansible-nas-overview.json" + +- name: Grafana Docker Container + docker_container: + name: grafana + image: grafana/grafana + pull: true + volumes: + - "{{ stats_grafana_data_directory }}:/var/lib/grafana:rw" + - "{{ stats_grafana_config_directory }}/provisioning:/etc/grafana/provisioning:ro" + - "{{ stats_grafana_config_directory }}/dashboards:/etc/dashboards:ro" + ports: + - "{{ stats_grafana_port }}:3000" + env: + GF_PLUGINS_ENABLE_ALPHA: "true" + GF_UNIFIED_ALERTING_ENABLED: "true" + restart_policy: unless-stopped + memory: 1g + labels: + traefik.enable: "{{ stats_grafana_available_externally | string }}" + traefik.http.routers.grafana.rule: "Host(`grafana.{{ ansible_nas_domain }}`) " + traefik.http.routers.grafana.tls.certresolver: "letsencrypt" + traefik.http.routers.grafana.tls.domains[0].main: "{{ ansible_nas_domain }}" + traefik.http.routers.grafana.tls.domains[0].sans: "*.{{ ansible_nas_domain }}" + traefik.http.services.grafana.loadbalancer.server.port: "3000" diff --git a/roles/stats/tasks/main.yml b/roles/stats/tasks/main.yml new file mode 100644 index 00000000..91e535de --- /dev/null +++ b/roles/stats/tasks/main.yml @@ -0,0 +1,5 @@ +--- +- import_tasks: prometheus.yml +- import_tasks: telegraf.yml +- import_tasks: exporters.yml +- import_tasks: grafana.yml diff --git a/roles/stats/tasks/prometheus.yml b/roles/stats/tasks/prometheus.yml new file mode 100644 index 00000000..f4a8c062 --- /dev/null +++ b/roles/stats/tasks/prometheus.yml @@ -0,0 +1,46 @@ +--- +- name: Create Prometheus Config Directory + file: + path: "{{ item }}" + state: directory + with_items: + - "{{ stats_prometheus_data_directory }}" + - "{{ stats_prometheus_config_directory }}" + +- name: Create Prometheus Data Directory + file: + path: "{{ item }}" + state: directory + mode: 0777 + with_items: + - "{{ stats_prometheus_data_directory }}" + - "{{ stats_prometheus_config_directory }}" + +- name: Template Prometheus config + template: + src: prometheus.yml + dest: "{{ stats_prometheus_config_directory }}/prometheus.yml" + register: prometheus_config + +- name: Prometheus Docker Container + docker_container: + name: stats-prometheus + image: prom/prometheus + pull: true + volumes: + - "{{ stats_prometheus_config_directory }}/prometheus.yml:/etc/prometheus/prometheus.yml:ro" + - "{{ stats_prometheus_data_directory }}:/prometheus:rw" + - "/etc/timezone:/etc/timezone:ro" + ports: + - "{{ stats_prometheus_port }}:9090" + restart_policy: unless-stopped + memory: "{{ stats_prometheus_memory }}" + restart: "{{ prometheus_config is changed }}" + command: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.retention.size={{ stats_prometheus_retention_size }} --storage.tsdb.retention.time={{ stats_prometheus_retention_time }}" + labels: + traefik.enable: "{{ stats_prometheus_available_externally | string }}" + traefik.http.routers.prometheus.rule: "Host(`{{ stats_prometheus_hostname }}.{{ ansible_nas_domain }}`)" + traefik.http.routers.prometheus.tls.certresolver: "letsencrypt" + traefik.http.routers.prometheus.tls.domains[0].main: "{{ ansible_nas_domain }}" + traefik.http.routers.prometheus.tls.domains[0].sans: "*.{{ ansible_nas_domain }}" + traefik.http.services.prometheus.loadbalancer.server.port: "9090" diff --git a/roles/stats/tasks/telegraf.yml b/roles/stats/tasks/telegraf.yml new file mode 100644 index 00000000..0f087957 --- /dev/null +++ b/roles/stats/tasks/telegraf.yml @@ -0,0 +1,49 @@ +--- +- name: Create Telegraf Directory + file: + path: "{{ item }}" + state: directory + with_items: + - "{{ stats_telegraf_config_directory }}" + +- name: Template telegraf.conf + template: + src: telegraf.conf.j2 + dest: "{{ stats_telegraf_config_directory }}/telegraf.conf" + register: telegraf_config + +- name: Get Docker daemon uid + command: stat -c '%g' /var/run/docker.sock + register: docker_uid + changed_when: false + +- name: Telegraf Docker Container + docker_container: + name: stats-telegraf + image: telegraf + pull: true + privileged: true + ipc_mode: host + ports: + - "{{ stats_telegraf_influxdb_port }}:8086" + - "{{ stats_telegraf_port }}:9273" + user: "telegraf:{{ docker_uid.stdout }}" + volumes: + - "{{ stats_telegraf_config_directory }}/telegraf.conf:/etc/telegraf/telegraf.conf:ro" + - "/var/run/docker.sock:/var/run/docker.sock:ro" + - "/:/hostfs:ro" + - "/etc:/hostfs/etc:ro" + - "/proc:/hostfs/proc:ro" + - "/sys:/hostfs/sys:ro" + - "/var:/hostfs/var:ro" + - "/run:/hostfs/run:ro" + env: + HOST_ETC: "/hostfs/etc" + HOST_PROC: "/hostfs/proc" + HOST_SYS: "/hostfs/sys" + HOST_VAR: "/hostfs/var" + HOST_RUN: "/hostfs/run" + HOST_MOUNT_PREFIX: "/hostfs" + restart_policy: unless-stopped + memory: 1g + restart: "{{ telegraf_config is changed }}" diff --git a/roles/stats/templates/datasources/ansible-nas.yml b/roles/stats/templates/datasources/ansible-nas.yml new file mode 100644 index 00000000..eab5a3b4 --- /dev/null +++ b/roles/stats/templates/datasources/ansible-nas.yml @@ -0,0 +1,18 @@ +--- +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + access: proxy + orgId: 1 + url: http://{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}:{{ stats_prometheus_port }} + uid: ansible_nas + isDefault: true + version: 4 + +deleteDatasources: + - name: "InfluxDB" + orgId: 1 + - name: "Alertmanager" + orgId: 1 diff --git a/roles/stats/templates/prometheus.yml b/roles/stats/templates/prometheus.yml new file mode 100644 index 00000000..d16bf802 --- /dev/null +++ b/roles/stats/templates/prometheus.yml @@ -0,0 +1,45 @@ +# my global config +global: + scrape_interval: {{ stats_collection_interval }} # Set the scrape interval to every 15 seconds. Default is every 1 minute. + evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. + # scrape_timeout is set to the global default (10s). + +# Load rules once and periodically evaluate them according to the global 'evaluation_interval'. +rule_files: + # - "first_rules.yml" + # - "second_rules.yml" + +# A scrape configuration containing exactly one endpoint to scrape: +# Here it's Prometheus itself. +scrape_configs: + # The job name is added as a label `job=` to any timeseries scraped from this config. + - job_name: "prometheus" + static_configs: + - targets: ["localhost:{{ stats_prometheus_port }}"] + + - job_name: "telegraf" + static_configs: + - targets: [ + "{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}:{{ stats_telegraf_port }}", + ] + + - job_name: "smartctl" + static_configs: + - targets: [ + "{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}:{{ stats_prometheus_smartctl_port }}" + ] + + - job_name: "traefik" + static_configs: + - targets: [ + "{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}:8083" + ] + + - job_name: "speedtest" + scrape_interval: 1h + scrape_timeout: 5m + static_configs: + - targets: [ + "{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}:{{ stats_speedtest_exporter_port }}" + ] + diff --git a/templates/telegraf/telegraf.conf b/roles/stats/templates/telegraf.conf.j2 similarity index 82% rename from templates/telegraf/telegraf.conf rename to roles/stats/templates/telegraf.conf.j2 index f473a831..fb9ee47a 100644 --- a/templates/telegraf/telegraf.conf +++ b/roles/stats/templates/telegraf.conf.j2 @@ -25,7 +25,7 @@ # Configuration for telegraf agent [agent] ## Default data collection interval for all inputs - interval = "{{ stat_collection_interval }}" + interval = "{{ stats_collection_interval }}" ## Rounds collection interval to 'interval' ## ie, if interval="10s" then always collect on :00, :10, :20, etc. round_interval = true @@ -82,70 +82,9 @@ # OUTPUT PLUGINS # ############################################################################### -# Configuration for sending metrics to InfluxDB -[[outputs.influxdb]] - ## The full HTTP or UDP URL for your InfluxDB instance. - ## - ## Multiple URLs can be specified for a single cluster, only ONE of the - ## urls will be written to each interval. - # urls = ["unix:///var/run/influxdb.sock"] - # urls = ["udp://127.0.0.1:8089"] - urls = ["http://{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}:8086"] - - ## The target database for metrics; will be created as needed. - database = "telegraf" - - ## If true, no CREATE DATABASE queries will be sent. Set to true when using - ## Telegraf with a user without permissions to create databases or when the - ## database already exists. - # skip_database_creation = false - - ## Name of existing retention policy to write to. Empty string writes to - ## the default retention policy. - # retention_policy = "" - - ## Write consistency (clusters only), can be: "any", "one", "quorum", "all" - # write_consistency = "any" - - ## Timeout for HTTP messages. - # timeout = "5s" - - ## HTTP Basic Auth - # username = "telegraf" - # password = "metricsmetricsmetricsmetrics" - - ## HTTP User-Agent - # user_agent = "telegraf" - - ## UDP payload size is the maximum packet size to send. - # udp_payload = 512 - - ## Optional SSL Config - # ssl_ca = "/etc/telegraf/ca.pem" - # ssl_cert = "/etc/telegraf/cert.pem" - # ssl_key = "/etc/telegraf/key.pem" - ## Use SSL but skip chain & host verification - # insecure_skip_verify = false - - ## HTTP Proxy override, if unset values the standard proxy environment - ## variables are consulted to determine which proxy, if any, should be used. - # http_proxy = "http://corporate.proxy:3128" - - ## Additional HTTP headers - # http_headers = {"X-Special-Header" = "Special-Value"} - - ## HTTP Content-Encoding for write request body, can be set to "gzip" to - ## compress body or "identity" to apply no encoding. - # content_encoding = "identity" - - ## When true, Telegraf will output unsigned integers as unsigned values, - ## i.e.: "42u". You will need a version of InfluxDB supporting unsigned - ## integer values. Enabling this option will result in field type errors if - ## existing data has been written. - # influx_uint_support = false - - - +[[outputs.prometheus_client]] + ## Address to listen on. + listen = ":9273" ############################################################################### # INPUT PLUGINS # @@ -271,17 +210,17 @@ # insecure_skip_verify = false -# Monitor disks' temperatures using hddtemp -[[inputs.hddtemp]] - ## By default, telegraf gathers temps data from all disks detected by the - ## hddtemp. - ## - ## Only collect temps from the selected disks. - ## - ## A * as the device name will return the temperature values of all disks. - ## - address = "hddtemp:7634" - devices = ["*"] +# # Monitor disks' temperatures using hddtemp +# [[inputs.hddtemp]] +# ## By default, telegraf gathers temps data from all disks detected by the +# ## hddtemp. +# ## +# ## Only collect temps from the selected disks. +# ## +# ## A * as the device name will return the temperature values of all disks. +# ## +# address = "hddtemp:7634" +# devices = ["*"] # Read metrics about network interface usage [[inputs.net]] @@ -420,3 +359,7 @@ ## By default, don't gather zpool stats poolMetrics = true +[[inputs.influxdb_v2_listener]] + ## Address and port to host InfluxDB listener on + ## (Double check the port. Could be 9999 if using OSS Beta) + service_address = ":8086" \ No newline at end of file diff --git a/templates/grafana/provisioning/datasources/ansible-nas.yml b/templates/grafana/provisioning/datasources/ansible-nas.yml deleted file mode 100644 index e53dddc2..00000000 --- a/templates/grafana/provisioning/datasources/ansible-nas.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- -apiVersion: 1 - -datasources: - - name: InfluxDB - type: influxdb - access: proxy - orgId: 1 - url: http://{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}:8086 - password: - user: - database: telegraf - basicAuth: - basicAuthUser: - basicAuthPassword: - withCredentials: - isDefault: true - jsonData: - timeInterval: "15s" - secureJsonData: - tlsCACert: "..." - tlsClientCert: "..." - tlsClientKey: "..." - version: 1 - editable: false