From b156ff3b435a3ef1a899eb311a4dfb123d085cd0 Mon Sep 17 00:00:00 2001 From: David Butenhof Date: Fri, 18 Oct 2024 13:06:58 -0400 Subject: [PATCH] Support graphing multiple run comparisons When graphing metrics from two runs, the timestamps rarely align; so we add a `relative` option to convert the absolute metric timestamps into relative delta seconds from each run's start. --- backend/app/services/crucible_svc.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/backend/app/services/crucible_svc.py b/backend/app/services/crucible_svc.py index 3d20bd56..6a7556fd 100644 --- a/backend/app/services/crucible_svc.py +++ b/backend/app/services/crucible_svc.py @@ -64,14 +64,21 @@ class GraphList(BaseModel): omitted if all Graph objects specify a run ID. (This is most useful to select a set of graphs all for a single run ID.) + Normally the X axis will be the actual sample timestamp values; if you + specify relative=True, the X axis will be the duration from the first + timestamp of the metric series, in seconds. This allows graphs of similar + runs started at different times to be overlaid. + Fields: run: Specify the (default) run ID name: Specify a name for the set of graphs + relative: True for relative timescale in seconds graphs: a list of Graph objects """ run: Optional[str] = None name: str + relative: bool = False graphs: list[Graph] @@ -1208,6 +1215,7 @@ async def get_runs( "params": iparams, } ) + run["iterations"].sort(key=lambda i: i["iteration"]) run["params"] = common.render() try: run["begin_date"] = self._format_timestamp(run["begin"]) @@ -1904,10 +1912,19 @@ async def get_metrics_graph(self, graphdata: GraphList) -> dict[str, Any]: x = [] y = [] + first = None + for p in sorted(points, key=lambda a: a.begin): - x.extend( - [self._format_timestamp(p.begin), self._format_timestamp(p.end)] - ) + if graphdata.relative: + if not first: + first = p.begin + s = (p.begin - first) / 1000.0 + e = (p.end - first) / 1000.0 + x.extend([s, e]) + else: + x.extend( + [self._format_timestamp(p.begin), self._format_timestamp(p.end)] + ) y.extend([p.value, p.value]) y_max = max(y_max, p.value)