C-Dash: Add bandwidth to MRR iterative
[csit.git] / csit.infra.dash / app / cdash / report / graphs.py
index 0e27836..50a3be2 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2022 Cisco and/or its affiliates.
+# Copyright (c) 2023 Cisco and/or its affiliates.
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at:
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+"""Implementation of graphs for iterative data.
 """
-"""
 
-import re
+
 import plotly.graph_objects as go
 import pandas as pd
 
 from copy import deepcopy
 
 from ..utils.constants import Constants as C
-from ..utils.utils import get_color
-
-
-def get_short_version(version: str, dut_type: str="vpp") -> str:
-    """Returns the short version of DUT without build number.
-
-    :param version: Original version string.
-    :param dut_type: DUT type.
-    :type version: str
-    :type dut_type: str
-    :returns: Short verion string.
-    :rtype: str
-    """
-
-    if dut_type in ("trex", "dpdk"):
-        return version
-
-    s_version = str()
-    groups = re.search(
-        pattern=re.compile(r"^(\d{2}).(\d{2})-(rc0|rc1|rc2|release$)"),
-        string=version
-    )
-    if groups:
-        try:
-            s_version = \
-                f"{groups.group(1)}.{groups.group(2)}.{groups.group(3)}".\
-                    replace("release", "rls")
-        except IndexError:
-            pass
-
-    return s_version
+from ..utils.utils import get_color, get_hdrh_latencies
 
 
 def select_iterative_data(data: pd.DataFrame, itm:dict) -> pd.DataFrame:
@@ -77,26 +47,20 @@ def select_iterative_data(data: pd.DataFrame, itm:dict) -> pd.DataFrame:
     else:
         return None
 
-    core = str() if itm["dut"] == "trex" else f"{itm['core']}"
-    ttype = "ndrpdr" if itm["testtype"] in ("ndr", "pdr") else itm["testtype"]
-    dut_v100 = "none" if itm["dut"] == "trex" else itm["dut"]
-    dut_v101 = itm["dut"]
-
+    if itm["testtype"] in ("ndr", "pdr"):
+        test_type = "ndrpdr"
+    elif itm["testtype"] == "mrr":
+        test_type = "mrr"
+    elif itm["area"] == "hoststack":
+        test_type = "hoststack"
     df = data.loc[(
         (data["release"] == itm["rls"]) &
-        (
-            (
-                (data["version"] == "1.0.0") &
-                (data["dut_type"].str.lower() == dut_v100)
-            ) |
-            (
-                (data["version"] == "1.0.1") &
-                (data["dut_type"].str.lower() == dut_v101)
-            )
-        ) &
-        (data["test_type"] == ttype) &
+        (data["test_type"] == test_type) &
         (data["passed"] == True)
     )]
+
+    core = str() if itm["dut"] == "trex" else f"{itm['core']}"
+    ttype = "ndrpdr" if itm["testtype"] in ("ndr", "pdr") else itm["testtype"]
     regex_test = \
         f"^.*[.|-]{nic}.*{itm['framesize']}-{core}-{drv}{itm['test']}-{ttype}$"
     df = df[
@@ -117,7 +81,7 @@ def graph_iterative(data: pd.DataFrame, sel:dict, layout: dict,
     :param data: Data frame with iterative data.
     :param sel: Selected tests.
     :param layout: Layout of plot.ly graph.
-    :param normalize: If True, the data is normalized to CPU frquency
+    :param normalize: If True, the data is normalized to CPU frequency
         Constants.NORM_FREQUENCY.
     :param data: pandas.DataFrame
     :param sel: dict
@@ -127,92 +91,193 @@ def graph_iterative(data: pd.DataFrame, sel:dict, layout: dict,
     :rtype: tuple(plotly.graph_objects.Figure, plotly.graph_objects.Figure)
     """
 
+    def get_y_values(data, y_data_max, param, norm_factor, release=str()):
+        if param == "result_receive_rate_rate_values":
+            if release == "rls2402":
+                y_vals_raw = data["result_receive_rate_rate_avg"].to_list()
+            else:
+                y_vals_raw = data[param].to_list()[0]
+        else:
+            y_vals_raw = data[param].to_list()
+        y_data = [(y * norm_factor) for y in y_vals_raw]
+        try:
+            y_data_max = max(max(y_data), y_data_max)
+        except TypeError:
+            y_data_max = 0
+        return y_data, y_data_max
+
     fig_tput = None
+    fig_band = None
     fig_lat = None
 
     tput_traces = list()
     y_tput_max = 0
+    y_units = set()
+
     lat_traces = list()
     y_lat_max = 0
     x_lat = list()
-    show_latency = False
-    show_tput = False
+
+    band_traces = list()
+    y_band_max = 0
+    y_band_units = set()
+    x_band = list()
+
     for idx, itm in enumerate(sel):
+
         itm_data = select_iterative_data(data, itm)
         if itm_data.empty:
             continue
+
         phy = itm["phy"].split("-")
         topo_arch = f"{phy[0]}-{phy[1]}" if len(phy) == 4 else str()
         norm_factor = (C.NORM_FREQUENCY / C.FREQUENCY[topo_arch]) \
             if normalize else 1.0
-        if itm["testtype"] == "mrr":
-            y_data_raw = itm_data[C.VALUE_ITER[itm["testtype"]]].to_list()[0]
-            y_data = [(y * norm_factor) for y in y_data_raw]
-            if len(y_data) > 0:
-                y_tput_max = \
-                    max(y_data) if max(y_data) > y_tput_max else y_tput_max
+
+        if itm["area"] == "hoststack":
+            ttype = f"hoststack-{itm['testtype']}"
         else:
-            y_data_raw = itm_data[C.VALUE_ITER[itm["testtype"]]].to_list()
-            y_data = [(y * norm_factor) for y in y_data_raw]
-            if y_data:
-                y_tput_max = \
-                    max(y_data) if max(y_data) > y_tput_max else y_tput_max
+            ttype = itm["testtype"]
+
+        y_units.update(itm_data[C.UNIT[ttype]].unique().tolist())
+
+        y_data, y_tput_max = get_y_values(
+            itm_data, y_tput_max, C.VALUE_ITER[ttype], norm_factor, itm["rls"]
+        )
+
         nr_of_samples = len(y_data)
+
+        customdata = list()
+        metadata = {
+            "csit release": itm["rls"],
+            "dut": itm["dut"],
+            "dut version": itm["dutver"],
+            "infra": itm["phy"],
+            "test": (
+                f"{itm['area']}-{itm['framesize']}-{itm['core']}-"
+                f"{itm['test']}-{itm['testtype']}"
+            )
+        }
+
+        if itm["testtype"] == "mrr" and itm["rls"] in ("rls2306", "rls2310"):
+            trial_run = "trial"
+            metadata["csit-ref"] = (
+                f"{itm_data['job'].to_list()[0]}/",
+                f"{itm_data['build'].to_list()[0]}"
+            )
+            customdata = [{"metadata": metadata}, ] * nr_of_samples
+        else:
+            trial_run = "run"
+            for _, row in itm_data.iterrows():
+                metadata["csit-ref"] = f"{row['job']}/{row['build']}"
+                customdata.append({"metadata": deepcopy(metadata)})
         tput_kwargs = dict(
             y=y_data,
             name=(
                 f"{idx + 1}. "
                 f"({nr_of_samples:02d} "
-                f"run{'s' if nr_of_samples > 1 else ''}) "
+                f"{trial_run}{'s' if nr_of_samples > 1 else ''}) "
                 f"{itm['id']}"
             ),
             hoverinfo=u"y+name",
             boxpoints="all",
             jitter=0.3,
-            marker=dict(color=get_color(idx))
+            marker=dict(color=get_color(idx)),
+            customdata=customdata
         )
         tput_traces.append(go.Box(**tput_kwargs))
-        show_tput = True
-
-        if itm["testtype"] == "pdr":
-            y_lat_row = itm_data[C.VALUE_ITER["pdr-lat"]].to_list()
-            y_lat = [(y / norm_factor) for y in y_lat_row]
-            if y_lat:
-                y_lat_max = max(y_lat) if max(y_lat) > y_lat_max else y_lat_max
-            nr_of_samples = len(y_lat)
-            lat_kwargs = dict(
-                y=y_lat,
-                name=(
-                    f"{idx + 1}. "
-                    f"({nr_of_samples:02d} "
-                    f"run{u's' if nr_of_samples > 1 else u''}) "
-                    f"{itm['id']}"
-                ),
-                hoverinfo="all",
-                boxpoints="all",
-                jitter=0.3,
-                marker=dict(color=get_color(idx))
+
+        if ttype in ("ndr", "pdr", "mrr"):
+            y_band, y_band_max = get_y_values(
+                itm_data,
+                y_band_max,
+                C.VALUE_ITER[f"{ttype}-bandwidth"],
+                norm_factor
             )
-            x_lat.append(idx + 1)
-            lat_traces.append(go.Box(**lat_kwargs))
-            show_latency = True
-        else:
-            lat_traces.append(go.Box())
+            if not all(pd.isna(y_band)):
+                y_band_units.update(
+                    itm_data[C.UNIT[f"{ttype}-bandwidth"]].unique().\
+                        dropna().tolist()
+                )
+                band_kwargs = dict(
+                    y=y_band,
+                    name=(
+                        f"{idx + 1}. "
+                        f"({nr_of_samples:02d} "
+                        f"run{'s' if nr_of_samples > 1 else ''}) "
+                        f"{itm['id']}"
+                    ),
+                    hoverinfo=u"y+name",
+                    boxpoints="all",
+                    jitter=0.3,
+                    marker=dict(color=get_color(idx)),
+                    customdata=customdata
+                )
+                x_band.append(idx + 1)
+                band_traces.append(go.Box(**band_kwargs))
 
-    if show_tput:
+        if ttype == "pdr":
+            y_lat, y_lat_max = get_y_values(
+                itm_data,
+                y_lat_max,
+                C.VALUE_ITER["latency"],
+                1 / norm_factor
+            )
+            if not all(pd.isna(y_lat)):
+                customdata = list()
+                for _, row in itm_data.iterrows():
+                    hdrh = get_hdrh_latencies(
+                        row,
+                        f"{metadata['infra']}-{metadata['test']}"
+                    )
+                    metadata["csit-ref"] = f"{row['job']}/{row['build']}"
+                    customdata.append({
+                        "metadata": deepcopy(metadata),
+                        "hdrh": hdrh
+                    })
+                nr_of_samples = len(y_lat)
+                lat_kwargs = dict(
+                    y=y_lat,
+                    name=(
+                        f"{idx + 1}. "
+                        f"({nr_of_samples:02d} "
+                        f"run{u's' if nr_of_samples > 1 else u''}) "
+                        f"{itm['id']}"
+                    ),
+                    hoverinfo="all",
+                    boxpoints="all",
+                    jitter=0.3,
+                    marker=dict(color=get_color(idx)),
+                    customdata=customdata
+                )
+                x_lat.append(idx + 1)
+                lat_traces.append(go.Box(**lat_kwargs))
+
+    if tput_traces:
         pl_tput = deepcopy(layout["plot-throughput"])
         pl_tput["xaxis"]["tickvals"] = [i for i in range(len(sel))]
         pl_tput["xaxis"]["ticktext"] = [str(i + 1) for i in range(len(sel))]
+        pl_tput["yaxis"]["title"] = f"Throughput [{'|'.join(sorted(y_units))}]"
         if y_tput_max:
-            pl_tput["yaxis"]["range"] = [0, (int(y_tput_max / 1e6) + 1) * 1e6]
+            pl_tput["yaxis"]["range"] = [0, int(y_tput_max) + 2e6]
         fig_tput = go.Figure(data=tput_traces, layout=pl_tput)
 
-    if show_latency:
+    if band_traces:
+        pl_band = deepcopy(layout["plot-bandwidth"])
+        pl_band["xaxis"]["tickvals"] = [i for i in range(len(x_band))]
+        pl_band["xaxis"]["ticktext"] = x_band
+        pl_band["yaxis"]["title"] = \
+            f"Bandwidth [{'|'.join(sorted(y_band_units))}]"
+        if y_band_max:
+            pl_band["yaxis"]["range"] = [0, int(y_band_max) + 2e9]
+        fig_band = go.Figure(data=band_traces, layout=pl_band)
+
+    if lat_traces:
         pl_lat = deepcopy(layout["plot-latency"])
         pl_lat["xaxis"]["tickvals"] = [i for i in range(len(x_lat))]
         pl_lat["xaxis"]["ticktext"] = x_lat
         if y_lat_max:
-            pl_lat["yaxis"]["range"] = [0, (int(y_lat_max / 10) + 1) * 10]
+            pl_lat["yaxis"]["range"] = [0, int(y_lat_max) + 5]
         fig_lat = go.Figure(data=lat_traces, layout=pl_lat)
 
-    return fig_tput, fig_lat
+    return fig_tput, fig_band, fig_lat