Skip to content

Commit f6ffb54

Browse files
TsadoqJenkins
authored andcommitted
graphing: Expose the raw to canonical metric name mapping
translate_metric_names walks each raw perf-data name to the canonical metric name a plug-in translation renames it to, and then returns a frozenset. The pairing it computed on the way - which raw column produced which canonical name - is discarded, and no caller can recover it, because several raw names may share one canonical name. Add map_metric_names, the same walk keeping the pairing, and reduce translate_metric_names to a frozenset over its values so the two cannot drift apart. A raw name no translation renames maps to itself, matching what _find_name_and_scale already falls back to, so every raw name has an entry and a caller never has to tell "not translated" from "unknown". No behaviour changes: every existing caller reads the same set as before. Jira: CMK-37694 Change-Id: I6e9b85cd9f9383a2b7c722f86835734271ea87dd
1 parent 7508890 commit f6ffb54

2 files changed

Lines changed: 57 additions & 7 deletions

File tree

cmk/gui/graphing/_engine_translations.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -179,18 +179,28 @@ def rrd_originals(
179179
]
180180

181181

182-
def translate_metric_names(
182+
def map_metric_names(
183183
check_command: str,
184184
raw_metric_names: Sequence[MetricName],
185185
registered_translations: Sequence[translations_v1.Translation],
186-
) -> frozenset[MetricName]:
186+
) -> Mapping[MetricName, MetricName]:
187187
specs = _specs_for_command(check_command, registered_translations)
188-
names: set[MetricName] = set()
189-
for metric_name in raw_metric_names:
190-
prefix, bare_name = _split_predict_prefix(metric_name)
188+
mapping: dict[MetricName, MetricName] = {}
189+
for raw_metric_name in raw_metric_names:
190+
prefix, bare_name = _split_predict_prefix(raw_metric_name)
191191
name, _scale = _find_name_and_scale(MetricName(bare_name), specs)
192-
names.add(MetricName(f"{prefix}{name}"))
193-
return frozenset(names)
192+
mapping[raw_metric_name] = MetricName(f"{prefix}{name}")
193+
return mapping
194+
195+
196+
def translate_metric_names(
197+
check_command: str,
198+
raw_metric_names: Sequence[MetricName],
199+
registered_translations: Sequence[translations_v1.Translation],
200+
) -> frozenset[MetricName]:
201+
return frozenset(
202+
map_metric_names(check_command, raw_metric_names, registered_translations).values()
203+
)
194204

195205

196206
def _scaled(value: float | None, scale: float) -> float | None:

tests/unit/cmk/gui/graphing/test_engine_translations.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from cmk.graphing_engine import MetricName
1010
from cmk.gui.graphing._engine_perfdata import RawPerformanceData, RawPerformanceValue
1111
from cmk.gui.graphing._engine_translations import (
12+
map_metric_names,
1213
rrd_originals,
1314
RRDOriginal,
1415
translate_metric_names,
@@ -46,6 +47,45 @@ def _original(name: str, scale: float) -> RRDOriginal:
4647
return RRDOriginal(metric_name=MetricName(name), scale=scale)
4748

4849

50+
def test_map_metric_names_pairs_raw_names_with_their_canonical_names() -> None:
51+
# A set of canonical names cannot say which raw column produced which name; the mapping can. A
52+
# raw name no translation renames is its own canonical name, so no raw name is dropped.
53+
assert dict(
54+
map_metric_names(
55+
_CHECK_COMMAND,
56+
[MetricName("old"), MetricName("untouched")],
57+
_registered({"old": translations.RenameTo("new")}),
58+
)
59+
) == {MetricName("old"): MetricName("new"), MetricName("untouched"): MetricName("untouched")}
60+
61+
62+
def test_two_raw_names_sharing_a_canonical_name_keep_their_own_entries() -> None:
63+
# The case the frozenset cannot express at all: it reports one name where two columns exist, so
64+
# a caller reading it back has no way to tell which of them it may ask an RRD for.
65+
assert dict(
66+
map_metric_names(
67+
_CHECK_COMMAND,
68+
[MetricName("if_in_octets"), MetricName("if_out_octets")],
69+
_registered({"~if_.*_octets": translations.RenameTo("if_octets")}),
70+
)
71+
) == {
72+
MetricName("if_in_octets"): MetricName("if_octets"),
73+
MetricName("if_out_octets"): MetricName("if_octets"),
74+
}
75+
76+
77+
def test_a_scaling_translation_leaves_the_name_alone() -> None:
78+
# A translation that only scales is still a translation, and a caller that resolves a name
79+
# through the mapping has to get the raw name back rather than nothing.
80+
assert dict(
81+
map_metric_names(
82+
_CHECK_COMMAND,
83+
[MetricName("mem")],
84+
_registered({"mem": translations.ScaleBy(1024)}),
85+
)
86+
) == {MetricName("mem"): MetricName("mem")}
87+
88+
4989
def test_metric_names_are_reported_under_their_canonical_name() -> None:
5090
assert translate_metric_names(
5191
_CHECK_COMMAND,

0 commit comments

Comments
 (0)