fix(prometheus): keep/drop patterns split on any whitespace, and a *_time_seconds value reads as a moment (#6423)
A pasted drop list whose line breaks had become spaces was stored as one pattern that matched nothing, so Home Assistant's two 526-series bookkeeping families filled the 1,000-series cap. No metric name holds whitespace, so patterns now split on spaces and tabs as well as lines and commas. Home Assistant names its Unix times *_time_seconds (e.g. homeassistant_last_updated_time_seconds), which read as "20751d 21h". is_moment() takes both suffixes, for the value shown and the chart axis. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -122,13 +122,23 @@ def fold_states(metric: str, rows: list[dict]) -> list[dict] | None:
|
||||
return folded
|
||||
|
||||
|
||||
# A series named for a moment holds Unix seconds, not a span of time: the
|
||||
# convention's *_timestamp_seconds, and the *_time_seconds some exporters use
|
||||
# (Home Assistant's homeassistant_last_updated_time_seconds).
|
||||
MOMENT_SUFFIXES = ("_timestamp_seconds", "_time_seconds")
|
||||
|
||||
|
||||
def is_moment(metric: str) -> bool:
|
||||
return metric.endswith(MOMENT_SUFFIXES)
|
||||
|
||||
|
||||
def shown_value(metric: str, value: float | None) -> dict:
|
||||
"""A series' value in its unit, from the Prometheus naming conventions.
|
||||
A *_timestamp_seconds is a moment: it comes back as `moment` for the page
|
||||
to show as "3m ago" in the reader's zone; 0 there means "never"."""
|
||||
A moment (is_moment) comes back as `moment` for the page to show as
|
||||
"3m ago" in the reader's zone; 0 there means "never"."""
|
||||
if value is None:
|
||||
return {"text": "—", "moment": None}
|
||||
if metric.endswith("_timestamp_seconds"):
|
||||
if is_moment(metric):
|
||||
if value <= 0:
|
||||
return {"text": "never", "moment": None}
|
||||
return {"text": "", "moment": datetime.fromtimestamp(value, timezone.utc)}
|
||||
@@ -184,11 +194,12 @@ def map_families(target: str, families: dict[str, prometheus.Family], keep: list
|
||||
# ── The form ─────────────────────────────────────────────────────────────────
|
||||
|
||||
def patterns(text: str) -> list[str]:
|
||||
"""Name patterns from a textarea: one per line or comma-separated."""
|
||||
"""Name patterns from a textarea: one per line, or separated by commas or
|
||||
spaces. A metric name never holds whitespace, so a paste that turned line
|
||||
breaks into spaces still reads as the patterns it was."""
|
||||
out: list[str] = []
|
||||
for line in (text or "").replace(",", "\n").splitlines():
|
||||
p = line.strip()
|
||||
if p and p not in out:
|
||||
for p in (text or "").replace(",", " ").split():
|
||||
if p not in out:
|
||||
out.append(p)
|
||||
return out
|
||||
|
||||
|
||||
Reference in New Issue
Block a user