From f578663642305f144f76ddadf0370701147f18ff Mon Sep 17 00:00:00 2001 From: Tibor Frank Date: Mon, 24 Apr 2023 12:07:53 +0200 Subject: [PATCH] C-Dash: Latency in coverage tables - Display latency on demand Signed-off-by: Tibor Frank Change-Id: I5152d1f6c843f6b1ffac5818e1de76a701c7ccf1 --- csit.infra.dash/app/cdash/comparisons/layout.py | 2 +- csit.infra.dash/app/cdash/coverage/layout.py | 69 ++++++++++++++-- csit.infra.dash/app/cdash/coverage/tables.py | 100 ++++++------------------ csit.infra.dash/app/cdash/report/layout.py | 2 +- csit.infra.dash/app/cdash/trending/layout.py | 2 +- 5 files changed, 88 insertions(+), 87 deletions(-) diff --git a/csit.infra.dash/app/cdash/comparisons/layout.py b/csit.infra.dash/app/cdash/comparisons/layout.py index 452afad1af..d78123b187 100644 --- a/csit.infra.dash/app/cdash/comparisons/layout.py +++ b/csit.infra.dash/app/cdash/comparisons/layout.py @@ -737,7 +737,7 @@ class Layout: (selected["reference"]["set"] == True) and (c_sel["set"] == True) ) - except (KeyError, IndexError): + except (KeyError, IndexError, AttributeError): pass if process_url: ctrl_panel.set({ diff --git a/csit.infra.dash/app/cdash/coverage/layout.py b/csit.infra.dash/app/cdash/coverage/layout.py index f519f5a8ac..a5e095f0c0 100644 --- a/csit.infra.dash/app/cdash/coverage/layout.py +++ b/csit.infra.dash/app/cdash/coverage/layout.py @@ -48,7 +48,8 @@ CP_PARAMS = { "phy-val": str(), "area-opt": list(), "area-dis": True, - "area-val": str() + "area-val": str(), + "show-latency": ["show_latency", ] } @@ -342,16 +343,45 @@ class Layout: size="sm" ) ] + ), + dbc.Row( + class_name="g-0 p-1", + children=[ + dbc.InputGroup( + [ + dbc.InputGroupText("Latency"), + dbc.Checklist( + id="show-latency", + options=[{ + "value": "show_latency", + "label": "Show Latency" + }], + value=["show_latency"], + inline=True, + class_name="ms-2" + ) + ], + style={"align-items": "center"}, + size="sm" + ) + ] ) ] - def _get_plotting_area(self, selected: dict, url: str) -> list: + def _get_plotting_area( + self, + selected: dict, + url: str, + show_latency: bool + ) -> list: """Generate the plotting area with all its content. :param selected: Selected parameters of tests. :param url: URL to be displayed in the modal window. + :param show_latency: If True, latency is displayed in the tables. :type selected: dict :type url: str + :type show_latency: bool :returns: List of rows with elements to be displayed in the plotting area. :rtype: list @@ -361,7 +391,7 @@ class Layout: return [ dbc.Row( - children=coverage_tables(self._data, selected), + children=coverage_tables(self._data, selected, show_latency), class_name="g-0 p-0", ), dbc.Row( @@ -441,6 +471,7 @@ class Layout: Output({"type": "ctrl-dd", "index": "area"}, "options"), Output({"type": "ctrl-dd", "index": "area"}, "disabled"), Output({"type": "ctrl-dd", "index": "area"}, "value"), + Output("show-latency", "value"), ], [ State("store-control-panel", "data"), @@ -448,6 +479,7 @@ class Layout: ], [ Input("url", "href"), + Input("show-latency", "value"), Input({"type": "ctrl-dd", "index": ALL}, "value") ] ) @@ -455,6 +487,7 @@ class Layout: control_panel: dict, selected: dict, href: str, + show_latency: list, *_ ) -> tuple: """Update the application when the event is detected. @@ -477,8 +510,9 @@ class Layout: if trigger.type == "url" and url_params: try: + show_latency = literal_eval(url_params["show_latency"][0]) selected = literal_eval(url_params["selection"][0]) - except (KeyError, IndexError): + except (KeyError, IndexError, AttributeError): pass if selected: ctrl_panel.set({ @@ -508,9 +542,13 @@ class Layout: [selected["phy"]] ) ], - "area-dis": False + "area-dis": False, + "show-latency": show_latency }) on_draw = True + elif trigger.type == "show-latency": + ctrl_panel.set({"show-latency": show_latency}) + on_draw = True elif trigger.type == "ctrl-dd": if trigger.idx == "rls": try: @@ -610,7 +648,14 @@ class Layout: if selected: plotting_area = self._get_plotting_area( selected, - gen_new_url(parsed_url, {"selection": selected}) + gen_new_url( + parsed_url, + { + "selection": selected, + "show_latency": show_latency + } + ), + show_latency=bool(show_latency) ) else: plotting_area = C.PLACEHOLDER @@ -639,15 +684,18 @@ class Layout: @app.callback( Output("download-iterative-data", "data"), State("store-selected-tests", "data"), + State("show-latency", "value"), Input("plot-btn-download", "n_clicks"), prevent_initial_call=True ) - def _download_coverage_data(selection, _): + def _download_coverage_data(selection, show_latency, _): """Download the data :param selection: List of tests selected by user stored in the browser. + :param show_latency: If True, latency is displayed in the tables. :type selection: dict + :type show_latency: bool :returns: dict of data frame content (base64 encoded) and meta data used by the Download component. :rtype: dict @@ -656,6 +704,11 @@ class Layout: if not selection: raise PreventUpdate - df = select_coverage_data(self._data, selection, csv=True) + df = select_coverage_data( + self._data, + selection, + csv=True, + show_latency=bool(show_latency) + ) return dcc.send_data_frame(df.to_csv, C.COVERAGE_DOWNLOAD_FILE_NAME) diff --git a/csit.infra.dash/app/cdash/coverage/tables.py b/csit.infra.dash/app/cdash/coverage/tables.py index a34b80f024..6cc2956637 100644 --- a/csit.infra.dash/app/cdash/coverage/tables.py +++ b/csit.infra.dash/app/cdash/coverage/tables.py @@ -28,7 +28,8 @@ from ..utils.constants import Constants as C def select_coverage_data( data: pd.DataFrame, selected: dict, - csv: bool=False + csv: bool=False, + show_latency: bool=True ) -> list: """Select coverage data for the tables and generate tables as pandas data frames. @@ -37,9 +38,11 @@ def select_coverage_data( :param selected: Dictionary with user selection. :param csv: If True, pandas data frame with selected coverage data is returned for "Download Data" feature. + :param show_latency: If True, latency is displayed in the tables. :type data: pandas.DataFrame :type selected: dict :type csv: bool + :type show_latency: bool :returns: List of tuples with suite name (str) and data (pandas dataframe) or pandas dataframe if csv is True. :rtype: list[tuple[str, pandas.DataFrame], ] or pandas.DataFrame @@ -78,7 +81,7 @@ def select_coverage_data( ttype = df["test_type"].to_list()[0] # Prepare the coverage data - def _laten(hdrh_string: str, percentile: float) -> int: + def _latency(hdrh_string: str, percentile: float) -> int: """Get latency from HDRH string for given percentile. :param hdrh_string: Encoded HDRH string. @@ -126,78 +129,16 @@ def select_coverage_data( cov["Throughput_PDR_Mbps"] = df.apply( lambda row: row["result_pdr_lower_bandwidth_value"] /1e9, axis=1 ) - cov["Latency Forward [us]_10% PDR_P50"] = df.apply( - lambda row: _laten(row["result_latency_forward_pdr_10_hdrh"], 50.0), - axis=1 - ) - cov["Latency Forward [us]_10% PDR_P90"] = df.apply( - lambda row: _laten(row["result_latency_forward_pdr_10_hdrh"], 90.0), - axis=1 - ) - cov["Latency Forward [us]_10% PDR_P99"] = df.apply( - lambda row: _laten(row["result_latency_forward_pdr_10_hdrh"], 99.0), - axis=1 - ) - cov["Latency Forward [us]_50% PDR_P50"] = df.apply( - lambda row: _laten(row["result_latency_forward_pdr_50_hdrh"], 50.0), - axis=1 - ) - cov["Latency Forward [us]_50% PDR_P90"] = df.apply( - lambda row: _laten(row["result_latency_forward_pdr_50_hdrh"], 90.0), - axis=1 - ) - cov["Latency Forward [us]_50% PDR_P99"] = df.apply( - lambda row: _laten(row["result_latency_forward_pdr_50_hdrh"], 99.0), - axis=1 - ) - cov["Latency Forward [us]_90% PDR_P50"] = df.apply( - lambda row: _laten(row["result_latency_forward_pdr_90_hdrh"], 50.0), - axis=1 - ) - cov["Latency Forward [us]_90% PDR_P90"] = df.apply( - lambda row: _laten(row["result_latency_forward_pdr_90_hdrh"], 90.0), - axis=1 - ) - cov["Latency Forward [us]_90% PDR_P99"] = df.apply( - lambda row: _laten(row["result_latency_forward_pdr_90_hdrh"], 99.0), - axis=1 - ) - cov["Latency Reverse [us]_10% PDR_P50"] = df.apply( - lambda row: _laten(row["result_latency_reverse_pdr_10_hdrh"], 50.0), - axis=1 - ) - cov["Latency Reverse [us]_10% PDR_P90"] = df.apply( - lambda row: _laten(row["result_latency_reverse_pdr_10_hdrh"], 90.0), - axis=1 - ) - cov["Latency Reverse [us]_10% PDR_P99"] = df.apply( - lambda row: _laten(row["result_latency_reverse_pdr_10_hdrh"], 99.0), - axis=1 - ) - cov["Latency Reverse [us]_50% PDR_P50"] = df.apply( - lambda row: _laten(row["result_latency_reverse_pdr_50_hdrh"], 50.0), - axis=1 - ) - cov["Latency Reverse [us]_50% PDR_P90"] = df.apply( - lambda row: _laten(row["result_latency_reverse_pdr_50_hdrh"], 90.0), - axis=1 - ) - cov["Latency Reverse [us]_50% PDR_P99"] = df.apply( - lambda row: _laten(row["result_latency_reverse_pdr_50_hdrh"], 99.0), - axis=1 - ) - cov["Latency Reverse [us]_90% PDR_P50"] = df.apply( - lambda row: _laten(row["result_latency_reverse_pdr_90_hdrh"], 50.0), - axis=1 - ) - cov["Latency Reverse [us]_90% PDR_P90"] = df.apply( - lambda row: _laten(row["result_latency_reverse_pdr_90_hdrh"], 90.0), - axis=1 - ) - cov["Latency Reverse [us]_90% PDR_P99"] = df.apply( - lambda row: _laten(row["result_latency_reverse_pdr_90_hdrh"], 99.0), - axis=1 - ) + if show_latency: + for way in ("Forward", "Reverse"): + for pdr in (10, 50, 90): + for perc in (50, 90, 99): + latency = f"result_latency_{way.lower()}_pdr_{pdr}_hdrh" + cov[f"Latency {way} [us]_{pdr}% PDR_P{perc}"] = \ + df.apply( + lambda row: _latency(row[latency], perc), + axis=1 + ) if csv: return cov @@ -222,19 +163,26 @@ def select_coverage_data( return l_data -def coverage_tables(data: pd.DataFrame, selected: dict) -> list: +def coverage_tables( + data: pd.DataFrame, + selected: dict, + show_latency: bool=True + ) -> list: """Generate an accordion with coverage tables. :param data: Coverage data. :param selected: Dictionary with user selection. + :param show_latency: If True, latency is displayed in the tables. :type data: pandas.DataFrame :type selected: dict + :type show_latency: bool :returns: Accordion with suite names (titles) and tables. :rtype: dash_bootstrap_components.Accordion """ accordion_items = list() - for suite, cov_data in select_coverage_data(data, selected): + sel_data = select_coverage_data(data, selected, show_latency=show_latency) + for suite, cov_data in sel_data: if len(cov_data.columns) == 3: # VPP Device cols = [ { diff --git a/csit.infra.dash/app/cdash/report/layout.py b/csit.infra.dash/app/cdash/report/layout.py index 1e79b68b5e..ec17dec7e8 100644 --- a/csit.infra.dash/app/cdash/report/layout.py +++ b/csit.infra.dash/app/cdash/report/layout.py @@ -919,7 +919,7 @@ class Layout: try: store_sel = literal_eval(url_params["store_sel"][0]) normalize = literal_eval(url_params["norm"][0]) - except (KeyError, IndexError): + except (KeyError, IndexError, AttributeError): pass if store_sel: row_card_sel_tests = C.STYLE_ENABLED diff --git a/csit.infra.dash/app/cdash/trending/layout.py b/csit.infra.dash/app/cdash/trending/layout.py index 005d1dc141..87d11626d4 100644 --- a/csit.infra.dash/app/cdash/trending/layout.py +++ b/csit.infra.dash/app/cdash/trending/layout.py @@ -1087,7 +1087,7 @@ class Layout: try: store_sel = literal_eval(url_params["store_sel"][0]) normalize = literal_eval(url_params["norm"][0]) - except (KeyError, IndexError): + except (KeyError, IndexError, AttributeError): pass if store_sel: last_test = store_sel[-1] -- 2.16.6