From 19d6ffcf2a4268fd414cbe5109aafd043d7bb514 Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Mon, 13 Apr 2026 01:43:21 -0300 Subject: [PATCH] monitoring(overview): recenter climate/ups cards and gate stale offline climate data --- scripts/dashboards_render_atlas.py | 71 +++++++++----- .../monitoring/dashboards/atlas-overview.json | 94 +++++++++---------- .../monitoring/dashboards/atlas-power.json | 10 +- .../grafana-dashboard-overview.yaml | 94 +++++++++---------- .../monitoring/grafana-dashboard-power.yaml | 10 +- 5 files changed, 152 insertions(+), 127 deletions(-) diff --git a/scripts/dashboards_render_atlas.py b/scripts/dashboards_render_atlas.py index 7a15e271..99bbbc84 100644 --- a/scripts/dashboards_render_atlas.py +++ b/scripts/dashboards_render_atlas.py @@ -677,33 +677,46 @@ ANANKE_UPS_DISCHARGE_RISK_TETHYS = ups_discharge_risk_expr( ) CLIMATE_SENSOR_COUNT = "count(typhon_temperature_celsius) or on() vector(0)" CLIMATE_DEDUP_LABELS = "job,instance,pod,service,endpoint,namespace" -CLIMATE_TEMP_SERIES = ( +CLIMATE_CONTROLLER_ONLINE_SERIES = ( + f"max without ({CLIMATE_DEDUP_LABELS}) (typhon_controller_online)" +) +CLIMATE_ONLINE_FILTER = f"(({CLIMATE_CONTROLLER_ONLINE_SERIES}) > 0)" +CLIMATE_TEMP_RAW_SERIES = ( f"max without ({CLIMATE_DEDUP_LABELS}) (typhon_temperature_celsius != 0)" ) +CLIMATE_TEMP_SERIES = ( + f"({CLIMATE_TEMP_RAW_SERIES}) and on(controller_id,controller_name) {CLIMATE_ONLINE_FILTER}" +) CLIMATE_TEMP_FAHRENHEIT_SERIES = f"({CLIMATE_TEMP_SERIES}) * 9 / 5 + 32" -CLIMATE_PRESSURE_SERIES = ( +CLIMATE_PRESSURE_RAW_SERIES = ( f"max without ({CLIMATE_DEDUP_LABELS}) (typhon_vpd_kpa != 0)" ) -CLIMATE_HUMIDITY_SERIES = ( +CLIMATE_PRESSURE_SERIES = ( + f"({CLIMATE_PRESSURE_RAW_SERIES}) and on(controller_id,controller_name) {CLIMATE_ONLINE_FILTER}" +) +CLIMATE_HUMIDITY_RAW_SERIES = ( f"max without ({CLIMATE_DEDUP_LABELS}) (typhon_relative_humidity_percent != 0)" ) -CLIMATE_TEMP_MAX = f"max({CLIMATE_TEMP_SERIES}) or on() vector(0)" -CLIMATE_TEMP_FAHRENHEIT_MAX = f"max({CLIMATE_TEMP_FAHRENHEIT_SERIES}) or on() vector(0)" -CLIMATE_PRESSURE_CURRENT = f"max({CLIMATE_PRESSURE_SERIES}) or on() vector(0)" -CLIMATE_HUMIDITY_MAX = f"max({CLIMATE_HUMIDITY_SERIES}) or on() vector(0)" -CLIMATE_TEMP_MIN_BOUND_SERIES = f"(min_over_time({CLIMATE_TEMP_SERIES}[$__range]) - 0.08)" -CLIMATE_TEMP_MAX_BOUND_SERIES = f"(max_over_time({CLIMATE_TEMP_SERIES}[$__range]) + 0.08)" +CLIMATE_HUMIDITY_SERIES = ( + f"({CLIMATE_HUMIDITY_RAW_SERIES}) and on(controller_id,controller_name) {CLIMATE_ONLINE_FILTER}" +) +CLIMATE_TEMP_MAX = f"max({CLIMATE_TEMP_SERIES})" +CLIMATE_TEMP_FAHRENHEIT_MAX = f"max({CLIMATE_TEMP_FAHRENHEIT_SERIES})" +CLIMATE_PRESSURE_CURRENT = f"max({CLIMATE_PRESSURE_SERIES})" +CLIMATE_HUMIDITY_MAX = f"max({CLIMATE_HUMIDITY_SERIES})" +CLIMATE_TEMP_MIN_BOUND_SERIES = f"(min_over_time(({CLIMATE_TEMP_SERIES})[$__range:]) - 0.08)" +CLIMATE_TEMP_MAX_BOUND_SERIES = f"(max_over_time(({CLIMATE_TEMP_SERIES})[$__range:]) + 0.08)" CLIMATE_HUMIDITY_MIN_BOUND_SERIES = ( - f"clamp_min((min_over_time({CLIMATE_HUMIDITY_SERIES}[$__range]) - 0.35), 0)" + f"clamp_min((min_over_time(({CLIMATE_HUMIDITY_SERIES})[$__range:]) - 0.35), 0)" ) CLIMATE_HUMIDITY_MAX_BOUND_SERIES = ( - f"clamp_max((max_over_time({CLIMATE_HUMIDITY_SERIES}[$__range]) + 0.35), 100)" + f"clamp_max((max_over_time(({CLIMATE_HUMIDITY_SERIES})[$__range:]) + 0.35), 100)" ) CLIMATE_PRESSURE_MIN_BOUND_SERIES = ( - f"clamp_min((min_over_time({CLIMATE_PRESSURE_SERIES}[$__range]) - 0.03), 0)" + f"clamp_min((min_over_time(({CLIMATE_PRESSURE_SERIES})[$__range:]) - 0.03), 0)" ) CLIMATE_PRESSURE_MAX_BOUND_SERIES = ( - f"(max_over_time({CLIMATE_PRESSURE_SERIES}[$__range]) + 0.03)" + f"(max_over_time(({CLIMATE_PRESSURE_SERIES})[$__range:]) + 0.03)" ) CLIMATE_FAN_OUTLET_CURRENT = ( f'max(max without ({CLIMATE_DEDUP_LABELS}) (typhon_fan_speed_level{{fan_group="outlet"}})) or on() vector(0)' @@ -1048,6 +1061,12 @@ def canvas_metric_grid_panel( if color_fields is None: color_fields = [targets[0]["legendFormat"], targets[1]["legendFormat"], targets[2]["legendFormat"], targets[3]["legendFormat"]] + panel_h = int(grid.get("h", 6)) + # Keep the 2x2 block centered enough across the two panel heights we use in overview. + x_left = 18 + x_right = x_left + 156 + y_top = 24 if panel_h <= 5 else 28 + y_row2 = y_top + 58 def text_element(name, text, left, top): return { @@ -1132,14 +1151,14 @@ def canvas_metric_grid_panel( "type": "frame", "name": f"{title} frame", "elements": [ - text_element("Cell 1 label", targets[0]["legendFormat"], 12, 18), - metric_element("Cell 1", targets[0]["legendFormat"], 12, 32), - text_element("Cell 2 label", targets[1]["legendFormat"], 168, 18), - metric_element("Cell 2", targets[1]["legendFormat"], 168, 32), - text_element("Cell 3 label", targets[2]["legendFormat"], 12, 76), - metric_element("Cell 3", targets[2]["legendFormat"], 12, 90), - text_element("Cell 4 label", targets[3]["legendFormat"], 168, 76), - metric_element("Cell 4", targets[3]["legendFormat"], 168, 90), + text_element("Cell 1 label", targets[0]["legendFormat"], x_left, y_top), + metric_element("Cell 1", targets[0]["legendFormat"], x_left, y_top + 14), + text_element("Cell 2 label", targets[1]["legendFormat"], x_right, y_top), + metric_element("Cell 2", targets[1]["legendFormat"], x_right, y_top + 14), + text_element("Cell 3 label", targets[2]["legendFormat"], x_left, y_row2), + metric_element("Cell 3", targets[2]["legendFormat"], x_left, y_row2 + 14), + text_element("Cell 4 label", targets[3]["legendFormat"], x_right, y_row2), + metric_element("Cell 4", targets[3]["legendFormat"], x_right, y_row2 + 14), ], "background": {"color": {"fixed": "transparent"}}, "border": {"color": {"fixed": "transparent"}}, @@ -1814,7 +1833,10 @@ def build_overview(): {"matcher": {"id": "byName", "options": "Pressure"}, "properties": [{"id": "unit", "value": "suffix:kPa"}]}, ], links=link_to("atlas-power"), - description="Current tent values in a fixed 2x2 layout: Temp °C / Temp °F / Humidity / Pressure.", + description=( + "Current tent values in a fixed 2x2 layout: Temp °C / Temp °F / Humidity / Pressure. " + "Values only render when Typhon reports the controller online." + ), metric_size=30, ) ) @@ -1907,7 +1929,10 @@ def build_overview(): legend_display="list", legend_placement="bottom", links=link_to("atlas-power"), - description="Temperature on left axis, humidity and pressure on right axis with dynamic bound series so small swings remain visible.", + description=( + "Temperature on left axis, humidity and pressure on right axis with dynamic bound series so small swings remain visible. " + "Series are filtered to online controllers to avoid plotting stale offline snapshots." + ), ) ) panels.append( diff --git a/services/monitoring/dashboards/atlas-overview.json b/services/monitoring/dashboards/atlas-overview.json index b91ec265..02684f4a 100644 --- a/services/monitoring/dashboards/atlas-overview.json +++ b/services/monitoring/dashboards/atlas-overview.json @@ -1194,8 +1194,8 @@ "vertical": "top" }, "placement": { - "left": 12, - "top": 18, + "left": 18, + "top": 24, "width": 146, "height": 14 }, @@ -1230,8 +1230,8 @@ "vertical": "top" }, "placement": { - "left": 12, - "top": 32, + "left": 18, + "top": 38, "width": 146, "height": 42 }, @@ -1269,8 +1269,8 @@ "vertical": "top" }, "placement": { - "left": 168, - "top": 18, + "left": 174, + "top": 24, "width": 146, "height": 14 }, @@ -1305,8 +1305,8 @@ "vertical": "top" }, "placement": { - "left": 168, - "top": 32, + "left": 174, + "top": 38, "width": 146, "height": 42 }, @@ -1344,8 +1344,8 @@ "vertical": "top" }, "placement": { - "left": 12, - "top": 76, + "left": 18, + "top": 82, "width": 146, "height": 14 }, @@ -1380,8 +1380,8 @@ "vertical": "top" }, "placement": { - "left": 12, - "top": 90, + "left": 18, + "top": 96, "width": 146, "height": 42 }, @@ -1419,8 +1419,8 @@ "vertical": "top" }, "placement": { - "left": 168, - "top": 76, + "left": 174, + "top": 82, "width": 146, "height": 14 }, @@ -1455,8 +1455,8 @@ "vertical": "top" }, "placement": { - "left": 168, - "top": 90, + "left": 174, + "top": 96, "width": 146, "height": 42 }, @@ -1579,25 +1579,25 @@ "targets": [ { "refId": "A", - "expr": "max(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) or on() vector(0)", + "expr": "max((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))", "legendFormat": "Temp \u00b0C", "instant": true }, { "refId": "B", - "expr": "max((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) * 9 / 5 + 32) or on() vector(0)", + "expr": "max(((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)) * 9 / 5 + 32)", "legendFormat": "Temp \u00b0F", "instant": true }, { "refId": "C", - "expr": "max(max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) or on() vector(0)", + "expr": "max((max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))", "legendFormat": "Humidity", "instant": true }, { "refId": "D", - "expr": "max(max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) or on() vector(0)", + "expr": "max((max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))", "legendFormat": "Pressure", "instant": true } @@ -1690,8 +1690,8 @@ "vertical": "top" }, "placement": { - "left": 12, - "top": 18, + "left": 18, + "top": 28, "width": 146, "height": 14 }, @@ -1726,8 +1726,8 @@ "vertical": "top" }, "placement": { - "left": 12, - "top": 32, + "left": 18, + "top": 42, "width": 146, "height": 42 }, @@ -1765,8 +1765,8 @@ "vertical": "top" }, "placement": { - "left": 168, - "top": 18, + "left": 174, + "top": 28, "width": 146, "height": 14 }, @@ -1801,8 +1801,8 @@ "vertical": "top" }, "placement": { - "left": 168, - "top": 32, + "left": 174, + "top": 42, "width": 146, "height": 42 }, @@ -1840,8 +1840,8 @@ "vertical": "top" }, "placement": { - "left": 12, - "top": 76, + "left": 18, + "top": 86, "width": 146, "height": 14 }, @@ -1876,8 +1876,8 @@ "vertical": "top" }, "placement": { - "left": 12, - "top": 90, + "left": 18, + "top": 100, "width": 146, "height": 42 }, @@ -1915,8 +1915,8 @@ "vertical": "top" }, "placement": { - "left": 168, - "top": 76, + "left": 174, + "top": 86, "width": 146, "height": 14 }, @@ -1951,8 +1951,8 @@ "vertical": "top" }, "placement": { - "left": 168, - "top": 90, + "left": 174, + "top": 100, "width": 146, "height": 42 }, @@ -2002,7 +2002,7 @@ "targetBlank": true } ], - "description": "Current tent values in a fixed 2x2 layout: Temp \u00b0C / Temp \u00b0F / Humidity / Pressure." + "description": "Current tent values in a fixed 2x2 layout: Temp \u00b0C / Temp \u00b0F / Humidity / Pressure. Values only render when Typhon reports the controller online." }, { "id": 43, @@ -2021,47 +2021,47 @@ "targets": [ { "refId": "A", - "expr": "max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)", + "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)", "legendFormat": "C" }, { "refId": "B", - "expr": "max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)", + "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)", "legendFormat": "RH" }, { "refId": "C", - "expr": "max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)", + "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)", "legendFormat": "P" }, { "refId": "D", - "expr": "(min_over_time(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)[$__range]) - 0.08)", + "expr": "(min_over_time(((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))[$__range:]) - 0.08)", "legendFormat": "C bound min" }, { "refId": "E", - "expr": "(max_over_time(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)[$__range]) + 0.08)", + "expr": "(max_over_time(((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))[$__range:]) + 0.08)", "legendFormat": "C bound max" }, { "refId": "F", - "expr": "clamp_min((min_over_time(max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)[$__range]) - 0.35), 0)", + "expr": "clamp_min((min_over_time(((max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))[$__range:]) - 0.35), 0)", "legendFormat": "RH bound min" }, { "refId": "G", - "expr": "clamp_max((max_over_time(max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)[$__range]) + 0.35), 100)", + "expr": "clamp_max((max_over_time(((max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))[$__range:]) + 0.35), 100)", "legendFormat": "RH bound max" }, { "refId": "H", - "expr": "clamp_min((min_over_time(max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)[$__range]) - 0.03), 0)", + "expr": "clamp_min((min_over_time(((max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))[$__range:]) - 0.03), 0)", "legendFormat": "P bound min" }, { "refId": "I", - "expr": "(max_over_time(max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)[$__range]) + 0.03)", + "expr": "(max_over_time(((max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))[$__range:]) + 0.03)", "legendFormat": "P bound max" } ], @@ -2301,7 +2301,7 @@ "targetBlank": true } ], - "description": "Temperature on left axis, humidity and pressure on right axis with dynamic bound series so small swings remain visible." + "description": "Temperature on left axis, humidity and pressure on right axis with dynamic bound series so small swings remain visible. Series are filtered to online controllers to avoid plotting stale offline snapshots." }, { "id": 140, diff --git a/services/monitoring/dashboards/atlas-power.json b/services/monitoring/dashboards/atlas-power.json index a8ce6cdf..86d0d9bd 100644 --- a/services/monitoring/dashboards/atlas-power.json +++ b/services/monitoring/dashboards/atlas-power.json @@ -163,7 +163,7 @@ }, "targets": [ { - "expr": "label_replace((max(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) or on() vector(0)), \"metric\", \"Temp \u00b0C\", \"__name__\", \".*\") or label_replace((max((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) * 9 / 5 + 32) or on() vector(0)), \"metric\", \"Temp \u00b0F\", \"__name__\", \".*\") or label_replace((max(max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) or on() vector(0)), \"metric\", \"Humidity\", \"__name__\", \".*\") or label_replace((max(max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) or on() vector(0)), \"metric\", \"Pressure\", \"__name__\", \".*\")", + "expr": "label_replace((max((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))), \"metric\", \"Temp \u00b0C\", \"__name__\", \".*\") or label_replace((max(((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)) * 9 / 5 + 32)), \"metric\", \"Temp \u00b0F\", \"__name__\", \".*\") or label_replace((max((max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))), \"metric\", \"Humidity\", \"__name__\", \".*\") or label_replace((max((max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))), \"metric\", \"Pressure\", \"__name__\", \".*\")", "refId": "A", "legendFormat": "{{metric}}", "instant": true @@ -283,22 +283,22 @@ "targets": [ { "refId": "A", - "expr": "max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)", + "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)", "legendFormat": "Temperature (\u00b0C)" }, { "refId": "B", - "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) * 9 / 5 + 32", + "expr": "((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)) * 9 / 5 + 32", "legendFormat": "Temperature (\u00b0F)" }, { "refId": "C", - "expr": "max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)", + "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)", "legendFormat": "Humidity (%)" }, { "refId": "D", - "expr": "max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)", + "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)", "legendFormat": "Pressure (VPD kPa)" } ], diff --git a/services/monitoring/grafana-dashboard-overview.yaml b/services/monitoring/grafana-dashboard-overview.yaml index b6e59c80..40469a8e 100644 --- a/services/monitoring/grafana-dashboard-overview.yaml +++ b/services/monitoring/grafana-dashboard-overview.yaml @@ -1203,8 +1203,8 @@ data: "vertical": "top" }, "placement": { - "left": 12, - "top": 18, + "left": 18, + "top": 24, "width": 146, "height": 14 }, @@ -1239,8 +1239,8 @@ data: "vertical": "top" }, "placement": { - "left": 12, - "top": 32, + "left": 18, + "top": 38, "width": 146, "height": 42 }, @@ -1278,8 +1278,8 @@ data: "vertical": "top" }, "placement": { - "left": 168, - "top": 18, + "left": 174, + "top": 24, "width": 146, "height": 14 }, @@ -1314,8 +1314,8 @@ data: "vertical": "top" }, "placement": { - "left": 168, - "top": 32, + "left": 174, + "top": 38, "width": 146, "height": 42 }, @@ -1353,8 +1353,8 @@ data: "vertical": "top" }, "placement": { - "left": 12, - "top": 76, + "left": 18, + "top": 82, "width": 146, "height": 14 }, @@ -1389,8 +1389,8 @@ data: "vertical": "top" }, "placement": { - "left": 12, - "top": 90, + "left": 18, + "top": 96, "width": 146, "height": 42 }, @@ -1428,8 +1428,8 @@ data: "vertical": "top" }, "placement": { - "left": 168, - "top": 76, + "left": 174, + "top": 82, "width": 146, "height": 14 }, @@ -1464,8 +1464,8 @@ data: "vertical": "top" }, "placement": { - "left": 168, - "top": 90, + "left": 174, + "top": 96, "width": 146, "height": 42 }, @@ -1588,25 +1588,25 @@ data: "targets": [ { "refId": "A", - "expr": "max(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) or on() vector(0)", + "expr": "max((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))", "legendFormat": "Temp \u00b0C", "instant": true }, { "refId": "B", - "expr": "max((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) * 9 / 5 + 32) or on() vector(0)", + "expr": "max(((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)) * 9 / 5 + 32)", "legendFormat": "Temp \u00b0F", "instant": true }, { "refId": "C", - "expr": "max(max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) or on() vector(0)", + "expr": "max((max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))", "legendFormat": "Humidity", "instant": true }, { "refId": "D", - "expr": "max(max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) or on() vector(0)", + "expr": "max((max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))", "legendFormat": "Pressure", "instant": true } @@ -1699,8 +1699,8 @@ data: "vertical": "top" }, "placement": { - "left": 12, - "top": 18, + "left": 18, + "top": 28, "width": 146, "height": 14 }, @@ -1735,8 +1735,8 @@ data: "vertical": "top" }, "placement": { - "left": 12, - "top": 32, + "left": 18, + "top": 42, "width": 146, "height": 42 }, @@ -1774,8 +1774,8 @@ data: "vertical": "top" }, "placement": { - "left": 168, - "top": 18, + "left": 174, + "top": 28, "width": 146, "height": 14 }, @@ -1810,8 +1810,8 @@ data: "vertical": "top" }, "placement": { - "left": 168, - "top": 32, + "left": 174, + "top": 42, "width": 146, "height": 42 }, @@ -1849,8 +1849,8 @@ data: "vertical": "top" }, "placement": { - "left": 12, - "top": 76, + "left": 18, + "top": 86, "width": 146, "height": 14 }, @@ -1885,8 +1885,8 @@ data: "vertical": "top" }, "placement": { - "left": 12, - "top": 90, + "left": 18, + "top": 100, "width": 146, "height": 42 }, @@ -1924,8 +1924,8 @@ data: "vertical": "top" }, "placement": { - "left": 168, - "top": 76, + "left": 174, + "top": 86, "width": 146, "height": 14 }, @@ -1960,8 +1960,8 @@ data: "vertical": "top" }, "placement": { - "left": 168, - "top": 90, + "left": 174, + "top": 100, "width": 146, "height": 42 }, @@ -2011,7 +2011,7 @@ data: "targetBlank": true } ], - "description": "Current tent values in a fixed 2x2 layout: Temp \u00b0C / Temp \u00b0F / Humidity / Pressure." + "description": "Current tent values in a fixed 2x2 layout: Temp \u00b0C / Temp \u00b0F / Humidity / Pressure. Values only render when Typhon reports the controller online." }, { "id": 43, @@ -2030,47 +2030,47 @@ data: "targets": [ { "refId": "A", - "expr": "max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)", + "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)", "legendFormat": "C" }, { "refId": "B", - "expr": "max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)", + "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)", "legendFormat": "RH" }, { "refId": "C", - "expr": "max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)", + "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)", "legendFormat": "P" }, { "refId": "D", - "expr": "(min_over_time(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)[$__range]) - 0.08)", + "expr": "(min_over_time(((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))[$__range:]) - 0.08)", "legendFormat": "C bound min" }, { "refId": "E", - "expr": "(max_over_time(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)[$__range]) + 0.08)", + "expr": "(max_over_time(((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))[$__range:]) + 0.08)", "legendFormat": "C bound max" }, { "refId": "F", - "expr": "clamp_min((min_over_time(max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)[$__range]) - 0.35), 0)", + "expr": "clamp_min((min_over_time(((max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))[$__range:]) - 0.35), 0)", "legendFormat": "RH bound min" }, { "refId": "G", - "expr": "clamp_max((max_over_time(max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)[$__range]) + 0.35), 100)", + "expr": "clamp_max((max_over_time(((max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))[$__range:]) + 0.35), 100)", "legendFormat": "RH bound max" }, { "refId": "H", - "expr": "clamp_min((min_over_time(max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)[$__range]) - 0.03), 0)", + "expr": "clamp_min((min_over_time(((max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))[$__range:]) - 0.03), 0)", "legendFormat": "P bound min" }, { "refId": "I", - "expr": "(max_over_time(max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)[$__range]) + 0.03)", + "expr": "(max_over_time(((max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))[$__range:]) + 0.03)", "legendFormat": "P bound max" } ], @@ -2310,7 +2310,7 @@ data: "targetBlank": true } ], - "description": "Temperature on left axis, humidity and pressure on right axis with dynamic bound series so small swings remain visible." + "description": "Temperature on left axis, humidity and pressure on right axis with dynamic bound series so small swings remain visible. Series are filtered to online controllers to avoid plotting stale offline snapshots." }, { "id": 140, diff --git a/services/monitoring/grafana-dashboard-power.yaml b/services/monitoring/grafana-dashboard-power.yaml index 2ad454c1..9c100b64 100644 --- a/services/monitoring/grafana-dashboard-power.yaml +++ b/services/monitoring/grafana-dashboard-power.yaml @@ -172,7 +172,7 @@ data: }, "targets": [ { - "expr": "label_replace((max(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) or on() vector(0)), \"metric\", \"Temp \u00b0C\", \"__name__\", \".*\") or label_replace((max((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) * 9 / 5 + 32) or on() vector(0)), \"metric\", \"Temp \u00b0F\", \"__name__\", \".*\") or label_replace((max(max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) or on() vector(0)), \"metric\", \"Humidity\", \"__name__\", \".*\") or label_replace((max(max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) or on() vector(0)), \"metric\", \"Pressure\", \"__name__\", \".*\")", + "expr": "label_replace((max((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))), \"metric\", \"Temp \u00b0C\", \"__name__\", \".*\") or label_replace((max(((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)) * 9 / 5 + 32)), \"metric\", \"Temp \u00b0F\", \"__name__\", \".*\") or label_replace((max((max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))), \"metric\", \"Humidity\", \"__name__\", \".*\") or label_replace((max((max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0))), \"metric\", \"Pressure\", \"__name__\", \".*\")", "refId": "A", "legendFormat": "{{metric}}", "instant": true @@ -292,22 +292,22 @@ data: "targets": [ { "refId": "A", - "expr": "max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)", + "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)", "legendFormat": "Temperature (\u00b0C)" }, { "refId": "B", - "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) * 9 / 5 + 32", + "expr": "((max without (job,instance,pod,service,endpoint,namespace) (typhon_temperature_celsius != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)) * 9 / 5 + 32", "legendFormat": "Temperature (\u00b0F)" }, { "refId": "C", - "expr": "max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)", + "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_relative_humidity_percent != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)", "legendFormat": "Humidity (%)" }, { "refId": "D", - "expr": "max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)", + "expr": "(max without (job,instance,pod,service,endpoint,namespace) (typhon_vpd_kpa != 0)) and on(controller_id,controller_name) ((max without (job,instance,pod,service,endpoint,namespace) (typhon_controller_online)) > 0)", "legendFormat": "Pressure (VPD kPa)" } ],