aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-07-19 03:14:35 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-07-19 03:16:20 +0200
commit3ef5db455a46095196191ed10509d000a0f29dc1 (patch)
treea2de40425b3e13650976d54009217f6142a444e0
parentflake.lock: Update (diff)
downloadnixos-server-3ef5db455a46095196191ed10509d000a0f29dc1.zip
{modules,test}/monitoring: Init basic version
Diffstat (limited to '')
-rw-r--r--modules/by-name/mo/monitoring/components/grafana.nix296
-rw-r--r--modules/by-name/mo/monitoring/components/loki.nix122
-rw-r--r--modules/by-name/mo/monitoring/components/perses.nix17
-rw-r--r--modules/by-name/mo/monitoring/components/prometheus.nix192
-rw-r--r--modules/by-name/mo/monitoring/components/scrutiny.nix106
-rw-r--r--modules/by-name/mo/monitoring/dashboards/Errors.json811
-rw-r--r--modules/by-name/mo/monitoring/dashboards/Health.json872
-rw-r--r--modules/by-name/mo/monitoring/dashboards/Performance.json1606
-rw-r--r--modules/by-name/mo/monitoring/dashboards/Scraping_Jobs.json334
-rw-r--r--modules/by-name/mo/monitoring/module.nix31
-rw-r--r--modules/by-name/mo/monitoring/rules.json386
-rw-r--r--modules/by-name/ng/nginx/module.nix24
-rw-r--r--tests/by-name/mo/monitoring/test.nix76
13 files changed, 4870 insertions, 3 deletions
diff --git a/modules/by-name/mo/monitoring/components/grafana.nix b/modules/by-name/mo/monitoring/components/grafana.nix
new file mode 100644
index 0000000..5459878
--- /dev/null
+++ b/modules/by-name/mo/monitoring/components/grafana.nix
@@ -0,0 +1,296 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}: let
+ cfg = config.vhack.monitoring.grafana;
+in {
+ options.vhack.monitoring.grafana = {
+ enable = lib.mkEnableOption "grafana";
+
+ orgId = lib.mkOption {
+ type = lib.types.int;
+ description = "Org ID where all vhack related config will be stored.";
+ default = 1;
+ };
+
+ contactPoints = lib.mkOption {
+ type = lib.types.listOf lib.types.str;
+ description = "List of email addresses to send alerts to";
+ default = [];
+ };
+
+ dashboards = lib.mkOption {
+ type = lib.types.listOf lib.types.path;
+ description = "dashboards to provision under 'Vhack' folder.";
+ default = [];
+ };
+
+ fqdn = lib.mkOption {
+ type = lib.types.str;
+ description = "Domain under which Grafana will be served.";
+ example = "grafana.example.org";
+ };
+
+ adminPassword = lib.mkOption {
+ type = lib.types.path;
+ description = "The age-encrypted initial admin password; passed to agenix";
+ };
+
+ secretKey = lib.mkOption {
+ type = lib.types.path;
+ description = "The age-encrypted secret key, used for signing; passed to agenix";
+ };
+
+ port = lib.mkOption {
+ type = lib.types.port;
+ description = "Port where Grafana listens to HTTP requests.";
+ default = 3000;
+ };
+
+ debugLog = lib.mkOption {
+ type = lib.types.bool;
+ description = "Set to true to enable debug logging of the infrastructure serving Grafana.";
+ default = false;
+ example = true;
+ };
+
+ smtp = lib.mkOption {
+ description = "SMTP options.";
+ default = null;
+ type = lib.types.nullOr (
+ lib.types.submodule {
+ options = {
+ from_address = lib.mkOption {
+ type = lib.types.str;
+ description = "SMTP address from which the emails originate.";
+ example = "vaultwarden@mydomain.com";
+ };
+ from_name = lib.mkOption {
+ type = lib.types.str;
+ description = "SMTP name from which the emails originate.";
+ default = "Grafana";
+ };
+ host = lib.mkOption {
+ type = lib.types.str;
+ description = "SMTP host to send the emails to.";
+ };
+ port = lib.mkOption {
+ type = lib.types.port;
+ description = "SMTP port to send the emails to.";
+ default = 25;
+ };
+ username = lib.mkOption {
+ type = lib.types.str;
+ description = "Username to connect to the SMTP host.";
+ };
+ passwordFile = lib.mkOption {
+ type = lib.types.str;
+ description = "File containing the password to connect to the SMTP host.";
+ };
+ };
+ }
+ );
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ assertions = [
+ {
+ assertion = builtins.length cfg.contactPoints > 0;
+ message = "Must have at least one contact point for alerting";
+ }
+ ];
+
+ age.secrets = {
+ grafanaInitialAdminPw = {
+ file = cfg.adminPassword;
+ mode = "0700";
+ owner = "grafana";
+ group = "grafana";
+ };
+ grafanaSecretKey = {
+ file = cfg.secretKey;
+ mode = "0700";
+ owner = "grafana";
+ group = "grafana";
+ };
+ };
+
+ vhack = {
+ postgresql.enable = true;
+ monitoring.grafana.dashboards = [
+ ../dashboards/Errors.json
+ ../dashboards/Performance.json
+ ../dashboards/Scraping_Jobs.json
+ ];
+ };
+
+ services = {
+ nginx = {
+ virtualHosts.${cfg.fqdn} = {
+ locations."/" = {
+ proxyPass = "http://${toString config.services.grafana.settings.server.http_addr}:${toString config.services.grafana.settings.server.http_port}";
+ proxyWebsockets = true;
+ extraConfig = ''
+ proxy_set_header Host $host;
+ '';
+ };
+
+ forceSSL = true;
+ enableACME = true;
+ };
+ };
+
+ postgresql = {
+ ensureUsers = [
+ {
+ name = "grafana";
+ ensureDBOwnership = true;
+ }
+ ];
+ ensureDatabases = [
+ "grafana"
+ ];
+ };
+
+ grafana = {
+ enable = true;
+
+ settings = {
+ database = {
+ host = "/run/postgresql";
+ user = "grafana";
+ name = "grafana";
+ type = "postgres";
+ };
+
+ security = {
+ secret_key = "$__file{${config.age.secrets.grafanaSecretKey.path}}";
+
+ disable_initial_admin_creation = false;
+ admin_password = "$__file{${config.age.secrets.grafanaInitialAdminPw.path}}";
+ };
+
+ server = {
+ http_addr = "127.0.0.1";
+ http_port = cfg.port;
+ domain = cfg.fqdn;
+ root_url = "https://${cfg.fqdn}";
+ router_logging = cfg.debugLog;
+ };
+
+ smtp = lib.mkIf (!(isNull cfg.smtp)) {
+ enabled = true;
+ inherit (cfg.smtp) from_address from_name;
+ host = "${cfg.smtp.host}:${toString cfg.smtp.port}";
+ user = cfg.smtp.username;
+ password = "$__file{${cfg.smtp.passwordFile}}";
+ };
+ };
+
+ provision = {
+ dashboards.settings = lib.mkIf (cfg.dashboards != []) {
+ apiVersion = 1;
+ providers = [
+ {
+ folder = "Vhack";
+ options.path = pkgs.symlinkJoin {
+ name = "dashboards";
+ paths = map (p: pkgs.runCommand "davhackoard" {} "mkdir $out; cp ${p} $out") cfg.dashboards;
+ };
+ allowUiUpdates = true;
+ disableDeletion = true;
+ }
+ ];
+ };
+ datasources.settings = {
+ apiVersion = 1;
+ datasources = [
+ {
+ inherit (cfg) orgId;
+ name = "Prometheus";
+ type = "prometheus";
+ url = "http://127.0.0.1:${toString config.services.prometheus.port}";
+ uid = "df80f9f5-97d7-4112-91d8-72f523a02b09";
+ isDefault = true;
+ version = 1;
+ }
+ {
+ inherit (cfg) orgId;
+ name = "Loki";
+ type = "loki";
+ url = "http://127.0.0.1:${toString config.services.loki.configuration.server.http_listen_port}";
+ uid = "cd6cc53e-840c-484d-85f7-96fede324006";
+ version = 1;
+ }
+ ];
+ deleteDatasources = [
+ {
+ inherit (cfg) orgId;
+ name = "Prometheus";
+ }
+ {
+ inherit (cfg) orgId;
+ name = "Loki";
+ }
+ ];
+ };
+ alerting = {
+ contactPoints.settings = {
+ apiVersion = 1;
+ contactPoints = [
+ {
+ inherit (cfg) orgId;
+ name = "grafana-default-email";
+ receivers = lib.optionals ((builtins.length cfg.contactPoints) > 0) [
+ {
+ uid = "sysadmin";
+ type = "email";
+ settings.addresses = lib.concatStringsSep ";" cfg.contactPoints;
+ }
+ ];
+ }
+ ];
+ };
+ policies.settings = {
+ apiVersion = 1;
+ policies = [
+ {
+ inherit (cfg) orgId;
+ receiver = "grafana-default-email";
+ group_by = [
+ "grafana_folder"
+ "alertname"
+ ];
+ group_wait = "30s";
+ group_interval = "5m";
+ repeat_interval = "4h";
+ }
+ ];
+ # resetPolicies seems to happen after setting the above policies, effectively rolling back
+ # any updates.
+ };
+ rules.settings = let
+ rules = builtins.fromJSON (builtins.readFile ../rules.json);
+ in {
+ apiVersion = 1;
+ groups = [
+ {
+ inherit (cfg) orgId;
+ name = "SysAdmin";
+ folder = "Vhack";
+ interval = "10m";
+ inherit rules;
+ }
+ ];
+ # deleteRules seems to happen after creating the above rules, effectively rolling back
+ # any updates.
+ };
+ };
+ };
+ };
+ };
+ };
+}
diff --git a/modules/by-name/mo/monitoring/components/loki.nix b/modules/by-name/mo/monitoring/components/loki.nix
new file mode 100644
index 0000000..9a285c5
--- /dev/null
+++ b/modules/by-name/mo/monitoring/components/loki.nix
@@ -0,0 +1,122 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}: let
+ cfg = config.vhack.monitoring.loki;
+in {
+ options.vhack.monitoring.loki = {
+ enable = lib.mkEnableOption "loki";
+
+ port = lib.mkOption {
+ type = lib.types.port;
+ description = "Port where Loki listens to HTTP requests.";
+ default = 3002;
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ services = {
+ loki = {
+ enable = true;
+ dataDir = "/var/lib/loki";
+ package = pkgs.grafana-loki;
+ configuration = {
+ auth_enabled = false;
+
+ server.http_listen_port = cfg.port;
+
+ common = {
+ ring = {
+ instance_addr = "127.0.0.1";
+ kvstore = {
+ store = "inmemory";
+ };
+ };
+
+ replication_factor = 1;
+ path_prefix = "/tmp/loki";
+ };
+
+ schema_config = {
+ configs = [
+ {
+ from = "2020-05-15";
+ store = "tsdb";
+ object_store = "filesystem";
+ schema = "v13";
+ index = {
+ prefix = "index_";
+ period = "24h";
+ };
+ }
+ ];
+ };
+
+ storage_config = {
+ filesystem.directory = "/tmp/loki/chunks";
+ };
+ };
+ };
+
+ # I decided to switch to fluent-bit because it can be tested locally https://docs.fluentbit.io/manual/local-testing/logging-pipeline
+ fluent-bit = {
+ enable = true;
+ settings = {
+ service = {
+ flush = 1;
+ log_level = "info";
+ http_server = "true";
+ http_listen = "127.0.0.1";
+ http_port = 9080;
+ grace = 30;
+ };
+
+ pipeline = {
+ inputs = [
+ {
+ name = "systemd";
+
+ # The asterisk appends the _SYSTEMD_UNIT to the prefix.
+ tag = "systemd.*";
+
+ # Read logs from this systemd journal directory.
+ path = "/var/log/journal";
+
+ # Database file to keep track of the journald cursor.
+ db = "/var/fluent-bit/systemd.db";
+
+ # Start reading new entries. Skip entries already stored in journald.
+ read_from_tail = true;
+
+ # Max entries to lookback on start.
+ max_entries = 10000;
+ }
+ ];
+
+ outputs = [
+ {
+ name = "loki";
+
+ match = "systemd.*";
+
+ host = "localhost";
+ port = config.services.loki.configuration.server.http_listen_port;
+
+ labels = lib.concatMapAttrsStringSep ", " (n: v: "${n}=${v}") {
+ job = "systemd-journal";
+ inherit (config.vhack.monitoring.grafana) fqdn;
+ hostname = config.networking.hostName;
+ };
+
+ label_keys = "$unit";
+ }
+ ];
+ };
+ };
+ graceLimit = "1m";
+ };
+ };
+ };
+}
diff --git a/modules/by-name/mo/monitoring/components/perses.nix b/modules/by-name/mo/monitoring/components/perses.nix
new file mode 100644
index 0000000..b0f1ab6
--- /dev/null
+++ b/modules/by-name/mo/monitoring/components/perses.nix
@@ -0,0 +1,17 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}: let
+ cfg = config.vhack.monitoring.perses;
+in {
+ options.vhack.monitoring.perses = {
+ enable = lib.mkEnableOption "perses";
+ };
+ config = lib.mkIf cfg.enable {
+ services.perses = {
+ enable = true;
+ };
+ };
+}
diff --git a/modules/by-name/mo/monitoring/components/prometheus.nix b/modules/by-name/mo/monitoring/components/prometheus.nix
new file mode 100644
index 0000000..468ece3
--- /dev/null
+++ b/modules/by-name/mo/monitoring/components/prometheus.nix
@@ -0,0 +1,192 @@
+{
+ lib,
+ config,
+ nixLib,
+ ...
+}: let
+ cfg = config.vhack.monitoring.prometheus;
+
+ commonLabels = {
+ hostname = config.networking.hostName;
+ inherit (config.vhack.monitoring.grafana) fqdn;
+ };
+
+ prom_cfg = config.services.prometheus;
+in {
+ options.vhack.monitoring.prometheus = {
+ enable = lib.mkEnableOption "prometheus";
+
+ port = lib.mkOption {
+ type = lib.types.port;
+ description = "Port where Prometheus listens to HTTP requests.";
+ default = 3001;
+ };
+
+ sources = lib.mkOption {
+ type = lib.types.listOf (lib.types.submodule {
+ options = {
+ name = lib.mkOption {
+ type = lib.types.str;
+ };
+ target = lib.mkOption {
+ type = lib.types.str;
+ };
+ extra = lib.mkOption {
+ type = lib.types.attrsOf lib.types.anything;
+ };
+ };
+ });
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ vhack = {
+ nginx.enable = true;
+ monitoring.prometheus.sources = [
+ {
+ name = "node";
+ target = "127.0.0.1:${toString prom_cfg.exporters.node.port}";
+ }
+ {
+ name = "smartctl";
+ target = "127.0.0.1:${toString prom_cfg.exporters.smartctl.port}";
+ }
+ {
+ name = "prometheus_internal";
+ target = "127.0.0.1:${toString prom_cfg.port}";
+ }
+ {
+ name = "systemd";
+ target = "127.0.0.1:${toString prom_cfg.exporters.systemd.port}";
+ }
+ {
+ name = "netdata";
+ target = "127.0.0.1:19999";
+ extra = {
+ metrics_path = "/api/v1/allmetrics";
+ params.format = ["prometheus"];
+ honor_labels = true;
+ };
+ }
+ ];
+ };
+
+ services = {
+ prometheus = {
+ enable = true;
+ inherit (cfg) port;
+
+ globalConfig = {
+ scrape_interval = "15s";
+ };
+
+ scrapeConfigs = builtins.map (attr:
+ nixLib.warnMerge {
+ job_name = attr.name;
+ static_configs = [
+ {
+ targets = [attr.target];
+ labels = commonLabels;
+ }
+ ];
+ }
+ attr.extra "prometheus scrapeConfig")
+ cfg.sources;
+ # ++ (lib.optional (builtins.length (lib.attrNames config.services.redis.servers) > 0) {
+ # job_name = "redis";
+ # static_configs = [
+ # {
+ # targets = ["127.0.0.1:${toString config.services.prometheus.exporters.redis.port}"];
+ # }
+ # ];
+ # }) ++ (lib.optional (builtins.length (lib.attrNames config.services.openvpn.servers) > 0) {
+ # job_name = "openvpn";
+ # static_configs = [
+ # {
+ # targets = ["127.0.0.1:${toString config.services.prometheus.exporters.openvpn.port}"];
+ # }
+ # ];
+ # })
+ # ++ (lib.optional config.services.dnsmasq.enable {
+ # job_name = "dnsmasq";
+ # static_configs = [
+ # {
+ # targets = ["127.0.0.1:${toString config.services.prometheus.exporters.dnsmasq.port}"];
+ # labels = commonLabels;
+ # }
+ # ];
+ # });
+
+ exporters = {
+ node = {
+ enable = true;
+ # https://github.com/prometheus/node_exporter#collectors
+ enabledCollectors = [
+ "arp"
+ "cpu"
+ "cpufreq"
+ "diskstats"
+ "dmi"
+ "edac"
+ "entropy"
+ "filefd"
+ "filesystem"
+ "hwmon"
+ "loadavg"
+ "meminfo"
+ "netclass"
+ "netdev"
+ "netstat"
+ "nvme"
+ "os"
+ "pressure"
+ "rapl"
+ "schedstat"
+ "stat"
+ "thermal_zone"
+ "time"
+ "uname"
+ "vmstat"
+ "zfs"
+
+ # Disabled by default
+ "cgroups"
+ "drm"
+ "ethtool"
+ "logind"
+ "wifi"
+ ];
+ port = 9112;
+ listenAddress = "127.0.0.1";
+ };
+ smartctl = {
+ enable = true;
+ port = 9115;
+ listenAddress = "127.0.0.1";
+ };
+ # services.prometheus.exporters.redis = lib.mkIf (builtins.length (lib.attrNames config.services.redis.servers) > 0) {
+ # enable = true;
+ # port = 9119;
+ # listenAddress = "127.0.0.1";
+ # };
+ # services.prometheus.exporters.openvpn = lib.mkIf (builtins.length (lib.attrNames config.services.openvpn.servers) > 0) {
+ # enable = true;
+ # port = 9121;
+ # listenAddress = "127.0.0.1";
+ # statusPaths = lib.mapAttrsToList (name: _config: "/tmp/openvpn/${name}.status") config.services.openvpn.servers;
+ # };
+ # dnsmasq = lib.mkIf config.services.dnsmasq.enable {
+ # enable = true;
+ # port = 9211;
+ # listenAddress = "127.0.0.1";
+ # };
+ systemd = {
+ enable = true;
+ port = 9116;
+ listenAddress = "127.0.0.1";
+ };
+ };
+ };
+ };
+ };
+}
diff --git a/modules/by-name/mo/monitoring/components/scrutiny.nix b/modules/by-name/mo/monitoring/components/scrutiny.nix
new file mode 100644
index 0000000..31871cd
--- /dev/null
+++ b/modules/by-name/mo/monitoring/components/scrutiny.nix
@@ -0,0 +1,106 @@
+{
+ config,
+ pkgs,
+ lib,
+ ...
+}: let
+ cfg = config.vhack.monitoring.scrutiny;
+in {
+ options.vhack.monitoring.scrutiny = {
+ enable = lib.mkEnableOption "scrutiny service";
+
+ fqdn = lib.mkOption {
+ type = lib.types.nullOr lib.types.str;
+ description = ''
+ If a string, this will be the domain under which the scrutiny web interface will be servced.
+
+ If null, the web interface will not be served and only the prometheus metrics will be accessible.
+ '';
+ };
+ };
+
+ config = {
+ vhack.monitoring = {
+ prometheus.sources = [
+ {
+ name = "scrutiny";
+ extra.metrics_path = "/api/metrics";
+ target = "127.0.0.1:${toString config.services.scrutiny.settings.web.listen.port}";
+ }
+ ];
+ grafana.dashboards = [
+ ../dashboards/Health.json
+ ];
+ };
+
+ services = {
+ scrutiny = {
+ enable = true;
+
+ openFirewall = false;
+
+ # This src includes Prometheus metrics exporter.
+ package = pkgs.scrutiny.overrideAttrs {
+ src = pkgs.fetchFromGitHub {
+ owner = "ibizaman";
+ repo = "scrutiny";
+ rev = "74faf06f77df83f29e7e1806cd88b2fafc0bbb82";
+ hash = "sha256-r0AVWL+E046xHxitwMPfRNTOpjuOk+W6tB41YgmLTPg=";
+ };
+
+ vendorHash = "sha256-kAlnlWnBMFCdgdak5L5hRquRtyLi5MTmDa/kxwqPs4E=";
+ };
+
+ settings = {
+ web = {
+ metrics.enabled = true; # Enables Prometheus exporter
+ listenHost = "127.0.0.1";
+ };
+ };
+
+ collector = {
+ enable = true;
+ };
+ };
+
+ # nginx.statusPage = lib.mkDefault config.services.nginx.enable;
+ nginx = lib.mkIf (cfg.fqdn != null) {
+ virtualHosts."${cfg.fqdn}" = {
+ locations."/".proxyPass = "http://127.0.0.1:${toString config.services.scrutiny.settings.web.listen.port}";
+
+ enableACME = true;
+ forceSSL = true;
+ };
+ };
+
+ netdata = {
+ enable = true;
+ config = {
+ # web.mode = "none";
+ # web."bind to" = "127.0.0.1:19999";
+ global = {
+ "debug log" = "syslog";
+ "access log" = "syslog";
+ "error log" = "syslog";
+ };
+ };
+ };
+ };
+
+ # nixpkgs.overlays = [
+ # (final: prev: {
+ # prometheus-systemd-exporter = prev.prometheus-systemd-exporter.overrideAttrs {
+ # src = final.fetchFromGitHub {
+ # owner = "ibizaman";
+ # repo = prev.prometheus-systemd-exporter.pname;
+ # # rev = "v${prev.prometheus-systemd-exporter.version}";
+ # rev = "next_timer";
+ # sha256 = "sha256-jzkh/616tsJbNxFtZ0xbdBQc16TMIYr9QOkPaeQw8xA=";
+ # };
+ #
+ # vendorHash = "sha256-4hsQ1417jLNOAqGkfCkzrmEtYR4YLLW2j0CiJtPg6GI=";
+ # };
+ # })
+ # ];
+ };
+}
diff --git a/modules/by-name/mo/monitoring/dashboards/Errors.json b/modules/by-name/mo/monitoring/dashboards/Errors.json
new file mode 100644
index 0000000..22f4340
--- /dev/null
+++ b/modules/by-name/mo/monitoring/dashboards/Errors.json
@@ -0,0 +1,811 @@
+{
+ "annotations": {
+ "list": [
+ {
+ "builtIn": 1,
+ "datasource": {
+ "type": "grafana",
+ "uid": "-- Grafana --"
+ },
+ "enable": true,
+ "hide": true,
+ "iconColor": "rgba(0, 211, 255, 1)",
+ "name": "Annotations & Alerts",
+ "type": "dashboard"
+ }
+ ]
+ },
+ "editable": true,
+ "fiscalYearStartMonth": 0,
+ "graphTooltip": 0,
+ "id": 8,
+ "links": [],
+ "panels": [
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": 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": "light-red",
+ "value": null
+ },
+ {
+ "color": "transparent",
+ "value": 0.99
+ }
+ ]
+ },
+ "unit": "reqps"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
+ "id": 12,
+ "links": [
+ {
+ "title": "explore",
+ "url": "https://grafana.tiserbox.com/explore?panes=%7B%22HWt%22:%7B%22datasource%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%7Bunit%3D%5C%22nginx.service%5C%22%7D%20%7C%20pattern%20%5C%22%3C_%3E%20%3C_%3E%20%3Cline%3E%5C%22%20%7C%20line_format%20%5C%22%7B%7B.line%7D%7D%5C%22%20%7C%20json%20%7C%20status%20%21~%20%5C%222..%5C%22%20%7C%20__error__%20%21%3D%20%5C%22JSONParserErr%5C%22%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22%7D,%22editorMode%22:%22code%22%7D%5D,%22range%22:%7B%22from%22:%22now-6h%22,%22to%22:%22now%22%7D%7D%7D&schemaVersion=1&orgId=1"
+ }
+ ],
+ "options": {
+ "legend": {
+ "calcs": [
+ "mean",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "editorMode": "code",
+ "expr": "sum by(server_name) (rate({unit=\"nginx.service\"} | pattern \"<_> <_> <line>\" | line_format \"{{.line}}\" | json | __error__ != \"JSONParserErr\" | server_name =~ \"[[server_name]].*\" [$__auto]))",
+ "legendFormat": "{{server_name}}",
+ "queryType": "range",
+ "refId": "A"
+ }
+ ],
+ "title": "Rate of Requests",
+ "transformations": [
+ {
+ "id": "extractFields",
+ "options": {
+ "replace": true,
+ "source": "Line"
+ }
+ },
+ {
+ "id": "organize",
+ "options": {
+ "excludeByName": {},
+ "indexByName": {
+ "body_bytes_sent": 9,
+ "bytes_sent": 8,
+ "gzip_ration": 11,
+ "post": 12,
+ "referrer": 10,
+ "remote_addr": 3,
+ "remote_user": 6,
+ "request": 4,
+ "request_length": 7,
+ "request_time": 15,
+ "server_name": 2,
+ "status": 1,
+ "time_local": 0,
+ "upstream_addr": 13,
+ "upstream_connect_time": 17,
+ "upstream_header_time": 18,
+ "upstream_response_time": 16,
+ "upstream_status": 14,
+ "user_agent": 5
+ },
+ "renameByName": {}
+ }
+ }
+ ],
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "axisSoftMin": 0.5,
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "dashed+area"
+ }
+ },
+ "mappings": [],
+ "max": 1.01,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "light-red",
+ "value": null
+ },
+ {
+ "color": "transparent",
+ "value": 0.99
+ }
+ ]
+ },
+ "unit": "percentunit"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 12,
+ "x": 0,
+ "y": 7
+ },
+ "id": 9,
+ "links": [
+ {
+ "title": "explore",
+ "url": "https://grafana.tiserbox.com/explore?panes=%7B%22HWt%22:%7B%22datasource%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%7Bunit%3D%5C%22nginx.service%5C%22%7D%20%7C%20pattern%20%5C%22%3C_%3E%20%3C_%3E%20%3Cline%3E%5C%22%20%7C%20line_format%20%5C%22%7B%7B.line%7D%7D%5C%22%20%7C%20json%20%7C%20status%20%21~%20%5C%222..%5C%22%20%7C%20__error__%20%21%3D%20%5C%22JSONParserErr%5C%22%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22%7D,%22editorMode%22:%22code%22%7D%5D,%22range%22:%7B%22from%22:%22now-6h%22,%22to%22:%22now%22%7D%7D%7D&schemaVersion=1&orgId=1"
+ }
+ ],
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "min"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "editorMode": "code",
+ "expr": "(sum by(server_name) (count_over_time({unit=\"nginx.service\"} | pattern \"<_> <_> <line>\" | line_format \"{{.line}}\" | json | __error__ != \"JSONParserErr\" | status =~ \"[1234]..\" | server_name =~ \"[[server_name]].*\" [7d])) / sum by(server_name) (count_over_time({unit=\"nginx.service\"} | pattern \"<_> <_> <line>\" | line_format \"{{.line}}\" | json | __error__ != \"JSONParserErr\" | server_name =~ \"[[server_name]].*\" [7d])))",
+ "legendFormat": "{{server_name}}",
+ "queryType": "range",
+ "refId": "A"
+ }
+ ],
+ "title": "5XX Requests Error Budgets",
+ "transformations": [
+ {
+ "id": "extractFields",
+ "options": {
+ "replace": true,
+ "source": "Line"
+ }
+ },
+ {
+ "id": "organize",
+ "options": {
+ "excludeByName": {},
+ "indexByName": {
+ "body_bytes_sent": 9,
+ "bytes_sent": 8,
+ "gzip_ration": 11,
+ "post": 12,
+ "referrer": 10,
+ "remote_addr": 3,
+ "remote_user": 6,
+ "request": 4,
+ "request_length": 7,
+ "request_time": 15,
+ "server_name": 2,
+ "status": 1,
+ "time_local": 0,
+ "upstream_addr": 13,
+ "upstream_connect_time": 17,
+ "upstream_header_time": 18,
+ "upstream_response_time": 16,
+ "upstream_status": 14,
+ "user_agent": 5
+ },
+ "renameByName": {}
+ }
+ }
+ ],
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "max": 1.01,
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "light-red",
+ "value": null
+ },
+ {
+ "color": "transparent",
+ "value": 0.99
+ }
+ ]
+ },
+ "unit": "percentunit"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 12,
+ "x": 12,
+ "y": 7
+ },
+ "id": 10,
+ "links": [
+ {
+ "title": "explore",
+ "url": "https://grafana.tiserbox.com/explore?panes=%7B%22HWt%22:%7B%22datasource%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%7Bunit%3D%5C%22nginx.service%5C%22%7D%20%7C%20pattern%20%5C%22%3C_%3E%20%3C_%3E%20%3Cline%3E%5C%22%20%7C%20line_format%20%5C%22%7B%7B.line%7D%7D%5C%22%20%7C%20json%20%7C%20status%20%21~%20%5C%222..%5C%22%20%7C%20__error__%20%21%3D%20%5C%22JSONParserErr%5C%22%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22%7D,%22editorMode%22:%22code%22%7D%5D,%22range%22:%7B%22from%22:%22now-6h%22,%22to%22:%22now%22%7D%7D%7D&schemaVersion=1&orgId=1"
+ }
+ ],
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "min"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "editorMode": "code",
+ "expr": "(sum by(server_name) (count_over_time({unit=\"nginx.service\"} | pattern \"<_> <_> <line>\" | line_format \"{{.line}}\" | json | __error__ != \"JSONParserErr\" | status =~ \"[1235]..\" | server_name =~ \"[[server_name]].*\" [7d])) / sum by(server_name) (count_over_time({unit=\"nginx.service\"} | pattern \"<_> <_> <line>\" | line_format \"{{.line}}\" | json | __error__ != \"JSONParserErr\" | server_name =~ \"[[server_name]].*\" [7d])))",
+ "legendFormat": "{{server_name}}",
+ "queryType": "range",
+ "refId": "A"
+ }
+ ],
+ "title": "4XX Requests Error Budgets",
+ "transformations": [
+ {
+ "id": "extractFields",
+ "options": {
+ "replace": true,
+ "source": "Line"
+ }
+ },
+ {
+ "id": "organize",
+ "options": {
+ "excludeByName": {},
+ "indexByName": {
+ "body_bytes_sent": 9,
+ "bytes_sent": 8,
+ "gzip_ration": 11,
+ "post": 12,
+ "referrer": 10,
+ "remote_addr": 3,
+ "remote_user": 6,
+ "request": 4,
+ "request_length": 7,
+ "request_time": 15,
+ "server_name": 2,
+ "status": 1,
+ "time_local": 0,
+ "upstream_addr": 13,
+ "upstream_connect_time": 17,
+ "upstream_header_time": 18,
+ "upstream_response_time": 16,
+ "upstream_status": 14,
+ "user_agent": 5
+ },
+ "renameByName": {}
+ }
+ }
+ ],
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "fieldConfig": {
+ "defaults": {},
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 24,
+ "x": 0,
+ "y": 14
+ },
+ "id": 8,
+ "options": {
+ "dedupStrategy": "none",
+ "enableLogDetails": true,
+ "prettifyLogMessage": false,
+ "showCommonLabels": false,
+ "showLabels": true,
+ "showTime": true,
+ "sortOrder": "Descending",
+ "wrapLogMessage": false
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "editorMode": "code",
+ "expr": "{unit=~\"[[service]].*\"}",
+ "queryType": "range",
+ "refId": "A"
+ }
+ ],
+ "title": "Log Errors",
+ "type": "logs"
+ },
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
+ "filterable": false,
+ "inspect": false
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green"
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "Time"
+ },
+ "properties": [
+ {
+ "id": "custom.width",
+ "value": 167
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 14,
+ "w": 24,
+ "x": 0,
+ "y": 22
+ },
+ "id": 7,
+ "links": [
+ {
+ "title": "explore",
+ "url": "https://grafana.tiserbox.com/explore?panes=%7B%22HWt%22:%7B%22datasource%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%7Bunit%3D%5C%22nginx.service%5C%22%7D%20%7C%20pattern%20%5C%22%3C_%3E%20%3C_%3E%20%3Cline%3E%5C%22%20%7C%20line_format%20%5C%22%7B%7B.line%7D%7D%5C%22%20%7C%20json%20%7C%20status%20%21~%20%5C%222..%5C%22%20%7C%20__error__%20%21%3D%20%5C%22JSONParserErr%5C%22%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22%7D,%22editorMode%22:%22code%22%7D%5D,%22range%22:%7B%22from%22:%22now-6h%22,%22to%22:%22now%22%7D%7D%7D&schemaVersion=1&orgId=1"
+ }
+ ],
+ "options": {
+ "cellHeight": "sm",
+ "footer": {
+ "countRows": false,
+ "enablePagination": false,
+ "fields": "",
+ "reducer": [
+ "sum"
+ ],
+ "show": false
+ },
+ "showHeader": true,
+ "sortBy": []
+ },
+ "pluginVersion": "10.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "editorMode": "code",
+ "expr": "{unit=\"nginx.service\"} | pattern \"<_> <_> <line>\" | line_format \"{{.line}}\" | json | __error__ != \"JSONParserErr\" | status =~ \"5..\" | server_name =~ \"[[server_name]].*\"",
+ "queryType": "range",
+ "refId": "A"
+ }
+ ],
+ "title": "5XX Requests Errors",
+ "transformations": [
+ {
+ "id": "extractFields",
+ "options": {
+ "keepTime": false,
+ "replace": false,
+ "source": "Line"
+ }
+ },
+ {
+ "id": "organize",
+ "options": {
+ "excludeByName": {
+ "Line": true,
+ "id": true,
+ "labels": true,
+ "time_local": true,
+ "tsNs": true
+ },
+ "indexByName": {
+ "Line": 21,
+ "Time": 0,
+ "body_bytes_sent": 10,
+ "bytes_sent": 9,
+ "gzip_ration": 12,
+ "id": 23,
+ "labels": 20,
+ "post": 13,
+ "referrer": 11,
+ "remote_addr": 4,
+ "remote_user": 7,
+ "request": 5,
+ "request_length": 8,
+ "request_time": 16,
+ "server_name": 3,
+ "status": 2,
+ "time_local": 1,
+ "tsNs": 22,
+ "upstream_addr": 14,
+ "upstream_connect_time": 18,
+ "upstream_header_time": 19,
+ "upstream_response_time": 17,
+ "upstream_status": 15,
+ "user_agent": 6
+ },
+ "renameByName": {}
+ }
+ }
+ ],
+ "type": "table"
+ },
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
+ "filterable": false,
+ "inspect": false
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green"
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 14,
+ "w": 24,
+ "x": 0,
+ "y": 36
+ },
+ "id": 11,
+ "links": [
+ {
+ "title": "explore",
+ "url": "https://grafana.tiserbox.com/explore?panes=%7B%22HWt%22:%7B%22datasource%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%7Bunit%3D%5C%22nginx.service%5C%22%7D%20%7C%20pattern%20%5C%22%3C_%3E%20%3C_%3E%20%3Cline%3E%5C%22%20%7C%20line_format%20%5C%22%7B%7B.line%7D%7D%5C%22%20%7C%20json%20%7C%20status%20%21~%20%5C%222..%5C%22%20%7C%20__error__%20%21%3D%20%5C%22JSONParserErr%5C%22%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22%7D,%22editorMode%22:%22code%22%7D%5D,%22range%22:%7B%22from%22:%22now-6h%22,%22to%22:%22now%22%7D%7D%7D&schemaVersion=1&orgId=1"
+ }
+ ],
+ "options": {
+ "cellHeight": "sm",
+ "footer": {
+ "countRows": false,
+ "enablePagination": false,
+ "fields": "",
+ "reducer": [
+ "sum"
+ ],
+ "show": false
+ },
+ "showHeader": true
+ },
+ "pluginVersion": "10.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "editorMode": "code",
+ "expr": "{unit=\"nginx.service\"} | pattern \"<_> <_> <line>\" | line_format \"{{.line}}\" | json | __error__ != \"JSONParserErr\" | status =~ \"4..\" | server_name =~ \"[[server_name]].*\"",
+ "queryType": "range",
+ "refId": "A"
+ }
+ ],
+ "title": "4XX Requests Errors",
+ "transformations": [
+ {
+ "id": "extractFields",
+ "options": {
+ "replace": true,
+ "source": "Line"
+ }
+ },
+ {
+ "id": "organize",
+ "options": {
+ "excludeByName": {},
+ "indexByName": {
+ "body_bytes_sent": 9,
+ "bytes_sent": 8,
+ "gzip_ration": 11,
+ "post": 12,
+ "referrer": 10,
+ "remote_addr": 3,
+ "remote_user": 6,
+ "request": 4,
+ "request_length": 7,
+ "request_time": 15,
+ "server_name": 2,
+ "status": 1,
+ "time_local": 0,
+ "upstream_addr": 13,
+ "upstream_connect_time": 17,
+ "upstream_header_time": 18,
+ "upstream_response_time": 16,
+ "upstream_status": 14,
+ "user_agent": 5
+ },
+ "renameByName": {}
+ }
+ }
+ ],
+ "type": "table"
+ }
+ ],
+ "preload": false,
+ "refresh": "",
+ "schemaVersion": 40,
+ "tags": [],
+ "templating": {
+ "list": [
+ {
+ "allValue": ".+",
+ "current": {
+ "text": "All",
+ "value": "$__all"
+ },
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "definition": "query_result(max by (name) (node_systemd_unit_state))",
+ "includeAll": true,
+ "multi": true,
+ "name": "service",
+ "options": [],
+ "query": {
+ "qryType": 3,
+ "query": "query_result(max by (name) (node_systemd_unit_state))",
+ "refId": "PrometheusVariableQueryEditor-VariableQuery"
+ },
+ "refresh": 1,
+ "regex": "/name=\"(?<value>.*)\\.service\"/",
+ "sort": 1,
+ "type": "query"
+ },
+ {
+ "current": {
+ "text": ".+",
+ "value": ".+"
+ },
+ "name": "server_name",
+ "options": [
+ {
+ "selected": true,
+ "text": ".+",
+ "value": ".+"
+ }
+ ],
+ "query": ".+",
+ "type": "textbox"
+ }
+ ]
+ },
+ "time": {
+ "from": "now-6h",
+ "to": "now"
+ },
+ "timepicker": {},
+ "timezone": "",
+ "title": "Errors",
+ "uid": "d66242cf-71e8-417c-8ef7-51b0741545df",
+ "version": 32,
+ "weekStart": ""
+}
diff --git a/modules/by-name/mo/monitoring/dashboards/Health.json b/modules/by-name/mo/monitoring/dashboards/Health.json
new file mode 100644
index 0000000..a2079a2
--- /dev/null
+++ b/modules/by-name/mo/monitoring/dashboards/Health.json
@@ -0,0 +1,872 @@
+{
+ "annotations": {
+ "list": [
+ {
+ "builtIn": 1,
+ "datasource": {
+ "type": "grafana",
+ "uid": "-- Grafana --"
+ },
+ "enable": true,
+ "hide": true,
+ "iconColor": "rgba(0, 211, 255, 1)",
+ "name": "Annotations & Alerts",
+ "type": "dashboard"
+ }
+ ]
+ },
+ "editable": true,
+ "fiscalYearStartMonth": 0,
+ "graphTooltip": 0,
+ "links": [],
+ "panels": [
+ {
+ "collapsed": false,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
+ "id": 4,
+ "panels": [],
+ "repeat": "hostname",
+ "title": "${hostname}",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
+ "footer": {
+ "reducers": []
+ },
+ "inspect": false
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 4,
+ "w": 12,
+ "x": 0,
+ "y": 1
+ },
+ "id": 3,
+ "maxDataPoints": 400,
+ "options": {
+ "cellHeight": "sm",
+ "showHeader": true
+ },
+ "pluginVersion": "12.4.0",
+ "targets": [
+ {
+ "disableTextWrap": false,
+ "editorMode": "builder",
+ "expr": "node_os_info",
+ "fullMetaSearch": false,
+ "includeNullMetadata": true,
+ "legendFormat": "__auto",
+ "range": true,
+ "refId": "A",
+ "useBackend": false
+ }
+ ],
+ "title": "OS Versions",
+ "transformations": [
+ {
+ "id": "labelsToFields",
+ "options": {
+ "keepLabels": [
+ "build_id",
+ "domain",
+ "hostname",
+ "id",
+ "instance",
+ "job",
+ "name",
+ "pretty_name",
+ "version",
+ "version_codename",
+ "version_id"
+ ],
+ "mode": "columns"
+ }
+ },
+ {
+ "id": "groupBy",
+ "options": {
+ "fields": {
+ "Time": {
+ "aggregations": [
+ "firstNotNull"
+ ],
+ "operation": "aggregate"
+ },
+ "pretty_name": {
+ "aggregations": [],
+ "operation": "groupby"
+ }
+ }
+ }
+ }
+ ],
+ "type": "table"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "showValues": false,
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 1
+ },
+ "id": 1,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "hideZeros": false,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "12.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "node_hwmon_temp_celsius{hostname=~\"$hostname\"}",
+ "instant": false,
+ "legendFormat": "{{chip}} - {{sensor}}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Temperature",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "custom": {
+ "axisPlacement": "auto",
+ "fillOpacity": 70,
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "lineWidth": 0
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 4,
+ "w": 24,
+ "x": 0,
+ "y": 9
+ },
+ "id": 5,
+ "interval": "1m",
+ "maxDataPoints": 200,
+ "options": {
+ "colWidth": 1,
+ "legend": {
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": false
+ },
+ "rowHeight": 0.8,
+ "showValue": "never",
+ "tooltip": {
+ "hideZeros": false,
+ "mode": "none",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "12.4.0",
+ "repeat": "hostname",
+ "repeatDirection": "h",
+ "targets": [
+ {
+ "editorMode": "code",
+ "expr": "node_zfs_zpool_state{hostname=~\"$hostname\", state=\"online\"} > 0",
+ "legendFormat": "{{zpool}} - {{state}}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "ZFS Pools",
+ "type": "status-history"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "showValues": false,
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "line+area"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "red",
+ "value": 0
+ },
+ {
+ "color": "transparent",
+ "value": 604808
+ }
+ ]
+ },
+ "unit": "s"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 13
+ },
+ "id": 2,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "displayMode": "table",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "hideZeros": false,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "12.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "ssl_certificate_expiry_seconds",
+ "legendFormat": "{{exported_hostname}}: {{subject}} {{path}}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Certificate Remaining Validity",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "axisSoftMin": 0,
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "showValues": false,
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "years"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 13
+ },
+ "id": 7,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "hideZeros": false,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "12.4.0",
+ "targets": [
+ {
+ "editorMode": "builder",
+ "expr": "scrutiny_smart_power_on_hours{hostname=~\"$hostname\"} / (24 * 365)",
+ "legendFormat": "{{device_name}}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Operating Years",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "continuous-YlRd"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "axisSoftMax": 100,
+ "axisSoftMin": 0,
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineStyle": {
+ "fill": "solid"
+ },
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "showValues": false,
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "percent"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 21
+ },
+ "id": 6,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "table",
+ "placement": "bottom",
+ "showLegend": true,
+ "width": 400
+ },
+ "tooltip": {
+ "hideZeros": false,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "12.4.0",
+ "targets": [
+ {
+ "disableTextWrap": false,
+ "editorMode": "builder",
+ "expr": "sum by(hostname, domain, mountpoint, device) (node_filesystem_free_bytes{hostname=~\"$hostname\"})",
+ "fullMetaSearch": false,
+ "hide": true,
+ "includeNullMetadata": false,
+ "legendFormat": "__auto",
+ "range": true,
+ "refId": "A",
+ "useBackend": false
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "builder",
+ "expr": "sum by(hostname, domain, mountpoint, device) (node_filesystem_size_bytes{hostname=~\"$hostname\"})",
+ "hide": true,
+ "instant": false,
+ "legendFormat": "__auto",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "name": "Expression",
+ "type": "__expr__",
+ "uid": "__expr__"
+ },
+ "expression": "(1 - $A / $B) * 100",
+ "refId": "Disk Full",
+ "type": "math"
+ }
+ ],
+ "title": "Filesystem Disk Usage",
+ "transformations": [
+ {
+ "id": "joinByField",
+ "options": {
+ "byField": "Time",
+ "mode": "outer"
+ }
+ }
+ ],
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "axisSoftMin": 0,
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "showValues": false,
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 21
+ },
+ "id": 9,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "hideZeros": false,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "12.4.0",
+ "targets": [
+ {
+ "editorMode": "builder",
+ "expr": "scrutiny_smart_power_on_hours{hostname=~\"$hostname\"}",
+ "legendFormat": "{{device_name}}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Operating Years",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
+ "footer": {
+ "reducers": []
+ },
+ "inspect": false
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 29
+ },
+ "id": 8,
+ "options": {
+ "cellHeight": "sm",
+ "showHeader": true
+ },
+ "pluginVersion": "12.4.0",
+ "targets": [
+ {
+ "editorMode": "builder",
+ "exemplar": false,
+ "expr": "scrutiny_device_info{hostname=~\"$hostname\"}",
+ "format": "table",
+ "instant": true,
+ "legendFormat": "{{device_name}}",
+ "range": false,
+ "refId": "A"
+ }
+ ],
+ "title": "Disk Info",
+ "transformations": [
+ {
+ "id": "organize",
+ "options": {
+ "excludeByName": {
+ "Time": true,
+ "Value": true,
+ "__name__": true,
+ "domain": true,
+ "hostname": true,
+ "instance": true,
+ "job": true,
+ "wwn": false
+ },
+ "includeByName": {},
+ "indexByName": {},
+ "renameByName": {}
+ }
+ }
+ ],
+ "type": "table"
+ }
+ ],
+ "preload": false,
+ "schemaVersion": 42,
+ "tags": [],
+ "templating": {
+ "list": [
+ {
+ "current": {
+ "text": "baryum",
+ "value": "baryum"
+ },
+ "definition": "label_values(up,hostname)",
+ "name": "hostname",
+ "options": [],
+ "query": {
+ "qryType": 1,
+ "query": "label_values(up,hostname)",
+ "refId": "PrometheusVariableQueryEditor-VariableQuery"
+ },
+ "refresh": 1,
+ "regex": "",
+ "regexApplyTo": "value",
+ "type": "query"
+ }
+ ]
+ },
+ "time": {
+ "from": "now-30m",
+ "to": "now"
+ },
+ "timepicker": {},
+ "timezone": "browser",
+ "title": "Node Health",
+ "uid": "edhuvl28vpjwge",
+ "version": 25,
+ "weekStart": ""
+}
diff --git a/modules/by-name/mo/monitoring/dashboards/Performance.json b/modules/by-name/mo/monitoring/dashboards/Performance.json
new file mode 100644
index 0000000..bb8c88f
--- /dev/null
+++ b/modules/by-name/mo/monitoring/dashboards/Performance.json
@@ -0,0 +1,1606 @@
+{
+ "annotations": {
+ "list": [
+ {
+ "builtIn": 1,
+ "datasource": {
+ "type": "grafana",
+ "uid": "-- Grafana --"
+ },
+ "enable": true,
+ "hide": true,
+ "iconColor": "rgba(0, 211, 255, 1)",
+ "name": "Annotations & Alerts",
+ "type": "dashboard"
+ }
+ ]
+ },
+ "editable": true,
+ "fiscalYearStartMonth": 0,
+ "graphTooltip": 0,
+ "id": 6,
+ "links": [],
+ "panels": [
+ {
+ "collapsed": false,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
+ "id": 12,
+ "panels": [],
+ "title": "Node",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "description": "",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": 3600000,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "decimals": 2,
+ "fieldMinMax": false,
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "red",
+ "value": null
+ },
+ {
+ "color": "transparent",
+ "value": 0.05
+ }
+ ]
+ },
+ "unit": "mbytes"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byFrameRefID",
+ "options": "A"
+ },
+ "properties": [
+ {
+ "id": "custom.axisPlacement",
+ "value": "right"
+ },
+ {
+ "id": "unit",
+ "value": "ms"
+ },
+ {
+ "id": "decimals"
+ },
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "dark-red",
+ "mode": "fixed"
+ }
+ },
+ {
+ "id": "custom.lineStyle",
+ "value": {
+ "dash": [
+ 10,
+ 10
+ ],
+ "fill": "dash"
+ }
+ },
+ {
+ "id": "custom.lineWidth",
+ "value": 2
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byFrameRefID",
+ "options": "B"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "green",
+ "mode": "fixed"
+ }
+ },
+ {
+ "id": "custom.lineStyle",
+ "value": {
+ "dash": [
+ 0,
+ 10
+ ],
+ "fill": "dot"
+ }
+ },
+ {
+ "id": "custom.lineWidth",
+ "value": 2
+ },
+ {
+ "id": "custom.fillOpacity",
+ "value": 10
+ },
+ {
+ "id": "custom.axisPlacement",
+ "value": "auto"
+ },
+ {
+ "id": "custom.stacking",
+ "value": {
+ "group": "A",
+ "mode": "none"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 1
+ },
+ "id": 20,
+ "options": {
+ "legend": {
+ "calcs": [
+ "max",
+ "lastNotNull"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true,
+ "width": 300
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "netdata_system_memory_full_pressure_stall_time_ms_average{hostname=~\"$hostname\"} * -1",
+ "hide": false,
+ "instant": false,
+ "legendFormat": "full stall time",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "sum(node_memory_MemTotal_bytes{instance=\"127.0.0.1:9112\"}) / 1000000 - sum(netdata_mem_available_MiB_average{instance=~\"$instance\"})",
+ "hide": false,
+ "instant": false,
+ "legendFormat": "remaining",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "disableTextWrap": false,
+ "editorMode": "code",
+ "expr": "sum by(dimension, service_name) (netdata_systemd_service_memory_usage_MiB_average{instance=~\"$instance\", service_name=~\"$service\", dimension=\"ram\"})",
+ "fullMetaSearch": false,
+ "hide": false,
+ "includeNullMetadata": true,
+ "legendFormat": "{{service_name}}",
+ "range": true,
+ "refId": "used",
+ "useBackend": false
+ }
+ ],
+ "title": "Memory",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "description": "",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": 3600000,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "decimals": 2,
+ "fieldMinMax": false,
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "red",
+ "value": null
+ },
+ {
+ "color": "transparent",
+ "value": 0.05
+ }
+ ]
+ },
+ "unit": "mbytes"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byFrameRefID",
+ "options": "A"
+ },
+ "properties": [
+ {
+ "id": "custom.axisPlacement",
+ "value": "right"
+ },
+ {
+ "id": "unit",
+ "value": "ms"
+ },
+ {
+ "id": "decimals"
+ },
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "dark-red",
+ "mode": "fixed"
+ }
+ },
+ {
+ "id": "custom.lineStyle",
+ "value": {
+ "dash": [
+ 10,
+ 10
+ ],
+ "fill": "dash"
+ }
+ },
+ {
+ "id": "custom.lineWidth",
+ "value": 2
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byFrameRefID",
+ "options": "B"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "green",
+ "mode": "fixed"
+ }
+ },
+ {
+ "id": "custom.lineStyle",
+ "value": {
+ "dash": [
+ 0,
+ 10
+ ],
+ "fill": "dot"
+ }
+ },
+ {
+ "id": "custom.lineWidth",
+ "value": 2
+ },
+ {
+ "id": "custom.fillOpacity",
+ "value": 10
+ },
+ {
+ "id": "custom.axisPlacement",
+ "value": "auto"
+ },
+ {
+ "id": "custom.stacking",
+ "value": {
+ "group": "A",
+ "mode": "none"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 1
+ },
+ "id": 23,
+ "options": {
+ "legend": {
+ "calcs": [
+ "max",
+ "lastNotNull"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true,
+ "width": 300
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "netdata_system_memory_full_pressure_stall_time_ms_average{hostname=~\"$hostname\"} * -1",
+ "hide": false,
+ "instant": false,
+ "legendFormat": "full stall time",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "sum(node_memory_SwapFree_bytes{instance=~\"127.0.0.1:9112\"}) / 1000000",
+ "hide": false,
+ "instant": false,
+ "legendFormat": "remaining",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "disableTextWrap": false,
+ "editorMode": "code",
+ "expr": "sum by(dimension, service_name) (netdata_systemd_service_memory_usage_MiB_average{hostname=~\"$hostname\", service_name=~\"$service\", dimension=\"swap\"})",
+ "fullMetaSearch": false,
+ "hide": false,
+ "includeNullMetadata": true,
+ "legendFormat": "{{service_name}}",
+ "range": true,
+ "refId": "used",
+ "useBackend": false
+ }
+ ],
+ "title": "Swap",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "description": "",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": 3600000,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "decimals": 2,
+ "fieldMinMax": false,
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "red",
+ "value": null
+ },
+ {
+ "color": "transparent",
+ "value": 0.05
+ }
+ ]
+ },
+ "unit": "percent"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byFrameRefID",
+ "options": "B"
+ },
+ "properties": [
+ {
+ "id": "custom.axisPlacement",
+ "value": "right"
+ },
+ {
+ "id": "unit",
+ "value": "ms"
+ },
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "orange",
+ "mode": "fixed"
+ }
+ },
+ {
+ "id": "custom.lineStyle",
+ "value": {
+ "dash": [
+ 0,
+ 10
+ ],
+ "fill": "dot"
+ }
+ },
+ {
+ "id": "custom.lineWidth",
+ "value": 2
+ },
+ {
+ "id": "custom.fillOpacity",
+ "value": 34
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 9
+ },
+ "id": 22,
+ "options": {
+ "legend": {
+ "calcs": [
+ "max",
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true,
+ "width": 300
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "netdata_system_cpu_some_pressure_stall_time_ms_average{hostname=~\"$hostname\"} * -1",
+ "hide": false,
+ "instant": false,
+ "legendFormat": "some stall time",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "disableTextWrap": false,
+ "editorMode": "code",
+ "expr": "sum by(dimension, service_name) (netdata_systemd_service_cpu_utilization_percentage_average{hostname=~\"$hostname\", service_name=~\"$service\"})",
+ "fullMetaSearch": false,
+ "hide": false,
+ "includeNullMetadata": true,
+ "legendFormat": "{{service_name}} / {{dimension}}",
+ "range": true,
+ "refId": "used",
+ "useBackend": false
+ }
+ ],
+ "title": "CPU",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "description": "",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": 3600000,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "decimals": 2,
+ "fieldMinMax": false,
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "red",
+ "value": null
+ },
+ {
+ "color": "transparent",
+ "value": 0.05
+ }
+ ]
+ },
+ "unit": "Kibits"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byFrameRefID",
+ "options": "A"
+ },
+ "properties": [
+ {
+ "id": "custom.axisPlacement",
+ "value": "right"
+ },
+ {
+ "id": "unit",
+ "value": "ms"
+ },
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "red",
+ "mode": "fixed"
+ }
+ },
+ {
+ "id": "custom.lineStyle",
+ "value": {
+ "dash": [
+ 0,
+ 10
+ ],
+ "fill": "dot"
+ }
+ },
+ {
+ "id": "custom.lineWidth",
+ "value": 2
+ },
+ {
+ "id": "custom.fillOpacity",
+ "value": 12
+ },
+ {
+ "id": "custom.stacking",
+ "value": {
+ "group": "A",
+ "mode": "none"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byFrameRefID",
+ "options": "B"
+ },
+ "properties": [
+ {
+ "id": "custom.axisPlacement",
+ "value": "right"
+ },
+ {
+ "id": "unit",
+ "value": "ms"
+ },
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "orange",
+ "mode": "fixed"
+ }
+ },
+ {
+ "id": "custom.lineStyle",
+ "value": {
+ "dash": [
+ 0,
+ 10
+ ],
+ "fill": "dot"
+ }
+ },
+ {
+ "id": "custom.lineWidth",
+ "value": 2
+ },
+ {
+ "id": "custom.fillOpacity",
+ "value": 17
+ },
+ {
+ "id": "custom.stacking",
+ "value": {
+ "group": "A",
+ "mode": "none"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 9
+ },
+ "id": 21,
+ "options": {
+ "legend": {
+ "calcs": [
+ "max",
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true,
+ "width": 300
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "netdata_system_io_full_pressure_stall_time_ms_average{hostname=~\"$hostname\"} * -1",
+ "hide": false,
+ "instant": false,
+ "legendFormat": "full stall time",
+ "range": true,
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "netdata_system_io_some_pressure_stall_time_ms_average{instance=~\"$instance\"} * -1",
+ "hide": false,
+ "instant": false,
+ "legendFormat": "some stall time",
+ "range": true,
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "disableTextWrap": false,
+ "editorMode": "code",
+ "expr": "sum by(dimension, service_name) (netdata_systemd_service_disk_io_KiB_persec_average{instance=~\"$instance\", service_name=~\"$service\"})",
+ "fullMetaSearch": false,
+ "hide": false,
+ "includeNullMetadata": true,
+ "legendFormat": "{{service_name}} / {{dimension}}",
+ "range": true,
+ "refId": "used",
+ "useBackend": false
+ }
+ ],
+ "title": "Disk I/O",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": 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
+ }
+ ]
+ },
+ "unit": "Kibits"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 17
+ },
+ "id": 18,
+ "options": {
+ "legend": {
+ "calcs": [
+ "max",
+ "sum"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "netdata_disk_io_KiB_persec_average{hostname=~\"$hostname\", chart=~\"disk.sd.+\"}",
+ "instant": false,
+ "legendFormat": "{{device}} / {{dimension}}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Disk I/O",
+ "type": "timeseries"
+ },
+ {
+ "collapsed": false,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 25
+ },
+ "id": 4,
+ "panels": [],
+ "title": "Network Requests",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "custom": {
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "scaleDistribution": {
+ "type": "linear"
+ }
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 26
+ },
+ "id": 17,
+ "links": [
+ {
+ "title": "explore",
+ "url": "https://grafana.tiserbox.com/explore?panes=%7B%22HWt%22:%7B%22datasource%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%7Bunit%3D%5C%22nginx.service%5C%22%7D%20%7C%20pattern%20%5C%22%3C_%3E%20%3C_%3E%20%3Cline%3E%5C%22%20%7C%20line_format%20%5C%22%7B%7B.line%7D%7D%5C%22%20%7C%20json%20%7C%20status%20%21~%20%5C%222..%5C%22%20%7C%20__error__%20%21%3D%20%5C%22JSONParserErr%5C%22%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22%7D,%22editorMode%22:%22code%22%7D%5D,%22range%22:%7B%22from%22:%22now-6h%22,%22to%22:%22now%22%7D%7D%7D&schemaVersion=1&orgId=1"
+ }
+ ],
+ "options": {
+ "calculate": false,
+ "cellGap": 1,
+ "color": {
+ "exponent": 0.5,
+ "fill": "dark-orange",
+ "mode": "scheme",
+ "reverse": false,
+ "scale": "exponential",
+ "scheme": "RdBu",
+ "steps": 62
+ },
+ "exemplars": {
+ "color": "rgba(255,0,255,0.7)"
+ },
+ "filterValues": {
+ "le": 1e-9
+ },
+ "legend": {
+ "show": true
+ },
+ "rowsFrame": {
+ "layout": "auto"
+ },
+ "tooltip": {
+ "mode": "single",
+ "showColorScale": false,
+ "yHistogram": false
+ },
+ "yAxis": {
+ "axisPlacement": "left",
+ "decimals": 0,
+ "reverse": false,
+ "unit": "s"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "editorMode": "code",
+ "expr": "{hostname=~\"$hostname\",unit=\"nginx.service\"} | pattern \"<_> <_> <line>\" | line_format \"{{.line}}\" | json | __error__ != \"JSONParserErr\" | request_time > 100",
+ "legendFormat": "{{server_name}}",
+ "queryType": "range",
+ "refId": "A"
+ }
+ ],
+ "title": "Slow Requests Histogram > 100ms",
+ "transformations": [
+ {
+ "id": "extractFields",
+ "options": {
+ "keepTime": false,
+ "replace": false,
+ "source": "Line"
+ }
+ },
+ {
+ "id": "organize",
+ "options": {
+ "excludeByName": {
+ "Line": true,
+ "body_bytes_sent": true,
+ "bytes_sent": true,
+ "gzip_ration": true,
+ "id": true,
+ "labels": true,
+ "post": true,
+ "referrer": true,
+ "remote_addr": true,
+ "remote_user": true,
+ "request": true,
+ "request_length": true,
+ "server_name": true,
+ "status": true,
+ "time_local": true,
+ "tsNs": true,
+ "upstream_addr": true,
+ "upstream_connect_time": true,
+ "upstream_header_time": true,
+ "upstream_response_time": true,
+ "upstream_status": true,
+ "user_agent": true
+ },
+ "indexByName": {},
+ "renameByName": {}
+ }
+ },
+ {
+ "id": "convertFieldType",
+ "options": {
+ "conversions": [
+ {
+ "destinationType": "number",
+ "targetField": "request_time"
+ }
+ ],
+ "fields": {}
+ }
+ },
+ {
+ "id": "heatmap",
+ "options": {
+ "xBuckets": {
+ "mode": "size",
+ "value": ""
+ },
+ "yBuckets": {
+ "mode": "size",
+ "scale": {
+ "log": 2,
+ "type": "log"
+ },
+ "value": ""
+ }
+ }
+ }
+ ],
+ "type": "heatmap"
+ },
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "points",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": 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
+ }
+ ]
+ },
+ "unit": "ms"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 26
+ },
+ "id": 2,
+ "options": {
+ "legend": {
+ "calcs": [
+ "max",
+ "mean",
+ "variance"
+ ],
+ "displayMode": "table",
+ "placement": "right",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "editorMode": "code",
+ "expr": "{hostname=~\"$hostname\",unit=\"nginx.service\"} | pattern \"<_> <_> <line>\" | line_format \"{{.line}}\" | json | __error__ != \"JSONParserErr\" | request_time > 100",
+ "legendFormat": "",
+ "queryType": "range",
+ "refId": "A"
+ }
+ ],
+ "title": "Requests > 100ms",
+ "transformations": [
+ {
+ "id": "extractFields",
+ "options": {
+ "keepTime": true,
+ "replace": true,
+ "source": "labels"
+ }
+ },
+ {
+ "id": "organize",
+ "options": {
+ "excludeByName": {
+ "body_bytes_sent": true,
+ "bytes_sent": true,
+ "gzip_ration": true,
+ "job": true,
+ "line": true,
+ "post": true,
+ "referrer": true,
+ "remote_addr": true,
+ "remote_user": true,
+ "request": true,
+ "request_length": true,
+ "status": true,
+ "time_local": true,
+ "unit": true,
+ "upstream_addr": true,
+ "upstream_connect_time": true,
+ "upstream_header_time": true,
+ "upstream_response_time": true,
+ "upstream_status": true,
+ "user_agent": true
+ },
+ "indexByName": {},
+ "renameByName": {}
+ }
+ },
+ {
+ "id": "convertFieldType",
+ "options": {
+ "conversions": [
+ {
+ "dateFormat": "",
+ "destinationType": "number",
+ "targetField": "request_time"
+ }
+ ],
+ "fields": {}
+ }
+ },
+ {
+ "id": "partitionByValues",
+ "options": {
+ "fields": [
+ "server_name"
+ ]
+ }
+ },
+ {
+ "id": "renameByRegex",
+ "options": {
+ "regex": "request_time (.*)",
+ "renamePattern": "$1"
+ }
+ }
+ ],
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "thresholds"
+ },
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
+ "filterable": false,
+ "inspect": false
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 24,
+ "x": 0,
+ "y": 34
+ },
+ "id": 3,
+ "links": [
+ {
+ "title": "explore",
+ "url": "https://grafana.tiserbox.com/explore?panes=%7B%22HWt%22:%7B%22datasource%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%7Bunit%3D%5C%22nginx.service%5C%22%7D%20%7C%20pattern%20%5C%22%3C_%3E%20%3C_%3E%20%3Cline%3E%5C%22%20%7C%20line_format%20%5C%22%7B%7B.line%7D%7D%5C%22%20%7C%20json%20%7C%20status%20%21~%20%5C%222..%5C%22%20%7C%20__error__%20%21%3D%20%5C%22JSONParserErr%5C%22%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22%7D,%22editorMode%22:%22code%22%7D%5D,%22range%22:%7B%22from%22:%22now-6h%22,%22to%22:%22now%22%7D%7D%7D&schemaVersion=1&orgId=1"
+ }
+ ],
+ "options": {
+ "cellHeight": "sm",
+ "footer": {
+ "countRows": false,
+ "enablePagination": false,
+ "fields": "",
+ "reducer": [
+ "sum"
+ ],
+ "show": false
+ },
+ "showHeader": true
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "editorMode": "code",
+ "expr": "{hostname=~\"$hostname\",unit=\"nginx.service\"} | pattern \"<_> <_> <line>\" | line_format \"{{.line}}\" | json | __error__ != \"JSONParserErr\" | request_time > 1",
+ "queryType": "range",
+ "refId": "A"
+ }
+ ],
+ "title": "Network Requests Above 1s",
+ "transformations": [
+ {
+ "id": "extractFields",
+ "options": {
+ "replace": true,
+ "source": "Line"
+ }
+ }
+ ],
+ "type": "table"
+ },
+ {
+ "collapsed": false,
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 42
+ },
+ "id": 7,
+ "panels": [],
+ "title": "Databases",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "custom": {
+ "align": "auto",
+ "cellOptions": {
+ "type": "auto"
+ },
+ "inspect": false
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "duration_ms"
+ },
+ "properties": [
+ {
+ "id": "custom.width",
+ "value": 100
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "unit"
+ },
+ "properties": [
+ {
+ "id": "custom.width",
+ "value": 150
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 24,
+ "x": 0,
+ "y": 43
+ },
+ "id": 6,
+ "links": [
+ {
+ "title": "explore",
+ "url": "https://grafana.tiserbox.com/explore?panes=%7B%22HWt%22:%7B%22datasource%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%7Bunit%3D%5C%22nginx.service%5C%22%7D%20%7C%20pattern%20%5C%22%3C_%3E%20%3C_%3E%20%3Cline%3E%5C%22%20%7C%20line_format%20%5C%22%7B%7B.line%7D%7D%5C%22%20%7C%20json%20%7C%20status%20%21~%20%5C%222..%5C%22%20%7C%20__error__%20%21%3D%20%5C%22JSONParserErr%5C%22%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22cd6cc53e-840c-484d-85f7-96fede324006%22%7D,%22editorMode%22:%22code%22%7D%5D,%22range%22:%7B%22from%22:%22now-6h%22,%22to%22:%22now%22%7D%7D%7D&schemaVersion=1&orgId=1"
+ }
+ ],
+ "options": {
+ "cellHeight": "sm",
+ "footer": {
+ "countRows": false,
+ "fields": "",
+ "reducer": [
+ "sum"
+ ],
+ "show": false
+ },
+ "showHeader": true
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "editorMode": "code",
+ "expr": "{hostname=~\"$hostname\",unit=\"postgresql.service\"} | regexp \".*duration: (?P<duration_ms>[0-9.]+) ms (?P<statement>.*)\" | duration_ms > 500 | __error__ != \"LabelFilterErr\"",
+ "queryType": "range",
+ "refId": "A"
+ }
+ ],
+ "title": "Slow DB Queries",
+ "transformations": [
+ {
+ "id": "extractFields",
+ "options": {
+ "replace": true,
+ "source": "labels"
+ }
+ },
+ {
+ "id": "organize",
+ "options": {
+ "excludeByName": {
+ "job": true
+ },
+ "indexByName": {
+ "duration_ms": 0,
+ "job": 1,
+ "statement": 3,
+ "unit": 2
+ },
+ "renameByName": {}
+ }
+ }
+ ],
+ "type": "table"
+ }
+ ],
+ "preload": false,
+ "refresh": "1m",
+ "schemaVersion": 40,
+ "tags": [],
+ "templating": {
+ "list": [
+ {
+ "allValue": ".*",
+ "current": {
+ "text": [
+ "baryum"
+ ],
+ "value": [
+ "baryum"
+ ]
+ },
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "definition": "label_values(netdata_systemd_service_unit_state_state_average,hostname)",
+ "includeAll": false,
+ "multi": true,
+ "name": "hostname",
+ "options": [],
+ "query": {
+ "qryType": 1,
+ "query": "label_values(netdata_systemd_service_unit_state_state_average,hostname)",
+ "refId": "PrometheusVariableQueryEditor-VariableQuery"
+ },
+ "refresh": 1,
+ "regex": "",
+ "type": "query"
+ },
+ {
+ "allValue": ".*",
+ "current": {
+ "text": [
+ "All"
+ ],
+ "value": [
+ "$__all"
+ ]
+ },
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "definition": "label_values(netdata_systemd_service_unit_state_state_average,unit_name)",
+ "includeAll": true,
+ "multi": true,
+ "name": "service",
+ "options": [],
+ "query": {
+ "qryType": 1,
+ "query": "label_values(netdata_systemd_service_unit_state_state_average,unit_name)",
+ "refId": "PrometheusVariableQueryEditor-VariableQuery"
+ },
+ "refresh": 1,
+ "regex": "",
+ "type": "query"
+ }
+ ]
+ },
+ "time": {
+ "from": "now-30m",
+ "to": "now"
+ },
+ "timepicker": {},
+ "timezone": "",
+ "title": "Performance",
+ "uid": "e01156bf-cdba-42eb-9845-a401dd634d41",
+ "version": 82,
+ "weekStart": ""
+}
diff --git a/modules/by-name/mo/monitoring/dashboards/Scraping_Jobs.json b/modules/by-name/mo/monitoring/dashboards/Scraping_Jobs.json
new file mode 100644
index 0000000..39921d0
--- /dev/null
+++ b/modules/by-name/mo/monitoring/dashboards/Scraping_Jobs.json
@@ -0,0 +1,334 @@
+{
+ "annotations": {
+ "list": [
+ {
+ "builtIn": 1,
+ "datasource": {
+ "type": "grafana",
+ "uid": "-- Grafana --"
+ },
+ "enable": true,
+ "hide": true,
+ "iconColor": "rgba(0, 211, 255, 1)",
+ "name": "Annotations & Alerts",
+ "type": "dashboard"
+ }
+ ]
+ },
+ "editable": true,
+ "fiscalYearStartMonth": 0,
+ "graphTooltip": 0,
+ "id": 5,
+ "links": [],
+ "panels": [
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "fieldConfig": {
+ "defaults": {},
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 0
+ },
+ "id": 5,
+ "options": {
+ "dedupStrategy": "none",
+ "enableInfiniteScrolling": false,
+ "enableLogDetails": true,
+ "prettifyLogMessage": false,
+ "showCommonLabels": false,
+ "showLabels": false,
+ "showTime": true,
+ "sortOrder": "Descending",
+ "wrapLogMessage": false
+ },
+ "pluginVersion": "12.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "direction": "backward",
+ "editorMode": "code",
+ "expr": "{unit=~\"prometheus-.*-exporter.service\"}",
+ "queryType": "range",
+ "refId": "A"
+ }
+ ],
+ "title": "Exporter Logs",
+ "type": "logs"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "fixedColor": "red",
+ "mode": "shades"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "showValues": false,
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 0
+ },
+ "id": 4,
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "hideZeros": false,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "12.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "rate(net_conntrack_dialer_conn_failed_total{hostname=~\"$hostname\"}[2m]) > 0",
+ "instant": false,
+ "legendFormat": "{{dialer_name}} - {{reason}}",
+ "range": true,
+ "refId": "A"
+ }
+ ],
+ "title": "Errors",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "fixedColor": "red",
+ "mode": "thresholds"
+ },
+ "custom": {
+ "axisPlacement": "auto",
+ "fillOpacity": 70,
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineWidth": 0,
+ "spanNulls": false
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": 0
+ },
+ {
+ "color": "red",
+ "value": 1
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 8
+ },
+ "id": 3,
+ "options": {
+ "alignValue": "center",
+ "legend": {
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": false
+ },
+ "mergeValues": true,
+ "rowHeight": 0.9,
+ "showValue": "never",
+ "tooltip": {
+ "hideZeros": false,
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "12.2.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "prometheus_sd_discovered_targets{hostname=~\"$hostname\"}",
+ "hide": false,
+ "instant": false,
+ "legendFormat": "{{config}}",
+ "range": true,
+ "refId": "All"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "label_replace(increase((sum by(dialer_name) (net_conntrack_dialer_conn_failed_total{hostname=~\"$hostname\"}))[15m:1m]), \"config\", \"$1\", \"dialer_name\", \"(.*)\")",
+ "hide": false,
+ "instant": false,
+ "legendFormat": "{{dialer_name}}",
+ "range": true,
+ "refId": "Failed"
+ }
+ ],
+ "title": "Scraping jobs",
+ "transformations": [
+ {
+ "id": "labelsToFields",
+ "options": {
+ "keepLabels": [
+ "config"
+ ],
+ "mode": "columns"
+ }
+ },
+ {
+ "id": "merge",
+ "options": {}
+ },
+ {
+ "id": "organize",
+ "options": {
+ "excludeByName": {
+ "prometheus_sd_discovered_targets": true
+ },
+ "indexByName": {},
+ "renameByName": {
+ "prometheus_sd_discovered_targets": ""
+ }
+ }
+ },
+ {
+ "id": "partitionByValues",
+ "options": {
+ "fields": [
+ "config"
+ ]
+ }
+ }
+ ],
+ "type": "state-timeline"
+ }
+ ],
+ "preload": false,
+ "refresh": "",
+ "schemaVersion": 42,
+ "tags": [],
+ "templating": {
+ "list": [
+ {
+ "current": {
+ "text": "baryum",
+ "value": "baryum"
+ },
+ "definition": "label_values(up,hostname)",
+ "includeAll": false,
+ "name": "hostname",
+ "options": [],
+ "query": {
+ "qryType": 1,
+ "query": "label_values(up,hostname)",
+ "refId": "PrometheusVariableQueryEditor-VariableQuery"
+ },
+ "refresh": 1,
+ "regex": "",
+ "type": "query"
+ }
+ ]
+ },
+ "time": {
+ "from": "now-6h",
+ "to": "now"
+ },
+ "timepicker": {},
+ "timezone": "",
+ "title": "Scraping Jobs",
+ "uid": "debb763d-77aa-47bd-9290-2e02583c8ed2",
+ "version": 24
+}
diff --git a/modules/by-name/mo/monitoring/module.nix b/modules/by-name/mo/monitoring/module.nix
new file mode 100644
index 0000000..e0fc5db
--- /dev/null
+++ b/modules/by-name/mo/monitoring/module.nix
@@ -0,0 +1,31 @@
+# Heavily inspired by:
+# https://github.com/ibizaman/selfhostblocks/blob/989865eb519e3fc3e8a803c374775451c47a29c8/modules/blocks/monitoring.nix
+{
+ lib,
+ config,
+ ...
+}: let
+ cfg = config.vhack.monitoring;
+in {
+ imports = [
+ ./components/loki.nix
+ # ./components/perses.nix
+ ./components/grafana.nix
+ ./components/scrutiny.nix
+ ./components/prometheus.nix
+ ];
+
+ options.vhack.monitoring = {
+ enable = lib.mkEnableOption "monitoring defaults";
+ };
+
+ config.vhack.monitoring = lib.mkIf cfg.enable {
+ grafana.enable = true;
+
+ loki.enable = true;
+
+ prometheus.enable = true;
+
+ scrutiny. enable = true;
+ };
+}
diff --git a/modules/by-name/mo/monitoring/rules.json b/modules/by-name/mo/monitoring/rules.json
new file mode 100644
index 0000000..8e050e6
--- /dev/null
+++ b/modules/by-name/mo/monitoring/rules.json
@@ -0,0 +1,386 @@
+[
+ {
+ "uid": "f5246fa3-163f-4eae-9e1d-5b0fe2af0509",
+ "title": "5XX Requests Error Budgets Under 99%",
+ "condition": "threshold",
+ "data": [
+ {
+ "refId": "A",
+ "queryType": "range",
+ "relativeTimeRange": {
+ "from": 21600,
+ "to": 0
+ },
+ "datasourceUid": "cd6cc53e-840c-484d-85f7-96fede324006",
+ "model": {
+ "datasource": {
+ "type": "loki",
+ "uid": "cd6cc53e-840c-484d-85f7-96fede324006"
+ },
+ "editorMode": "code",
+ "expr": "(sum by(server_name) (count_over_time({unit=\"nginx.service\"} | pattern \"<_> <_> <line>\" | line_format \"{{.line}}\" | json | __error__ != \"JSONParserErr\" | status =~ \"[1234]..\" | server_name =~ \".*\" [1h])) / sum by(server_name) (count_over_time({unit=\"nginx.service\"} | pattern \"<_> <_> <line>\" | line_format \"{{.line}}\" | json | __error__ != \"JSONParserErr\" | server_name =~ \".*\" [1h])))",
+ "intervalMs": 1000,
+ "legendFormat": "{{server_name}}",
+ "maxDataPoints": 43200,
+ "queryType": "range",
+ "refId": "A"
+ }
+ },
+ {
+ "refId": "last",
+ "relativeTimeRange": {
+ "from": 0,
+ "to": 0
+ },
+ "datasourceUid": "__expr__",
+ "model": {
+ "conditions": [
+ {
+ "evaluator": {
+ "params": [],
+ "type": "gt"
+ },
+ "operator": {
+ "type": "and"
+ },
+ "query": {
+ "params": [
+ "B"
+ ]
+ },
+ "reducer": {
+ "params": [],
+ "type": "last"
+ },
+ "type": "query"
+ }
+ ],
+ "datasource": {
+ "type": "__expr__",
+ "uid": "__expr__"
+ },
+ "expression": "A",
+ "intervalMs": 1000,
+ "maxDataPoints": 43200,
+ "reducer": "last",
+ "refId": "last",
+ "type": "reduce"
+ }
+ },
+ {
+ "refId": "threshold",
+ "relativeTimeRange": {
+ "from": 0,
+ "to": 0
+ },
+ "datasourceUid": "__expr__",
+ "model": {
+ "conditions": [
+ {
+ "evaluator": {
+ "params": [
+ 0.99
+ ],
+ "type": "lt"
+ },
+ "operator": {
+ "type": "and"
+ },
+ "query": {
+ "params": [
+ "C"
+ ]
+ },
+ "reducer": {
+ "params": [],
+ "type": "last"
+ },
+ "type": "query"
+ }
+ ],
+ "datasource": {
+ "type": "__expr__",
+ "uid": "__expr__"
+ },
+ "expression": "last",
+ "intervalMs": 1000,
+ "maxDataPoints": 43200,
+ "refId": "threshold",
+ "type": "threshold"
+ }
+ }
+ ],
+ "dasboardUid": "d66242cf-71e8-417c-8ef7-51b0741545df",
+ "panelId": 9,
+ "noDataState": "OK",
+ "execErrState": "Error",
+ "for": "20m",
+ "annotations": {
+ "__dashboardUid__": "d66242cf-71e8-417c-8ef7-51b0741545df",
+ "__panelId__": "9",
+ "description": "",
+ "runbook_url": "",
+ "summary": "The error budget for a service for the last 1 hour is under 99%"
+ },
+ "labels": {
+ "role": "sysadmin"
+ },
+ "isPaused": false
+ },
+ {
+ "uid": "ee817l3a88s1sd",
+ "title": "Certificate Did Not Renew",
+ "condition": "C",
+ "data": [
+ {
+ "refId": "A",
+ "relativeTimeRange": {
+ "from": 1800,
+ "to": 0
+ },
+ "datasourceUid": "df80f9f5-97d7-4112-91d8-72f523a02b09",
+ "model": {
+ "adhocFilters": [],
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "expr": "min by(subject) (ssl_certificate_expiry_seconds)",
+ "interval": "",
+ "intervalMs": 15000,
+ "legendFormat": "{{exported_hostname}}: {{subject}} {{path}}",
+ "maxDataPoints": 43200,
+ "range": true,
+ "refId": "A"
+ }
+ },
+ {
+ "refId": "B",
+ "relativeTimeRange": {
+ "from": 0,
+ "to": 0
+ },
+ "datasourceUid": "__expr__",
+ "model": {
+ "conditions": [
+ {
+ "evaluator": {
+ "params": [],
+ "type": "gt"
+ },
+ "operator": {
+ "type": "and"
+ },
+ "query": {
+ "params": [
+ "B"
+ ]
+ },
+ "reducer": {
+ "params": [],
+ "type": "last"
+ },
+ "type": "query"
+ }
+ ],
+ "datasource": {
+ "type": "__expr__",
+ "uid": "__expr__"
+ },
+ "expression": "A",
+ "intervalMs": 1000,
+ "maxDataPoints": 43200,
+ "reducer": "last",
+ "refId": "B",
+ "type": "reduce"
+ }
+ },
+ {
+ "refId": "C",
+ "relativeTimeRange": {
+ "from": 0,
+ "to": 0
+ },
+ "datasourceUid": "__expr__",
+ "model": {
+ "conditions": [
+ {
+ "evaluator": {
+ "params": [
+ 604800
+ ],
+ "type": "lt"
+ },
+ "operator": {
+ "type": "and"
+ },
+ "query": {
+ "params": [
+ "C"
+ ]
+ },
+ "reducer": {
+ "params": [],
+ "type": "last"
+ },
+ "type": "query"
+ }
+ ],
+ "datasource": {
+ "type": "__expr__",
+ "uid": "__expr__"
+ },
+ "expression": "B",
+ "intervalMs": 1000,
+ "maxDataPoints": 43200,
+ "refId": "C",
+ "type": "threshold"
+ }
+ }
+ ],
+ "dashboardUid": "ae818js0bvw8wb",
+ "panelId": 3,
+ "noDataState": "NoData",
+ "execErrState": "Error",
+ "for": "20m",
+ "annotations": {
+ "__dashboardUid__": "ae818js0bvw8wb",
+ "__panelId__": "3",
+ "description": "The expiry date of the certificate is 1 week from now.",
+ "summary": "Certificate did not renew on time."
+ },
+ "labels": {
+ "role": "sysadmin"
+ },
+ "isPaused": false
+ },
+ {
+ "uid": "df4doj5pomhvkf",
+ "title": "Late Backups",
+ "condition": "C",
+ "data": [
+ {
+ "refId": "A",
+ "relativeTimeRange": {
+ "from": 10800,
+ "to": 0
+ },
+ "datasourceUid": "df80f9f5-97d7-4112-91d8-72f523a02b09",
+ "model": {
+ "adhocFilters": [],
+ "datasource": {
+ "type": "prometheus",
+ "uid": "df80f9f5-97d7-4112-91d8-72f523a02b09"
+ },
+ "editorMode": "code",
+ "exemplar": false,
+ "expr": "(\n # Timer triggered at least once in the last 24h\n label_replace((\n time()\n -\n systemd_timer_last_trigger_seconds{name=~\".*backup.*.timer\"}\n ) < 24*60*60, \"name\", \"$1.service\", \"name\", \"(.*).timer\")\n AND on(name)\n # At least one failure in the last 24h\n (\n max_over_time(systemd_unit_state{name=~\".*backup.*.service\", state=\"failed\"}[24h]) > 0\n )\n AND on(name)\n # No successes in the last 24h\n (\n max_over_time(systemd_unit_state{name=~\".*backup.*.service\", state=\"inactive\"}[24h]) == 0\n )\n)",
+ "instant": false,
+ "interval": "",
+ "intervalMs": 15000,
+ "legendFormat": "{{name}}",
+ "maxDataPoints": 43200,
+ "range": true,
+ "refId": "A"
+ }
+ },
+ {
+ "refId": "B",
+ "relativeTimeRange": {
+ "from": 0,
+ "to": 0
+ },
+ "datasourceUid": "__expr__",
+ "model": {
+ "conditions": [
+ {
+ "evaluator": {
+ "params": [],
+ "type": "gt"
+ },
+ "operator": {
+ "type": "and"
+ },
+ "query": {
+ "params": [
+ "B"
+ ]
+ },
+ "reducer": {
+ "params": [],
+ "type": "last"
+ },
+ "type": "query"
+ }
+ ],
+ "datasource": {
+ "type": "__expr__",
+ "uid": "__expr__"
+ },
+ "expression": "A",
+ "intervalMs": 1000,
+ "maxDataPoints": 43200,
+ "reducer": "last",
+ "refId": "B",
+ "type": "reduce"
+ }
+ },
+ {
+ "refId": "C",
+ "relativeTimeRange": {
+ "from": 0,
+ "to": 0
+ },
+ "datasourceUid": "__expr__",
+ "model": {
+ "conditions": [
+ {
+ "evaluator": {
+ "params": [
+ 0
+ ],
+ "type": "gt"
+ },
+ "operator": {
+ "type": "and"
+ },
+ "query": {
+ "params": [
+ "C"
+ ]
+ },
+ "reducer": {
+ "params": [],
+ "type": "last"
+ },
+ "type": "query"
+ }
+ ],
+ "datasource": {
+ "type": "__expr__",
+ "uid": "__expr__"
+ },
+ "expression": "B",
+ "intervalMs": 1000,
+ "maxDataPoints": 43200,
+ "refId": "C",
+ "type": "threshold"
+ }
+ }
+ ],
+ "dashboardUid": "f05500d0-15ed-4719-b68d-fb898ca13cc8",
+ "panelId": 15,
+ "noDataState": "OK",
+ "execErrState": "Error",
+ "annotations": {
+ "__dashboardUid__": "f05500d0-15ed-4719-b68d-fb898ca13cc8",
+ "__panelId__": "15",
+ "summary": "A backup did not run in the last 24 hours."
+ },
+ "labels": {
+ "role": "sysadmin"
+ },
+ "isPaused": false
+ }
+]
diff --git a/modules/by-name/ng/nginx/module.nix b/modules/by-name/ng/nginx/module.nix
index fa3337d..734a2d2 100644
--- a/modules/by-name/ng/nginx/module.nix
+++ b/modules/by-name/ng/nginx/module.nix
@@ -39,9 +39,27 @@ in {
};
config = lib.mkIf cfg.enable {
- vhack.persist.directories = [
- "/var/lib/acme"
- ];
+ vhack = {
+ persist.directories = [
+ "/var/lib/acme"
+ ];
+
+ monitoring.prometheus = {
+ sources = [
+ {
+ name = "nginx";
+ target = "127.0.0.1:${toString config.services.prometheus.exporters.nginx.port}";
+ }
+ ];
+ };
+ };
+
+ services.prometheus.exporters.nginx = {
+ enable = true;
+ port = 9111;
+ listenAddress = "127.0.0.1";
+ scrapeUri = "http://localhost:80/nginx_status";
+ };
users = {
users.acme = {
diff --git a/tests/by-name/mo/monitoring/test.nix b/tests/by-name/mo/monitoring/test.nix
new file mode 100644
index 0000000..0b2ed1c
--- /dev/null
+++ b/tests/by-name/mo/monitoring/test.nix
@@ -0,0 +1,76 @@
+{
+ extraModules,
+ pkgs,
+ vhack,
+ ...
+}: let
+ grafanaDomain = "grafana.server.org";
+ scrutinyDomain = "scrutiny.server.org";
+in
+ vhack.runTest {
+ name = "monitoring";
+
+ serverDomains = [
+ {server = grafanaDomain;}
+ {server = scrutinyDomain;}
+ ];
+
+ nodes = {
+ client = {};
+
+ server = {config, ...}: {
+ imports =
+ extraModules
+ ++ [
+ ../../../../modules
+ ];
+
+ # there are no SMART available disk in the VM, so this service always fails.
+ systemd.services."smartd".enable = false;
+
+ age.identityPaths = ["${../../../common/email/hostKey}"];
+
+ vhack = {
+ monitoring = {
+ grafana = {
+ enable = true;
+ contactPoints = ["me@example.com"];
+ fqdn = grafanaDomain;
+
+ adminPassword = ../../../common/email/dkim/alice.com/private.age;
+ secretKey = ../../../common/email/dkim/bob.com/private.age;
+
+ # TODO: Add a test for that <2026-07-19>
+ smtp = null;
+ };
+
+ loki = {
+ enable = true;
+ };
+
+ prometheus = {
+ enable = true;
+ };
+
+ scrutiny = {
+ enable = true;
+ fqdn = scrutinyDomain;
+ };
+ };
+ };
+ };
+ };
+
+ services = [
+ {server = "grafana.service";}
+ {server = "fluent-bit.service";}
+ {server = "loki.service";}
+ {server = "netdata.service";}
+ ];
+
+ testScript = {...}:
+ # Python
+ ''
+ # TODO: We should probably query some of the prometheus metrics here? <2026-07-19>
+ '';
+ }