Skip to content

Commit 73cbce9

Browse files
Expose aggregated metrics (frequenz-floss#204)
Example:MetricSample(timestamp=datetime.datetime(2025, 7, 8, 9, 10, 20, tzinfo=datetime.timezone.utc), microgrid_id=13, component_id=262, metric='BATTERY_SOC_PCT_avg', value=43.198001861572266), MetricSample(timestamp=datetime.datetime(2025, 7, 8, 9, 10, 20, tzinfo=datetime.timezone.utc), microgrid_id=13, component_id=262, metric='BATTERY_SOC_PCT_min', value=42.70000076293945), MetricSample(timestamp=datetime.datetime(2025, 7, 8, 9, 10, 20, tzinfo=datetime.timezone.utc), microgrid_id=13, component_id=262, metric='BATTERY_SOC_PCT_max', value=43.29999923706055),
2 parents 3edb34d + 7714e38 commit 73cbce9

File tree

2 files changed

+25
-10
lines changed

2 files changed

+25
-10
lines changed

RELEASE_NOTES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
## New Features
1212

13-
<!-- Here goes the main new features and examples or instructions on how to use them -->
13+
* Expose aggregated metrics if available.
1414

1515
## Bug Fixes
1616

src/frequenz/client/reporting/_types.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
"""Types for the Reporting API client."""
55

6-
import math
76
from collections.abc import Iterable, Iterator
87
from dataclasses import dataclass
98
from datetime import datetime, timezone
@@ -70,11 +69,13 @@ def is_empty(self) -> bool:
7069
return True
7170
return False
7271

72+
# pylint: disable=too-many-locals
73+
# pylint: disable=too-many-branches
7374
def __iter__(self) -> Iterator[MetricSample]:
7475
"""Get generator that iterates over all values in the batch.
7576
76-
Note: So far only `SimpleMetricSample` in the `MetricSampleVariant`
77-
message is supported.
77+
`SimpleMetricSample` and `AggregatedMetricSample` in the
78+
`MetricSampleVariant` message is supported.
7879
7980
8081
Yields:
@@ -93,12 +94,26 @@ def __iter__(self) -> Iterator[MetricSample]:
9394
for sample in getattr(item, "metric_samples", []):
9495
ts = sample.sampled_at.ToDatetime().replace(tzinfo=timezone.utc)
9596
met = Metric.from_proto(sample.metric).name
96-
value = (
97-
sample.value.simple_metric.value
98-
if sample.value.HasField("simple_metric")
99-
else math.nan
100-
)
101-
yield MetricSample(ts, mid, cid, met, value)
97+
98+
# Handle simple_metric
99+
if sample.value.HasField("simple_metric"):
100+
value = sample.value.simple_metric.value
101+
yield MetricSample(ts, mid, cid, met, value)
102+
103+
# Handle aggregated_metric
104+
if sample.value.HasField("aggregated_metric"):
105+
agg = sample.value.aggregated_metric
106+
# Average value
107+
yield MetricSample(ts, mid, cid, f"{met}_avg", agg.avg_value)
108+
# Min value if present
109+
if agg.HasField("min_value"):
110+
yield MetricSample(ts, mid, cid, f"{met}_min", agg.min_value)
111+
# Max value if present
112+
if agg.HasField("max_value"):
113+
yield MetricSample(ts, mid, cid, f"{met}_max", agg.max_value)
114+
# Optionally yield individual raw values
115+
for i, raw in enumerate(agg.raw_values):
116+
yield MetricSample(ts, mid, cid, f"{met}_raw_{i}", raw)
102117

103118
if self.has_bounds:
104119
for i, bound in enumerate(sample.bounds):

0 commit comments

Comments
 (0)