Repository: NetApp/harvest
Pull request #1792 (2023-03-01 19:30:01)

feat: qtree dashboard should include topK qtrees by disk used growth
Thanks to Watson9121 for raising


Patch:
diff --git a/cmd/tools/grafana/units.yaml b/cmd/tools/grafana/units.yaml
index 37b26415..645e1f73 100644
--- a/cmd/tools/grafana/units.yaml
+++ b/cmd/tools/grafana/units.yaml
@@ -170,4 +170,10 @@
   ontapUnit: per_sec
   grafanaJson: ops
   grafanaDisplay: Blocks/sec(ops)
-  comment: Number of block free per second
\ No newline at end of file
+  comment: Number of block free per second
+
+- metric: quota_disk_used
+  ontapUnit: kilobytes
+  grafanaJson: kbytes
+  grafanaDisplay: kbytes
+  comment: Current amount of disk space, in kilobytes, used by the quota target.
diff --git a/grafana/dashboards/cmode/aggregate.json b/grafana/dashboards/cmode/aggregate.json
index 5e8b417e..6fc3bc99 100644
--- a/grafana/dashboards/cmode/aggregate.json
+++ b/grafana/dashboards/cmode/aggregate.json
@@ -1387,6 +1387,7 @@
           },
           "mappings": [],
           "min": 0,
+          "max": 100,
           "thresholds": {
             "mode": "absolute",
             "steps": [
@@ -1484,6 +1485,7 @@
           },
           "mappings": [],
           "min": 0,
+          "max": 100,
           "thresholds": {
             "mode": "absolute",
             "steps": [
@@ -1863,6 +1865,7 @@
           },
           "mappings": [],
           "min": 0,
+          "max": 100,
           "thresholds": {
             "mode": "absolute",
             "steps": [
@@ -1953,6 +1956,7 @@
           },
           "mappings": [],
           "min": 0,
+          "max": 100,
           "thresholds": {
             "mode": "absolute",
             "steps": [
@@ -2043,6 +2047,7 @@
           },
           "mappings": [],
           "min": 0,
+          "max": 100,
           "thresholds": {
             "mode": "absolute",
             "steps": [
@@ -3172,7 +3177,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -3273,7 +3280,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": [
               {
@@ -3943,7 +3952,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -4129,7 +4140,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
diff --git a/grafana/dashboards/cmode/cdot.json b/grafana/dashboards/cmode/cdot.json
index 858c0232..2a9005d6 100644
--- a/grafana/dashboards/cmode/cdot.json
+++ b/grafana/dashboards/cmode/cdot.json
@@ -422,7 +422,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -597,7 +599,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": [
               {
@@ -725,7 +729,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": [
               {
@@ -853,7 +859,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": [
               {
@@ -1006,7 +1014,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1093,7 +1103,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1180,7 +1192,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
diff --git a/grafana/dashboards/cmode/cluster.json b/grafana/dashboards/cmode/cluster.json
index f86db564..b0dd4b6e 100644
--- a/grafana/dashboards/cmode/cluster.json
+++ b/grafana/dashboards/cmode/cluster.json
@@ -1919,7 +1919,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -2295,7 +2297,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -2373,7 +2377,6 @@
               },
               "links": [],
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -2387,7 +2390,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -2478,7 +2483,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
diff --git a/grafana/dashboards/cmode/disk.json b/grafana/dashboards/cmode/disk.json
index c764e1b1..f01b4a5a 100644
--- a/grafana/dashboards/cmode/disk.json
+++ b/grafana/dashboards/cmode/disk.json
@@ -1009,7 +1009,9 @@
               }
             ]
           },
-          "unit": "percent"
+          "unit": "percent",
+          "min": 0,
+          "max": 100
         },
         "overrides": []
       },
@@ -2174,7 +2176,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": [
               {
@@ -2301,7 +2305,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": [
               {
diff --git a/grafana/dashboards/cmode/lun.json b/grafana/dashboards/cmode/lun.json
index 63c7ac85..48b044bf 100644
--- a/grafana/dashboards/cmode/lun.json
+++ b/grafana/dashboards/cmode/lun.json
@@ -3333,7 +3333,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -3409,7 +3411,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -3423,7 +3424,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -3512,7 +3515,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -3588,7 +3593,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -3602,7 +3606,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -3691,7 +3697,9 @@
                   }
                 ]
               },
-              "unit": "percentunit"
+              "unit": "percentunit",
+              "min": 0,
+              "max": 1
             },
             "overrides": []
           },
@@ -3782,7 +3790,9 @@
                   }
                 ]
               },
-              "unit": "percentunit"
+              "unit": "percentunit",
+              "min": 0,
+              "max": 1
             },
             "overrides": []
           },
diff --git a/grafana/dashboards/cmode/mcc_cluster.json b/grafana/dashboards/cmode/mcc_cluster.json
index f43075fe..fe799e43 100644
--- a/grafana/dashboards/cmode/mcc_cluster.json
+++ b/grafana/dashboards/cmode/mcc_cluster.json
@@ -1188,7 +1188,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -1206,7 +1205,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
diff --git a/grafana/dashboards/cmode/metadata.json b/grafana/dashboards/cmode/metadata.json
index 3fd11dd9..c67d8bca 100644
--- a/grafana/dashboards/cmode/metadata.json
+++ b/grafana/dashboards/cmode/metadata.json
@@ -2087,7 +2087,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -2179,7 +2181,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
diff --git a/grafana/dashboards/cmode/nfs4storePool.json b/grafana/dashboards/cmode/nfs4storePool.json
index 06ff110f..2b2b4b96 100644
--- a/grafana/dashboards/cmode/nfs4storePool.json
+++ b/grafana/dashboards/cmode/nfs4storePool.json
@@ -119,7 +119,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "noValue": "No StorePools Allocations > 50%",
               "thresholds": {
                 "mode": "absolute",
@@ -142,7 +141,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -378,7 +379,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -396,7 +396,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -474,7 +476,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -492,7 +493,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -569,7 +572,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -587,7 +589,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -664,7 +668,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -682,7 +685,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -759,7 +764,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -777,7 +781,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -854,7 +860,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -872,7 +877,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -949,7 +956,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -967,7 +973,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1044,7 +1052,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -1062,7 +1069,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1139,7 +1148,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -1157,7 +1165,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1234,7 +1244,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -1252,7 +1261,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1329,7 +1340,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -1347,7 +1357,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1424,7 +1436,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -1442,7 +1453,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1519,7 +1532,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -1537,7 +1549,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1614,7 +1628,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -1632,7 +1645,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1709,7 +1724,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -1727,7 +1741,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1804,7 +1820,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -1822,7 +1837,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1899,7 +1916,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -1917,7 +1933,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
diff --git a/grafana/dashboards/cmode/node.json b/grafana/dashboards/cmode/node.json
index d14d83c9..454f1397 100644
--- a/grafana/dashboards/cmode/node.json
+++ b/grafana/dashboards/cmode/node.json
@@ -424,8 +424,6 @@
       "fieldConfig": {
         "defaults": {
           "mappings": [],
-          "max": 100,
-          "min": 0,
           "thresholds": {
             "mode": "absolute",
             "steps": [
@@ -435,7 +433,9 @@
               }
             ]
           },
-          "unit": "percent"
+          "unit": "percent",
+          "min": 0,
+          "max": 100
         },
         "overrides": []
       },
@@ -753,8 +753,6 @@
       "fieldConfig": {
         "defaults": {
           "mappings": [],
-          "max": 100,
-          "min": 0,
           "thresholds": {
             "mode": "absolute",
             "steps": [
@@ -764,7 +762,9 @@
               }
             ]
           },
-          "unit": "percent"
+          "unit": "percent",
+          "min": 0,
+          "max": 100
         },
         "overrides": []
       },
@@ -1074,7 +1074,6 @@
                 }
               },
               "mappings": [],
-              "max": 100,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -1092,7 +1091,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1184,7 +1185,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1291,7 +1294,9 @@
                   }
                 ]
               },
-              "unit": "percentunit"
+              "unit": "percentunit",
+              "min": 0,
+              "max": 1
             },
             "overrides": []
           },
@@ -1381,7 +1386,9 @@
                   }
                 ]
               },
-              "unit": "percentunit"
+              "unit": "percentunit",
+              "min": 0,
+              "max": 1
             },
             "overrides": []
           },
@@ -1959,7 +1966,6 @@
                 }
               },
               "mappings": [],
-              "max": 100,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -1977,7 +1983,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -2080,7 +2088,6 @@
                 }
               },
               "mappings": [],
-              "max": 100,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -2094,7 +2101,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
diff --git a/grafana/dashboards/cmode/qtree.json b/grafana/dashboards/cmode/qtree.json
index e073faa8..d7f3c224 100644
--- a/grafana/dashboards/cmode/qtree.json
+++ b/grafana/dashboards/cmode/qtree.json
@@ -628,6 +628,94 @@
           ],
           "title": "Top $TopResources Qtrees by Files Used",
           "type": "timeseries"
+        },
+        {
+          "datasource": "${DS_PROMETHEUS}",
+          "description": "",
+          "fieldConfig": {
+            "defaults": {
+              "color": {
+                "mode": "palette-classic"
+              },
+              "custom": {
+                "axisLabel": "",
+                "axisPlacement": "auto",
+                "barAlignment": 0,
+                "drawStyle": "line",
+                "fillOpacity": 10,
+                "gradientMode": "none",
+                "hideFrom": {
+                  "legend": false,
+                  "tooltip": false,
+                  "viz": false
+                },
+                "lineInterpolation": "linear",
+                "lineWidth": 2,
+                "pointSize": 5,
+                "scaleDistribution": {
+                  "type": "linear"
+                },
+                "showPoints": "auto",
+                "spanNulls": true,
+                "stacking": {
+                  "group": "A",
+                  "mode": "none"
+                },
+                "thresholdsStyle": {
+                  "mode": "off"
+                }
+              },
+              "mappings": [],
+              "thresholds": {
+                "mode": "absolute",
+                "steps": [
+                  {
+                    "color": "green",
+                    "value": null
+                  },
+                  {
+                    "color": "red",
+                    "value": 80
+                  }
+                ]
+              },
+              "unit": "KiBs"
+            },
+            "overrides": []
+          },
+          "gridPos": {
+            "h": 10,
+            "w": 24,
+            "x": 0,
+            "y": 30
+          },
+          "id": 129,
+          "options": {
+            "legend": {
+              "calcs": [
+                "min",
+                "mean",
+                "lastNotNull",
+                "max"
+              ],
+              "displayMode": "table",
+              "placement": "bottom"
+            },
+            "tooltip": {
+              "mode": "single"
+            }
+          },
+          "targets": [
+            {
+              "exemplar": true,
+              "expr": "rate(quota_disk_used{datacenter=~\"$Datacenter\", cluster=~\"$Cluster\", svm=~\"$SVM\", volume=~\"$Volume\", qtree=~\"$TopQtreeDiskUsedGrowth\"}[5m])",
+              "interval": "",
+              "legendFormat": "{{svm}} - {{volume}} - {{qtree}}",
+              "refId": "A"
+            }
+          ],
+          "title": "Top $TopResources Qtrees by Disk Used Growth",
+          "type": "timeseries"
         }
       ],
       "title": "Usage",
@@ -1004,6 +1092,29 @@
         "skipUrlSync": false,
         "sort": 0,
         "type": "query"
+      },
+      {
+        "allValue": null,
+        "current": {},
+        "datasource": "${DS_PROMETHEUS}",
+        "definition": "query_result(topk($TopResources, rate(quota_disk_used{datacenter=~\"$Datacenter\", cluster=~\"$Cluster\", svm=~\"$SVM\", volume=~\"$Volume\", qtree=~\"$Qtree\"}[${__range}])))",
+        "description": null,
+        "error": null,
+        "hide": 2,
+        "includeAll": true,
+        "label": null,
+        "multi": true,
+        "name": "TopQtreeDiskUsedGrowth",
+        "options": [],
+        "query": {
+          "query": "query_result(topk($TopResources, rate(quota_disk_used{datacenter=~\"$Datacenter\", cluster=~\"$Cluster\", svm=~\"$SVM\", volume=~\"$Volume\", qtree=~\"$Qtree\"}[${__range}])))",
+          "refId": "StandardVariableQuery"
+        },
+        "refresh": 1,
+        "regex": ".*qtree=\\\"(.*?)\\\".*",
+        "skipUrlSync": false,
+        "sort": 0,
+        "type": "query"
       }
     ]
   },
@@ -1027,5 +1138,5 @@
   "timezone": "",
   "title": "ONTAP: Qtree",
   "uid": "",
-  "version": 6
+  "version": 7
 }
\ No newline at end of file
diff --git a/grafana/dashboards/cmode/svm.json b/grafana/dashboards/cmode/svm.json
index 8e7cbda1..8025f04b 100644
--- a/grafana/dashboards/cmode/svm.json
+++ b/grafana/dashboards/cmode/svm.json
@@ -11406,7 +11406,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -11420,7 +11419,9 @@
                   }
                 ]
               },
-              "unit": "percentunit"
+              "unit": "percentunit",
+              "min": 0,
+              "max": 1
             },
             "overrides": []
           },
@@ -12357,8 +12358,9 @@
                   }
                 ]
               },
-              "unit": "percent"
-            },
+              "unit": "percent",
+              "min": 0,
+              "max": 100            },
             "overrides": []
           },
           "gridPos": {
@@ -12445,7 +12447,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -12533,7 +12537,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -12696,7 +12702,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -12710,7 +12715,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
diff --git a/grafana/dashboards/cmode/volume.json b/grafana/dashboards/cmode/volume.json
index d39bd4dd..8b919492 100644
--- a/grafana/dashboards/cmode/volume.json
+++ b/grafana/dashboards/cmode/volume.json
@@ -2782,7 +2782,9 @@
                   }
                 ]
               },
-              "unit": "percentunit"
+              "unit": "percentunit",
+              "min": 0,
+              "max": 1
             },
             "overrides": []
           },
@@ -2871,7 +2873,9 @@
                   }
                 ]
               },
-              "unit": "percentunit"
+              "unit": "percentunit",
+              "min": 0,
+              "max": 1
             },
             "overrides": []
           },
@@ -4115,7 +4119,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -4339,7 +4345,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -5094,7 +5102,6 @@
                 }
               },
               "mappings": [],
-              "min": 0,
               "thresholds": {
                 "mode": "absolute",
                 "steps": [
@@ -5108,7 +5115,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
diff --git a/grafana/dashboards/storagegrid/overview.json b/grafana/dashboards/storagegrid/overview.json
index c46c992a..7f2f22fe 100644
--- a/grafana/dashboards/storagegrid/overview.json
+++ b/grafana/dashboards/storagegrid/overview.json
@@ -1453,7 +1453,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },
@@ -1543,7 +1545,9 @@
                   }
                 ]
               },
-              "unit": "percent"
+              "unit": "percent",
+              "min": 0,
+              "max": 100
             },
             "overrides": []
           },


Test patch:
diff --git a/cmd/tools/grafana/dashboard_test.go b/cmd/tools/grafana/dashboard_test.go
index cba0d252..048bdd25 100644
--- a/cmd/tools/grafana/dashboard_test.go
+++ b/cmd/tools/grafana/dashboard_test.go
@@ -63,6 +63,11 @@ func TestUnitsAndExprMatch(t *testing.T) {
 		"_lag_time": {"", "s", "short"},
 	}
 
+	// Normalize rates to their base unit
+	rates := map[string]string{
+		"KiBs": "kbytes",
+	}
+
 	metricNames := make([]string, 0, len(mt.metricsByUnit))
 	for m := range mt.metricsByUnit {
 		metricNames = append(metricNames, m)
@@ -73,6 +78,20 @@ func TestUnitsAndExprMatch(t *testing.T) {
 		u := mt.metricsByUnit[metric]
 
 		failText := strings.Builder{}
+		// Normalize units if there are rates
+		for unit, listMetricLoc := range u.units {
+			normal, ok := rates[unit]
+			if !ok {
+				continue
+			}
+			list, ok := u.units[normal]
+			if !ok {
+				continue
+			}
+			delete(u.units, unit)
+			list = append(list, listMetricLoc...)
+			u.units[normal] = list
+		}
 		numUnits := len(u.units)
 		for unit, location := range u.units {
 			if unit == "" || unit == "none" {
@@ -740,7 +759,7 @@ func checkRate1m(t *testing.T, path string, data []byte) {
 	expressions := allExpressions(data)
 	for _, expr := range expressions {
 		if strings.Contains(expr.metric, "[1m]") {
-			t.Errorf("dashboard=%s, expr should not use rate of [1m] expr=%s", path, expr)
+			t.Errorf("dashboard=%s, expr should not use rate of [1m] expr=%s", path, expr.metric)
 		}
 	}
 }
@@ -782,3 +801,40 @@ func asTitle(id string) string {
 	replacer := strings.NewReplacer("[", ".", "]", "")
 	return replacer.Replace(path)
 }
+
+func TestPercentHasMinMax(t *testing.T) {
+	visitDashboards(
+		[]string{"../../../grafana/dashboards/cmode", "../../../grafana/dashboards/storagegrid"},
+		func(path string, data []byte) {
+			checkPercentHasMinMax(t, path, data)
+		})
+}
+
+func checkPercentHasMinMax(t *testing.T, path string, data []byte) {
+	dashPath := shortPath(path)
+
+	visitAllPanels(data, func(path string, key, value gjson.Result) {
+		panelType := value.Get("type").String()
+		if panelType != "timeseries" {
+			return
+		}
+		defaultUnit := value.Get("fieldConfig.defaults.unit").String()
+		if defaultUnit != "percent" && defaultUnit != "percentunit" {
+			return
+		}
+		min := value.Get("fieldConfig.defaults.min").String()
+		max := value.Get("fieldConfig.defaults.max").String()
+		if min != "0" {
+			t.Errorf(`dashboard=%s path=%s panel="%s" has unit=%s, min should be 0 got=%s`,
+				dashPath, path, value.Get("title").String(), defaultUnit, min)
+		}
+		if defaultUnit == "percent" && max != "100" {
+			t.Errorf(`dashboard=%s path=%s panel="%s" has unit=%s, max should be 100 got=%s`,
+				dashPath, path, value.Get("title").String(), defaultUnit, max)
+		}
+		if defaultUnit == "percentunit" && max != "1" {
+			t.Errorf(`dashboard=%s path=%s panel="%s" has unit=%s, max should be 1 got=%s`,
+				dashPath, path, value.Get("title").String(), defaultUnit, max)
+		}
+	})
+}