C-Dash: Latency in coverage tables 20/38720/4
authorTibor Frank <tifrank@cisco.com>
Mon, 24 Apr 2023 10:07:53 +0000 (12:07 +0200)
committerTibor Frank <tifrank@cisco.com>
Mon, 24 Apr 2023 12:01:13 +0000 (14:01 +0200)
- Display latency on demand

Signed-off-by: Tibor Frank <tifrank@cisco.com>
Change-Id: I5152d1f6c843f6b1ffac5818e1de76a701c7ccf1

csit.infra.dash/app/cdash/comparisons/layout.py
csit.infra.dash/app/cdash/coverage/layout.py
csit.infra.dash/app/cdash/coverage/tables.py
csit.infra.dash/app/cdash/report/layout.py
csit.infra.dash/app/cdash/trending/layout.py

index 452afad..d78123b 100644 (file)
@@ -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({
index f519f5a..a5e095f 100644 (file)
@@ -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)
index a34b80f..6cc2956 100644 (file)
@@ -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 = [
                 {
index 1e79b68..ec17dec 100644 (file)
@@ -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
index 005d1dc..87d1162 100644 (file)
@@ -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]