diff options
-rw-r--r-- | resources/tools/dash/app/pal/data/data.yaml | 60 | ||||
-rw-r--r-- | resources/tools/dash/app/pal/trending/graphs.py | 94 | ||||
-rw-r--r-- | resources/tools/dash/app/pal/trending/layout.py | 180 | ||||
-rw-r--r-- | resources/tools/dash/app/pal/trending/layout.yaml | 80 |
4 files changed, 311 insertions, 103 deletions
diff --git a/resources/tools/dash/app/pal/data/data.yaml b/resources/tools/dash/app/pal/data/data.yaml index 45e7f6b7ed..f639873fa8 100644 --- a/resources/tools/dash/app/pal/data/data.yaml +++ b/resources/tools/dash/app/pal/data/data.yaml @@ -48,46 +48,46 @@ trending-ndrpdr: - result_ndr_lower_rate_value - result_ndr_lower_bandwidth_unit - result_ndr_lower_bandwidth_value - - result_latency_reverse_pdr_90_avg + # - result_latency_reverse_pdr_90_avg - result_latency_reverse_pdr_90_hdrh - - result_latency_reverse_pdr_90_max - - result_latency_reverse_pdr_90_min - - result_latency_reverse_pdr_90_unit - - result_latency_reverse_pdr_50_avg + # - result_latency_reverse_pdr_90_max + # - result_latency_reverse_pdr_90_min + # - result_latency_reverse_pdr_90_unit + # - result_latency_reverse_pdr_50_avg - result_latency_reverse_pdr_50_hdrh - - result_latency_reverse_pdr_50_max - - result_latency_reverse_pdr_50_min - - result_latency_reverse_pdr_50_unit - - result_latency_reverse_pdr_10_avg + # - result_latency_reverse_pdr_50_max + # - result_latency_reverse_pdr_50_min + # - result_latency_reverse_pdr_50_unit + # - result_latency_reverse_pdr_10_avg - result_latency_reverse_pdr_10_hdrh - - result_latency_reverse_pdr_10_max - - result_latency_reverse_pdr_10_min - - result_latency_reverse_pdr_10_unit - - result_latency_reverse_pdr_0_avg + # - result_latency_reverse_pdr_10_max + # - result_latency_reverse_pdr_10_min + # - result_latency_reverse_pdr_10_unit + # - result_latency_reverse_pdr_0_avg - result_latency_reverse_pdr_0_hdrh - - result_latency_reverse_pdr_0_max - - result_latency_reverse_pdr_0_min - - result_latency_reverse_pdr_0_unit - - result_latency_forward_pdr_90_avg + # - result_latency_reverse_pdr_0_max + # - result_latency_reverse_pdr_0_min + # - result_latency_reverse_pdr_0_unit + # - result_latency_forward_pdr_90_avg - result_latency_forward_pdr_90_hdrh - - result_latency_forward_pdr_90_max - - result_latency_forward_pdr_90_min - - result_latency_forward_pdr_90_unit + # - result_latency_forward_pdr_90_max + # - result_latency_forward_pdr_90_min + # - result_latency_forward_pdr_90_unit - result_latency_forward_pdr_50_avg - result_latency_forward_pdr_50_hdrh - - result_latency_forward_pdr_50_max - - result_latency_forward_pdr_50_min + # - result_latency_forward_pdr_50_max + # - result_latency_forward_pdr_50_min - result_latency_forward_pdr_50_unit - - result_latency_forward_pdr_10_avg + # - result_latency_forward_pdr_10_avg - result_latency_forward_pdr_10_hdrh - - result_latency_forward_pdr_10_max - - result_latency_forward_pdr_10_min - - result_latency_forward_pdr_10_unit - - result_latency_forward_pdr_0_avg + # - result_latency_forward_pdr_10_max + # - result_latency_forward_pdr_10_min + # - result_latency_forward_pdr_10_unit + # - result_latency_forward_pdr_0_avg - result_latency_forward_pdr_0_hdrh - - result_latency_forward_pdr_0_max - - result_latency_forward_pdr_0_min - - result_latency_forward_pdr_0_unit + # - result_latency_forward_pdr_0_max + # - result_latency_forward_pdr_0_min + # - result_latency_forward_pdr_0_unit iterative-mrr: path: s3://fdio-docs-s3-cloudfront-index/csit/parquet/iterative_rls2202 columns: diff --git a/resources/tools/dash/app/pal/trending/graphs.py b/resources/tools/dash/app/pal/trending/graphs.py index 8cb96ea3b5..b71c3271a0 100644 --- a/resources/tools/dash/app/pal/trending/graphs.py +++ b/resources/tools/dash/app/pal/trending/graphs.py @@ -15,14 +15,12 @@ """ -import logging import plotly.graph_objects as go import pandas as pd import re from datetime import datetime from numpy import isnan -from dash import no_update from ..jumpavg import classify @@ -57,7 +55,7 @@ _ANOMALY_COLOR = { u"normal": 0.5, u"progression": 1.0 } -_COLORSCALE = [ +_COLORSCALE_TPUT = [ [0.00, u"red"], [0.33, u"red"], [0.33, u"white"], @@ -65,15 +63,27 @@ _COLORSCALE = [ [0.66, u"green"], [1.00, u"green"] ] +_TICK_TEXT_TPUT = [u"Regression", u"Normal", u"Progression"] +_COLORSCALE_LAT = [ + [0.00, u"green"], + [0.33, u"green"], + [0.33, u"white"], + [0.66, u"white"], + [0.66, u"red"], + [1.00, u"red"] +] +_TICK_TEXT_LAT = [u"Progression", u"Normal", u"Regression"] _VALUE = { "mrr": "result_receive_rate_rate_avg", "ndr": "result_ndr_lower_rate_value", - "pdr": "result_pdr_lower_rate_value" + "pdr": "result_pdr_lower_rate_value", + "pdr-lat": "result_latency_forward_pdr_50_avg" } _UNIT = { "mrr": "result_receive_rate_rate_unit", "ndr": "result_ndr_lower_rate_unit", - "pdr": "result_pdr_lower_rate_unit" + "pdr": "result_pdr_lower_rate_unit", + "pdr-lat": "result_latency_forward_pdr_50_unit" } @@ -133,7 +143,7 @@ def trending_tput(data: pd.DataFrame, sel:dict, layout: dict, start: datetime, """ if not sel: - return no_update, no_update + return None, None def _generate_traces(ttype: str, name: str, df: pd.DataFrame, start: datetime, end: datetime, color: str): @@ -151,10 +161,9 @@ def trending_tput(data: pd.DataFrame, sel:dict, layout: dict, start: datetime, hover = list() for _, row in df.iterrows(): hover_itm = ( - f"date: " - f"{row['start_time'].strftime('%d-%m-%Y %H:%M:%S')}<br>" - f"average [{row[_UNIT[ttype]]}]: " - f"{row[_VALUE[ttype]]}<br>" + f"date: {row['start_time'].strftime('%d-%m-%Y %H:%M:%S')}<br>" + f"<prop> [{row[_UNIT[ttype]]}]: {row[_VALUE[ttype]]}<br>" + f"<stdev>" f"{row['dut_type']}-ref: {row['dut_version']}<br>" f"csit-ref: {row['job']}/{row['build']}" ) @@ -165,15 +174,23 @@ def trending_tput(data: pd.DataFrame, sel:dict, layout: dict, start: datetime, ) else: stdev = "" - hover_itm = hover_itm.replace("<stdev>", stdev) + hover_itm = hover_itm.replace( + "<prop>", "latency" if ttype == "pdr-lat" else "average" + ).replace("<stdev>", stdev) hover.append(hover_itm) hover_trend = list() for avg, stdev in zip(trend_avg, trend_stdev): - hover_trend.append( - f"trend [pps]: {avg}<br>" - f"stdev [pps]: {stdev}" - ) + if ttype == "pdr-lat": + hover_trend.append( + f"trend [us]: {avg}<br>" + f"stdev [us]: {stdev}" + ) + else: + hover_trend.append( + f"trend [pps]: {avg}<br>" + f"stdev [pps]: {stdev}" + ) traces = [ go.Scatter( # Samples @@ -212,13 +229,12 @@ def trending_tput(data: pd.DataFrame, sel:dict, layout: dict, start: datetime, anomaly_x = list() anomaly_y = list() anomaly_color = list() - ticktext = [u"Regression", u"Normal", u"Progression"] for idx, anomaly in enumerate(anomalies): if anomaly in (u"regression", u"progression"): anomaly_x.append(x_axis[idx]) anomaly_y.append(trend_avg[idx]) anomaly_color.append(_ANOMALY_COLOR[anomaly]) - anomaly_color.append([0.0, 0.5, 1.0]) + anomaly_color.extend([0.0, 0.5, 1.0]) traces.append( go.Scatter( x=anomaly_x, @@ -232,7 +248,8 @@ def trending_tput(data: pd.DataFrame, sel:dict, layout: dict, start: datetime, u"size": 15, u"symbol": u"circle-open", u"color": anomaly_color, - u"colorscale": _COLORSCALE, + u"colorscale": _COLORSCALE_LAT \ + if ttype == "pdr-lat" else _COLORSCALE_TPUT, u"showscale": True, u"line": { u"width": 2 @@ -247,7 +264,8 @@ def trending_tput(data: pd.DataFrame, sel:dict, layout: dict, start: datetime, }, u"tickmode": u"array", u"tickvals": [0.167, 0.500, 0.833], - u"ticktext": ticktext, + u"ticktext": _TICK_TEXT_LAT \ + if ttype == "pdr-lat" else _TICK_TEXT_TPUT, u"ticks": u"", u"ticklen": 0, u"tickangle": -90, @@ -260,7 +278,8 @@ def trending_tput(data: pd.DataFrame, sel:dict, layout: dict, start: datetime, return traces # Generate graph: - fig = go.Figure() + fig_tput = None + fig_lat = None for idx, itm in enumerate(sel): phy = itm["phy"].split("-") if len(phy) == 4: @@ -293,18 +312,29 @@ def trending_tput(data: pd.DataFrame, sel:dict, layout: dict, start: datetime, f"{itm['phy']}-{itm['framesize']}-{itm['core']}-" f"{itm['test']}-{itm['testtype']}" ) - for trace in _generate_traces(itm['testtype'], name, df, start, end, - _COLORS[idx % len(_COLORS)]): - fig.add_trace(trace) - style={ - "vertical-align": "top", - "display": "inline-block", - "width": "80%", - "padding": "5px" - } + traces = _generate_traces( + itm["testtype"], name, df, start, end, _COLORS[idx % len(_COLORS)] + ) + if traces: + if not fig_tput: + fig_tput = go.Figure() + for trace in traces: + fig_tput.add_trace(trace) + + if itm["testtype"] == "pdr": + traces = _generate_traces( + "pdr-lat", name, df, start, end, _COLORS[idx % len(_COLORS)] + ) + if traces: + if not fig_lat: + fig_lat = go.Figure() + for trace in traces: + fig_lat.add_trace(trace) - layout = layout.get("plot-trending", dict()) - fig.update_layout(layout) + if fig_tput: + fig_tput.update_layout(layout.get("plot-trending-tput", dict())) + if fig_lat: + fig_lat.update_layout(layout.get("plot-trending-lat", dict())) - return fig, style + return fig_tput, fig_lat diff --git a/resources/tools/dash/app/pal/trending/layout.py b/resources/tools/dash/app/pal/trending/layout.py index 6be71ace15..377621425c 100644 --- a/resources/tools/dash/app/pal/trending/layout.py +++ b/resources/tools/dash/app/pal/trending/layout.py @@ -34,6 +34,11 @@ class Layout: """ """ + STYLE_HIDEN = {"display": "none"} + STYLE_BLOCK = {"display": "block"} + STYLE_INLINE ={"display": "inline-block", "width": "50%"} + NO_GRAPH = {"data": [], "layout": {}, "frames": []} + def __init__(self, app, html_layout_file, spec_file, graph_layout_file, data_spec_file): """ @@ -170,27 +175,52 @@ class Layout: id="loading-graph", children=[ dcc.Graph( - id="graph" + id="graph-tput", + style=self.STYLE_HIDEN + ), + dcc.Graph( + id="graph-latency", + style=self.STYLE_HIDEN ) ], type="circle" ), html.Div( children=[ - dcc.Markdown(""" - **Metadata** - - Click on data points in the graph. - """), - html.Pre( - id="hover-metadata" + html.Div( + id="div-tput-metadata", + children=[ + dcc.Markdown(""" + **Metadata** + + Click on data points in the graph. + """), + html.Pre( + id="tput-metadata" + ) + ], + style=self.STYLE_HIDEN + ), + html.Div( + id="div-latency-metadata", + children=[ + dcc.Markdown(""" + **Metadata** + + Click on data points in the graph. + """), + html.Pre( + id="latency-metadata" + ) + ], + style=self.STYLE_HIDEN ) ] ) ], style={ "vertical-align": "top", - "display": "none", + "display": "inline-block", "width": "80%", "padding": "5px" } @@ -471,13 +501,17 @@ class Layout: return _sync_checklists(opt, sel, all, "cl-ctrl-testtype") @app.callback( - Output("graph", "figure"), + Output("graph-tput", "figure"), + Output("graph-tput", "style"), + Output("div-tput-metadata", "style"), + Output("graph-latency", "figure"), + Output("graph-latency", "style"), + Output("div-latency-metadata", "style"), Output("selected-tests", "data"), # Store Output("cl-selected", "options"), # User selection Output("dd-ctrl-phy", "value"), Output("dd-ctrl-area", "value"), Output("dd-ctrl-test", "value"), - Output("div-plotting-area", "style"), State("selected-tests", "data"), # Store State("cl-selected", "value"), State("dd-ctrl-phy", "value"), @@ -511,24 +545,46 @@ class Layout: else: return list() + class RetunValue: + def __init__(self) -> None: + self._output = { + "graph-tput-figure": no_update, + "graph-tput-style": no_update, + "div-tput-metadata-style": no_update, + "graph-lat-figure": no_update, + "graph-lat-style": no_update, + "div-lat-metadata-style": no_update, + "selected-tests-data": no_update, + "cl-selected-options": no_update, + "dd-ctrl-phy-value": no_update, + "dd-ctrl-area-value": no_update, + "dd-ctrl-test-value": no_update, + } + + def value(self): + return tuple(self._output.values()) + + def set_values(self, kwargs: dict) -> None: + for key, val in kwargs.items(): + if key in self._output: + self._output[key] = val + else: + raise KeyError(f"The key {key} is not defined.") + + trigger_id = callback_context.triggered[0]["prop_id"].split(".")[0] - d_start = datetime( - int(d_start[0:4]), int(d_start[5:7]), int(d_start[8:10]) - ) - d_end = datetime( - int(d_end[0:4]), int(d_end[5:7]), int(d_end[8:10]) - ) + d_start = datetime(int(d_start[0:4]), int(d_start[5:7]), + int(d_start[8:10])) + d_end = datetime(int(d_end[0:4]), int(d_end[5:7]), int(d_end[8:10])) + + output = RetunValue() if trigger_id == "btn-ctrl-add": # Add selected test to the list of tests in store: if phy and area and test and cores and framesizes and testtypes: - - # TODO: Add validation - if store_sel is None: store_sel = list() - for core in cores: for framesize in framesizes: for ttype in testtypes: @@ -550,15 +606,32 @@ class Layout: "core": core.lower(), "testtype": ttype.lower() }) - return (no_update, store_sel, _list_tests(), None, - None, None, no_update) + output.set_values({ + "selected-tests-data": store_sel, + "cl-selected-options": _list_tests(), + "dd-ctrl-phy-value": None, + "dd-ctrl-area-value": None, + "dd-ctrl-test-value": None, + }) elif trigger_id in ("btn-sel-display", "dpr-period"): - fig, style = trending_tput( + fig_tput, fig_lat = trending_tput( self.data, store_sel, self.layout, d_start, d_end ) - return (fig, no_update, no_update, - no_update, no_update, no_update, style) + output.set_values({ + "graph-tput-figure": \ + fig_tput if fig_tput else self.NO_GRAPH, + "graph-tput-style": \ + self.STYLE_BLOCK if fig_tput else self.STYLE_HIDEN, + "div-tput-metadata-style": \ + self.STYLE_INLINE if fig_tput else self.STYLE_HIDEN, + "graph-lat-figure": \ + fig_lat if fig_lat else self.NO_GRAPH, + "graph-lat-style": \ + self.STYLE_BLOCK if fig_lat else self.STYLE_HIDEN, + "div-lat-metadata-style": \ + self.STYLE_INLINE if fig_lat else self.STYLE_HIDEN + }) elif trigger_id == "btn-sel-remove": if list_sel: @@ -568,26 +641,53 @@ class Layout: new_store_sel.append(item) store_sel = new_store_sel if store_sel: - fig, style = trending_tput( + fig_tput, fig_lat = trending_tput( self.data, store_sel, self.layout, d_start, d_end ) - return (fig, store_sel, _list_tests(), - no_update, no_update, no_update, style) + output.set_values({ + "graph-tput-figure": \ + fig_tput if fig_tput else self.NO_GRAPH, + "graph-tput-style": \ + self.STYLE_BLOCK if fig_tput else self.STYLE_HIDEN, + "div-tput-metadata-style": \ + self.STYLE_INLINE if fig_tput else self.STYLE_HIDEN, + "graph-lat-figure": \ + fig_lat if fig_lat else self.NO_GRAPH, + "graph-lat-style": \ + self.STYLE_BLOCK if fig_lat else self.STYLE_HIDEN, + "div-lat-metadata-style": \ + self.STYLE_INLINE if fig_lat else self.STYLE_HIDEN, + "selected-tests-data": store_sel, + "cl-selected-options": _list_tests() + }) else: - style={ - "vertical-align": "top", - "display": "none", - "width": "80%", - "padding": "5px" - } - return (no_update, store_sel, _list_tests(), - no_update, no_update, no_update, style) + output.set_values({ + "graph-tput-figure": self.NO_GRAPH, + "graph-tput-style": self.STYLE_HIDEN, + "div-tput-metadata-style": self.STYLE_HIDEN, + "graph-lat-figure": self.NO_GRAPH, + "graph-lat-style": self.STYLE_HIDEN, + "div-lat-metadata-style": self.STYLE_HIDEN, + "selected-tests-data": store_sel, + "cl-selected-options": _list_tests() + }) + + return output.value() + + @app.callback( + Output("tput-metadata", "children"), + Input("graph-tput", "clickData") + ) + def _show_tput_metadata(hover_data): + if not hover_data: + raise PreventUpdate + return json.dumps(hover_data, indent=2) @app.callback( - Output("hover-metadata", "children"), - Input("graph", "clickData") + Output("latency-metadata", "children"), + Input("graph-latency", "clickData") ) - def _show_metadata(hover_data): + def _show_latency_metadata(hover_data): if not hover_data: raise PreventUpdate return json.dumps(hover_data, indent=2) diff --git a/resources/tools/dash/app/pal/trending/layout.yaml b/resources/tools/dash/app/pal/trending/layout.yaml index 143ade1978..86a9f19a70 100644 --- a/resources/tools/dash/app/pal/trending/layout.yaml +++ b/resources/tools/dash/app/pal/trending/layout.yaml @@ -1,4 +1,4 @@ -plot-trending: +plot-trending-tput: title: "" titlefont: size: 16 @@ -75,3 +75,81 @@ plot-trending: plot_bgcolor: "#fff" hoverlabel: namelength: -1 + +plot-trending-lat: + title: "" + titlefont: + size: 16 + autosize: True + showlegend: True + # width: 1100 + height: 600 + yaxis: + showticklabels: True + tickformat: ".3s" + title: "Latency [us]" + hoverformat: ".5s" + gridcolor: "rgb(238, 238, 238)" + linecolor: "rgb(238, 238, 238)" + showline: True + zeroline: False + tickcolor: "rgb(238, 238, 238)" + linewidth: 1 + showgrid: True + xaxis: + title: 'Date [MMDD]' + type: "date" + autorange: True + fixedrange: False + showgrid: True + gridcolor: "rgb(238, 238, 238)" + showline: True + linecolor: "rgb(238, 238, 238)" + zeroline: False + linewidth: 1 + showticklabels: True + tickcolor: "rgb(238, 238, 238)" + tickmode: "auto" + tickformat: "%m%d" + rangeselector: + buttons: + - count: 14 + label: "2w" + step: "day" + stepmode: "backward" + - count: 1 + label: "1m" + step: "month" + stepmode: "backward" + - count: 2 + label: "2m" + step: "month" + stepmode: "backward" + - count: 3 + label: "3m" + step: "month" + stepmode: "backward" + - count: 4 + label: "4m" + step: "month" + stepmode: "backward" + - count: 5 + label: "5m" + step: "month" + stepmode: "backward" + - step: "all" + margin: + r: 20 + b: 0 + t: 5 + l: 70 + legend: + orientation: "h" + y: -0.18 + xanchor: "auto" + traceorder: "normal" + bordercolor: "rgb(238, 238, 238)" + paper_bgcolor: "#fff" + plot_bgcolor: "#fff" + hoverlabel: + namelength: -1 |