{
  "uid": "incus-capacity-planning",
  "title": "Capacity Planning",
  "description": "CPU/memory headroom per node, resource trends, disk space forecast with predict_linear, instance count trends.",
  "tags": ["incus", "capacity", "operations"],
  "timezone": "browser",
  "schemaVersion": 39,
  "refresh": "5m",
  "time": { "from": "now-7d", "to": "now" },
  "fiscalYearStartMonth": 0,
  "liveNow": false,
  "editable": true,
  "graphTooltip": 1,
  "links": [
    {
      "asDropdown": true,
      "icon": "external link",
      "includeVars": true,
      "keepTime": true,
      "tags": ["incus"],
      "targetBlank": false,
      "title": "Incus Dashboards",
      "tooltip": "Navigate to other Incus dashboards",
      "type": "dashboards"
    }
  ],
  "templating": { "list": [] },
  "annotations": {
    "list": [
      {
        "builtIn": 1,
        "datasource": { "type": "grafana", "uid": "-- Grafana --" },
        "enable": true,
        "hide": true,
        "iconColor": "rgba(0, 211, 255, 1)",
        "name": "Annotations & Alerts",
        "type": "dashboard"
      }
    ]
  },
  "panels": [
    {
      "type": "row",
      "title": "Current Headroom",
      "collapsed": false,
      "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 },
      "id": 1,
      "panels": []
    },
    {
      "type": "bargauge",
      "title": "CPU Headroom per Node",
      "description": "Available (idle) CPU percentage per host node. Higher values mean more headroom for additional workloads.",
      "gridPos": { "h": 6, "w": 12, "x": 0, "y": 1 },
      "id": 2,
      "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
      "targets": [
        {
          "expr": "avg by (instance) (rate(node_cpu_seconds_total{job=\"node-exporter\", mode=\"idle\"}[$__rate_interval])) * 100",
          "legendFormat": "{{instance}}",
          "refId": "A"
        }
      ],
      "fieldConfig": {
        "defaults": {
          "thresholds": {
            "mode": "absolute",
            "steps": [
              { "color": "red", "value": null },
              { "color": "orange", "value": 20 },
              { "color": "yellow", "value": 40 },
              { "color": "green", "value": 60 }
            ]
          },
          "unit": "percent",
          "min": 0,
          "max": 100,
          "color": { "mode": "thresholds" }
        },
        "overrides": []
      },
      "options": {
        "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
        "orientation": "horizontal",
        "displayMode": "gradient",
        "showUnfilled": true,
        "minVizWidth": 8,
        "minVizHeight": 16,
        "valueMode": "color"
      }
    },
    {
      "type": "bargauge",
      "title": "Memory Headroom per Node",
      "description": "Available memory percentage per host node. Higher values mean more headroom for additional workloads.",
      "gridPos": { "h": 6, "w": 12, "x": 12, "y": 1 },
      "id": 3,
      "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
      "targets": [
        {
          "expr": "(node_memory_MemAvailable_bytes{job=\"node-exporter\"} / node_memory_MemTotal_bytes{job=\"node-exporter\"}) * 100",
          "legendFormat": "{{instance}}",
          "refId": "A"
        }
      ],
      "fieldConfig": {
        "defaults": {
          "thresholds": {
            "mode": "absolute",
            "steps": [
              { "color": "red", "value": null },
              { "color": "orange", "value": 20 },
              { "color": "yellow", "value": 40 },
              { "color": "green", "value": 60 }
            ]
          },
          "unit": "percent",
          "min": 0,
          "max": 100,
          "color": { "mode": "thresholds" }
        },
        "overrides": []
      },
      "options": {
        "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
        "orientation": "horizontal",
        "displayMode": "gradient",
        "showUnfilled": true,
        "minVizWidth": 8,
        "minVizHeight": 16,
        "valueMode": "color"
      }
    },
    {
      "type": "row",
      "title": "Resource Trends",
      "collapsed": false,
      "gridPos": { "h": 1, "w": 24, "x": 0, "y": 7 },
      "id": 4,
      "panels": []
    },
    {
      "type": "timeseries",
      "title": "CPU Usage Trend (7-day)",
      "description": "CPU utilization percentage per host node over the past 7 days. Helps identify sustained usage patterns and growth trends.",
      "gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 },
      "id": 5,
      "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
      "targets": [
        {
          "expr": "(1 - avg by (instance) (rate(node_cpu_seconds_total{job=\"node-exporter\", mode=\"idle\"}[5m]))) * 100",
          "legendFormat": "{{instance}}",
          "refId": "A"
        }
      ],
      "fieldConfig": {
        "defaults": {
          "custom": {
            "drawStyle": "line",
            "lineInterpolation": "smooth",
            "lineWidth": 2,
            "fillOpacity": 25,
            "gradientMode": "scheme",
            "spanNulls": false,
            "showPoints": "never",
            "pointSize": 5,
            "stacking": { "mode": "none", "group": "A" },
            "axisPlacement": "auto",
            "axisLabel": "",
            "scaleDistribution": { "type": "linear" },
            "thresholdsStyle": { "mode": "off" }
          },
          "unit": "percent",
          "min": 0,
          "max": 100,
          "color": { "mode": "continuous-GrYlRd" },
          "thresholds": {
            "mode": "absolute",
            "steps": [
              { "color": "green", "value": null },
              { "color": "yellow", "value": 70 },
              { "color": "red", "value": 90 }
            ]
          }
        },
        "overrides": []
      },
      "options": {
        "tooltip": { "mode": "multi", "sort": "desc" },
        "legend": { "displayMode": "table", "placement": "right", "calcs": ["mean", "max", "lastNotNull"] }
      }
    },
    {
      "type": "timeseries",
      "title": "Memory Usage Trend (7-day)",
      "description": "Memory utilization percentage per host node over the past 7 days. Helps identify sustained usage patterns and growth trends.",
      "gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 },
      "id": 6,
      "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
      "targets": [
        {
          "expr": "(1 - node_memory_MemAvailable_bytes{job=\"node-exporter\"} / node_memory_MemTotal_bytes{job=\"node-exporter\"}) * 100",
          "legendFormat": "{{instance}}",
          "refId": "A"
        }
      ],
      "fieldConfig": {
        "defaults": {
          "custom": {
            "drawStyle": "line",
            "lineInterpolation": "smooth",
            "lineWidth": 2,
            "fillOpacity": 25,
            "gradientMode": "scheme",
            "spanNulls": false,
            "showPoints": "never",
            "pointSize": 5,
            "stacking": { "mode": "none", "group": "A" },
            "axisPlacement": "auto",
            "axisLabel": "",
            "scaleDistribution": { "type": "linear" },
            "thresholdsStyle": { "mode": "off" }
          },
          "unit": "percent",
          "min": 0,
          "max": 100,
          "color": { "mode": "continuous-GrYlRd" },
          "thresholds": {
            "mode": "absolute",
            "steps": [
              { "color": "green", "value": null },
              { "color": "yellow", "value": 70 },
              { "color": "red", "value": 90 }
            ]
          }
        },
        "overrides": []
      },
      "options": {
        "tooltip": { "mode": "multi", "sort": "desc" },
        "legend": { "displayMode": "table", "placement": "right", "calcs": ["mean", "max", "lastNotNull"] }
      }
    },
    {
      "type": "row",
      "title": "Disk Space Forecast",
      "collapsed": false,
      "gridPos": { "h": 1, "w": 24, "x": 0, "y": 16 },
      "id": 7,
      "panels": []
    },
    {
      "type": "timeseries",
      "title": "Disk Space Forecast (30-day projection)",
      "description": "Current available disk space on root filesystem with a 30-day linear projection based on the past 7 days of data. Dashed lines show the forecast; if a forecast line drops below zero, the disk will fill up within 30 days at current consumption rates.",
      "gridPos": { "h": 8, "w": 24, "x": 0, "y": 17 },
      "id": 8,
      "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
      "targets": [
        {
          "expr": "node_filesystem_avail_bytes{job=\"node-exporter\", mountpoint=\"/\"}",
          "legendFormat": "{{instance}} actual",
          "refId": "A"
        },
        {
          "expr": "predict_linear(node_filesystem_avail_bytes{job=\"node-exporter\", mountpoint=\"/\"}[7d], 30*24*3600)",
          "legendFormat": "{{instance}} forecast",
          "refId": "B"
        }
      ],
      "fieldConfig": {
        "defaults": {
          "custom": {
            "drawStyle": "line",
            "lineInterpolation": "smooth",
            "lineWidth": 2,
            "fillOpacity": 15,
            "gradientMode": "none",
            "spanNulls": false,
            "showPoints": "never",
            "pointSize": 5,
            "stacking": { "mode": "none", "group": "A" },
            "axisPlacement": "auto",
            "axisLabel": "",
            "scaleDistribution": { "type": "linear" },
            "thresholdsStyle": { "mode": "off" }
          },
          "unit": "bytes",
          "color": { "mode": "palette-classic" },
          "thresholds": {
            "mode": "absolute",
            "steps": [{ "color": "green", "value": null }]
          }
        },
        "overrides": [
          {
            "matcher": { "id": "byRegexp", "options": ".*forecast$" },
            "properties": [
              { "id": "custom.lineStyle", "value": { "fill": "dash", "dash": [10, 10] } },
              { "id": "custom.fillOpacity", "value": 0 }
            ]
          }
        ]
      },
      "options": {
        "tooltip": { "mode": "multi", "sort": "desc" },
        "legend": { "displayMode": "table", "placement": "right", "calcs": ["mean", "max", "lastNotNull"] }
      }
    },
    {
      "type": "row",
      "title": "Instance Trends",
      "collapsed": false,
      "gridPos": { "h": 1, "w": 24, "x": 0, "y": 25 },
      "id": 9,
      "panels": []
    },
    {
      "type": "timeseries",
      "title": "Instance Count Over Time",
      "description": "Total number of running Incus instances over time. Tracks growth and churn in the cluster workload count.",
      "gridPos": { "h": 8, "w": 12, "x": 0, "y": 26 },
      "id": 10,
      "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
      "targets": [
        {
          "expr": "count(incus_cpu_effective_total)",
          "legendFormat": "Instances",
          "refId": "A"
        }
      ],
      "fieldConfig": {
        "defaults": {
          "custom": {
            "drawStyle": "line",
            "lineInterpolation": "smooth",
            "lineWidth": 2,
            "fillOpacity": 25,
            "gradientMode": "none",
            "spanNulls": false,
            "showPoints": "never",
            "pointSize": 5,
            "stacking": { "mode": "none", "group": "A" },
            "axisPlacement": "auto",
            "axisLabel": "",
            "scaleDistribution": { "type": "linear" },
            "thresholdsStyle": { "mode": "off" }
          },
          "unit": "short",
          "color": { "mode": "palette-classic" },
          "thresholds": {
            "mode": "absolute",
            "steps": [{ "color": "green", "value": null }]
          }
        },
        "overrides": []
      },
      "options": {
        "tooltip": { "mode": "multi", "sort": "desc" },
        "legend": { "displayMode": "table", "placement": "right", "calcs": ["mean", "max", "lastNotNull"] }
      }
    },
    {
      "type": "timeseries",
      "title": "Memory Allocation vs Usage per Instance",
      "description": "Compares total allocated memory (MemTotal) against active memory usage for each Incus instance. A large gap between allocated and used indicates overprovisioning; converging lines indicate an instance may need more memory.",
      "gridPos": { "h": 8, "w": 12, "x": 12, "y": 26 },
      "id": 11,
      "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" },
      "targets": [
        {
          "expr": "incus_memory_MemTotal_bytes",
          "legendFormat": "{{name}} allocated",
          "refId": "A"
        },
        {
          "expr": "incus_memory_Active_bytes",
          "legendFormat": "{{name}} used (active)",
          "refId": "B"
        }
      ],
      "fieldConfig": {
        "defaults": {
          "custom": {
            "drawStyle": "line",
            "lineInterpolation": "smooth",
            "lineWidth": 1,
            "fillOpacity": 0,
            "gradientMode": "none",
            "spanNulls": false,
            "showPoints": "never",
            "pointSize": 5,
            "stacking": { "mode": "none", "group": "A" },
            "axisPlacement": "auto",
            "axisLabel": "",
            "scaleDistribution": { "type": "linear" },
            "thresholdsStyle": { "mode": "off" }
          },
          "unit": "bytes",
          "color": { "mode": "palette-classic" },
          "thresholds": {
            "mode": "absolute",
            "steps": [{ "color": "green", "value": null }]
          }
        },
        "overrides": [
          {
            "matcher": { "id": "byRegexp", "options": ".*allocated$" },
            "properties": [
              { "id": "custom.lineStyle", "value": { "fill": "dash", "dash": [10, 10] } },
              { "id": "custom.lineWidth", "value": 2 }
            ]
          },
          {
            "matcher": { "id": "byRegexp", "options": ".*used \\(active\\)$" },
            "properties": [
              { "id": "custom.fillOpacity", "value": 15 }
            ]
          }
        ]
      },
      "options": {
        "tooltip": { "mode": "multi", "sort": "desc" },
        "legend": { "displayMode": "table", "placement": "right", "calcs": ["mean", "max", "lastNotNull"] }
      }
    }
  ]
}
