-# Copyright (c) 2023 Cisco and/or its affiliates.
+# Copyright (c) 2024 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:
from ..utils.trigger import Trigger
from ..utils.telemetry_data import TelemetryData
from ..utils.utils import show_tooltip, label, sync_checklists, gen_new_url, \
- generate_options, get_list_group_items, graph_hdrh_latency
+ generate_options, get_list_group_items, navbar_trending, \
+ show_trending_graph_data
from ..utils.url_processing import url_decode
from .graphs import graph_trending, select_trending_data, graph_tm_trending
if tbs.get(dut, None) is None:
tbs[dut] = dict()
- if tbs[dut].get(infra, None) is None:
- tbs[dut][infra] = dict()
- if tbs[dut][infra].get(area, None) is None:
- tbs[dut][infra][area] = dict()
- if tbs[dut][infra][area].get(test, None) is None:
- tbs[dut][infra][area][test] = dict()
- tbs[dut][infra][area][test]["core"] = list()
- tbs[dut][infra][area][test]["frame-size"] = list()
- tbs[dut][infra][area][test]["test-type"] = list()
- if core.upper() not in tbs[dut][infra][area][test]["core"]:
- tbs[dut][infra][area][test]["core"].append(core.upper())
- if framesize.upper() not in \
- tbs[dut][infra][area][test]["frame-size"]:
- tbs[dut][infra][area][test]["frame-size"].append(
- framesize.upper()
- )
+ if tbs[dut].get(area, None) is None:
+ tbs[dut][area] = dict()
+ if tbs[dut][area].get(test, None) is None:
+ tbs[dut][area][test] = dict()
+ if tbs[dut][area][test].get(infra, None) is None:
+ tbs[dut][area][test][infra] = {
+ "core": list(),
+ "frame-size": list(),
+ "test-type": list()
+ }
+ tst_params = tbs[dut][area][test][infra]
+ if core.upper() not in tst_params["core"]:
+ tst_params["core"].append(core.upper())
+ if framesize.upper() not in tst_params["frame-size"]:
+ tst_params["frame-size"].append(framesize.upper())
if row["test_type"] == "mrr":
- if "MRR" not in tbs[dut][infra][area][test]["test-type"]:
- tbs[dut][infra][area][test]["test-type"].append("MRR")
+ if "MRR" not in tst_params["test-type"]:
+ tst_params["test-type"].append("MRR")
elif row["test_type"] == "ndrpdr":
- if "NDR" not in tbs[dut][infra][area][test]["test-type"]:
- tbs[dut][infra][area][test]["test-type"].extend(
- ("NDR", "PDR")
- )
+ if "NDR" not in tst_params["test-type"]:
+ tst_params["test-type"].extend(("NDR", "PDR"))
elif row["test_type"] == "hoststack":
if row["tg_type"] in ("iperf", "vpp"):
- if "BPS" not in tbs[dut][infra][area][test]["test-type"]:
- tbs[dut][infra][area][test]["test-type"].append("BPS")
+ if "BPS" not in tst_params["test-type"]:
+ tst_params["test-type"].append("BPS")
elif row["tg_type"] == "ab":
- if "CPS" not in tbs[dut][infra][area][test]["test-type"]:
- tbs[dut][infra][area][test]["test-type"].extend(
- ("CPS", "RPS")
- )
+ if "CPS" not in tst_params["test-type"]:
+ tst_params["test-type"].extend(("CPS", "RPS"))
self._spec_tbs = tbs
# Read from files:
dbc.Row(
id="row-navbar",
class_name="g-0",
- children=[
- self._add_navbar()
- ]
+ children=[navbar_trending((True, False, False, False))]
),
dbc.Row(
id="row-main",
dbc.Offcanvas(
class_name="w-50",
id="offcanvas-metadata",
- title="Throughput And Latency",
+ title="Detailed Information",
placement="end",
is_open=False,
children=[
]
),
delay_show=C.SPINNER_DELAY
+ ),
+ dbc.Offcanvas(
+ class_name="w-75",
+ id="offcanvas-documentation",
+ title="Documentation",
+ placement="end",
+ is_open=False,
+ children=html.Iframe(
+ src=C.URL_DOC_TRENDING,
+ width="100%",
+ height="100%"
+ )
)
]
)
id="div-main-error"
)
- def _add_navbar(self):
- """Add nav element with navigation panel. It is placed on the top.
-
- :returns: Navigation bar.
- :rtype: dbc.NavbarSimple
- """
- return dbc.NavbarSimple(
- dbc.NavItem(
- dbc.NavLink(
- C.TREND_TITLE,
- disabled=True,
- external_link=True,
- href="#"
- )
- ),
- id="navbarsimple-main",
- brand=C.BRAND,
- brand_href="/",
- brand_external_link=True,
- class_name="p-2",
- fluid=True
- )
-
def _add_ctrl_col(self) -> dbc.Col:
"""Add column with controls. It is placed on the left side.
dbc.InputGroup(
[
dbc.InputGroupText(
- show_tooltip(self._tooltips, "help-infra", "Infra")
+ show_tooltip(self._tooltips, "help-area", "Area")
),
dbc.Select(
- id={"type": "ctrl-dd", "index": "phy"},
- placeholder="Select a Physical Test Bed Topology..."
+ id={"type": "ctrl-dd", "index": "area"},
+ placeholder="Select an Area..."
)
],
size="sm"
dbc.InputGroup(
[
dbc.InputGroupText(
- show_tooltip(self._tooltips, "help-area", "Area")
+ show_tooltip(self._tooltips, "help-test", "Test")
),
dbc.Select(
- id={"type": "ctrl-dd", "index": "area"},
- placeholder="Select an Area..."
+ id={"type": "ctrl-dd", "index": "test"},
+ placeholder="Select a Test..."
)
],
size="sm"
dbc.InputGroup(
[
dbc.InputGroupText(
- show_tooltip(self._tooltips, "help-test", "Test")
+ show_tooltip(self._tooltips, "help-infra", "Infra")
),
dbc.Select(
- id={"type": "ctrl-dd", "index": "test"},
- placeholder="Select a Test..."
+ id={"type": "ctrl-dd", "index": "phy"},
+ placeholder="Select a Physical Test Bed Topology..."
)
],
size="sm"
tab_items.append(
dbc.Tab(
children=dcc.Graph(
- id={"type": "graph", "index": "lat"},
+ id={"type": "graph", "index": "bandwidth"},
figure=graphs[1]
),
+ label="Bandwidth",
+ tab_id="tab-bandwidth"
+ )
+ )
+
+ if graphs[2]:
+ tab_items.append(
+ dbc.Tab(
+ children=dcc.Graph(
+ id={"type": "graph", "index": "lat"},
+ figure=graphs[2]
+ ),
label="Latency",
tab_id="tab-lat"
)
pass
if store_sel:
last_test = store_sel[-1]
- test = self._spec_tbs[last_test["dut"]][last_test["phy"]]\
- [last_test["area"]][last_test["test"]]
+ test = self._spec_tbs[last_test["dut"]]\
+ [last_test["area"]][last_test["test"]][last_test["phy"]]
ctrl_panel.set({
"dd-dut-val": last_test["dut"],
- "dd-phy-val": last_test["phy"],
- "dd-phy-opt": generate_options(
- self._spec_tbs[last_test["dut"]].keys()
- ),
- "dd-phy-dis": False,
"dd-area-val": last_test["area"],
"dd-area-opt": [
{"label": label(v), "value": v} for v in sorted(
- self._spec_tbs[last_test["dut"]]\
- [last_test["phy"]].keys()
- )
+ self._spec_tbs[last_test["dut"]].keys())
],
"dd-area-dis": False,
"dd-test-val": last_test["test"],
"dd-test-opt": generate_options(
- self._spec_tbs[last_test["dut"]][last_test["phy"]]\
+ self._spec_tbs[last_test["dut"]]\
[last_test["area"]].keys()
),
"dd-test-dis": False,
+ "dd-phy-val": last_test["phy"],
+ "dd-phy-opt": generate_options(
+ self._spec_tbs[last_test["dut"]][last_test["area"]]\
+ [last_test["test"]].keys()
+ ),
+ "dd-phy-dis": False,
"cl-core-opt": generate_options(test["core"]),
"cl-core-val": [last_test["core"].upper(), ],
"cl-core-all-val": list(),
elif trigger.type == "ctrl-dd":
if trigger.idx == "dut":
try:
- options = generate_options(
- self._spec_tbs[trigger.value].keys()
- )
+ dut = self._spec_tbs[trigger.value]
+ options = [{"label": label(v), "value": v} \
+ for v in sorted(dut.keys())]
disabled = False
except KeyError:
options = list()
disabled = True
ctrl_panel.set({
"dd-dut-val": trigger.value,
- "dd-phy-val": str(),
- "dd-phy-opt": options,
- "dd-phy-dis": disabled,
"dd-area-val": str(),
- "dd-area-opt": list(),
- "dd-area-dis": True,
+ "dd-area-opt": options,
+ "dd-area-dis": disabled,
"dd-test-val": str(),
"dd-test-opt": list(),
"dd-test-dis": True,
+ "dd-phy-val": str(),
+ "dd-phy-opt": list(),
+ "dd-phy-dis": True,
"cl-core-opt": list(),
"cl-core-val": list(),
"cl-core-all-val": list(),
"cl-tsttype-all-opt": C.CL_ALL_DISABLED,
"btn-add-dis": True
})
- elif trigger.idx == "phy":
+ if trigger.idx == "area":
try:
dut = ctrl_panel.get("dd-dut-val")
- phy = self._spec_tbs[dut][trigger.value]
- options = [{"label": label(v), "value": v} \
- for v in sorted(phy.keys())]
+ area = self._spec_tbs[dut][trigger.value]
+ options = generate_options(area.keys())
disabled = False
except KeyError:
options = list()
disabled = True
ctrl_panel.set({
- "dd-phy-val": trigger.value,
- "dd-area-val": str(),
- "dd-area-opt": options,
- "dd-area-dis": disabled,
+ "dd-area-val": trigger.value,
"dd-test-val": str(),
- "dd-test-opt": list(),
- "dd-test-dis": True,
+ "dd-test-opt": options,
+ "dd-test-dis": disabled,
+ "dd-phy-val": str(),
+ "dd-phy-opt": list(),
+ "dd-phy-dis": True,
"cl-core-opt": list(),
"cl-core-val": list(),
"cl-core-all-val": list(),
"cl-tsttype-all-val": list(),
"cl-tsttype-all-opt": C.CL_ALL_DISABLED,
"btn-add-dis": True
- })
- elif trigger.idx == "area":
+ })
+ if trigger.idx == "test":
try:
dut = ctrl_panel.get("dd-dut-val")
- phy = ctrl_panel.get("dd-phy-val")
- area = self._spec_tbs[dut][phy][trigger.value]
- options = generate_options(area.keys())
+ area = ctrl_panel.get("dd-area-val")
+ test = self._spec_tbs[dut][area][trigger.value]
+ options = generate_options(test.keys())
disabled = False
except KeyError:
options = list()
disabled = True
ctrl_panel.set({
- "dd-area-val": trigger.value,
- "dd-test-val": str(),
- "dd-test-opt": options,
- "dd-test-dis": disabled,
+ "dd-test-val": trigger.value,
+ "dd-phy-val": str(),
+ "dd-phy-opt": options,
+ "dd-phy-dis": disabled,
"cl-core-opt": list(),
"cl-core-val": list(),
"cl-core-all-val": list(),
"cl-tsttype-all-opt": C.CL_ALL_DISABLED,
"btn-add-dis": True
})
- elif trigger.idx == "test":
+ if trigger.idx == "phy":
dut = ctrl_panel.get("dd-dut-val")
- phy = ctrl_panel.get("dd-phy-val")
area = ctrl_panel.get("dd-area-val")
- if all((dut, phy, area, trigger.value, )):
- test = self._spec_tbs[dut][phy][area][trigger.value]
+ test = ctrl_panel.get("dd-test-val")
+ if all((dut, area, test, trigger.value, )):
+ phy = self._spec_tbs[dut][area][test][trigger.value]
ctrl_panel.set({
- "dd-test-val": trigger.value,
- "cl-core-opt": generate_options(test["core"]),
+ "dd-phy-val": trigger.value,
+ "cl-core-opt": generate_options(phy["core"]),
"cl-core-val": list(),
"cl-core-all-val": list(),
"cl-core-all-opt": C.CL_ALL_ENABLED,
"cl-frmsize-opt": \
- generate_options(test["frame-size"]),
+ generate_options(phy["frame-size"]),
"cl-frmsize-val": list(),
"cl-frmsize-all-val": list(),
"cl-frmsize-all-opt": C.CL_ALL_ENABLED,
"cl-tsttype-opt": \
- generate_options(test["test-type"]),
+ generate_options(phy["test-type"]),
"cl-tsttype-val": list(),
"cl-tsttype-all-val": list(),
"cl-tsttype-all-opt": C.CL_ALL_ENABLED,
tm_ignore_host = list()
store["trending-graphs"] = None
store["telemetry-graphs"] = list()
- # on_draw[0] = True
on_draw = [True, True]
if trigger.idx == "add-test":
dut = ctrl_panel.get("dd-dut-val")
"""
trigger = Trigger(callback_context.triggered)
-
- try:
- idx = 0 if trigger.idx == "tput" else 1
- graph_data = graph_data[idx]["points"][0]
- except (IndexError, KeyError, ValueError, TypeError):
- raise PreventUpdate
-
- metadata = no_update
- graph = list()
-
- children = [
- dbc.ListGroupItem(
- [dbc.Badge(x.split(":")[0]), x.split(": ")[1]]
- ) for x in graph_data.get("text", "").split("<br>")
- ]
- if trigger.idx == "tput":
- title = "Throughput"
- elif trigger.idx == "lat":
- title = "Latency"
- hdrh_data = graph_data.get("customdata", None)
- if hdrh_data:
- graph = [dbc.Card(
- class_name="gy-2 p-0",
- children=[
- dbc.CardHeader(hdrh_data.pop("name")),
- dbc.CardBody(children=[
- dcc.Graph(
- id="hdrh-latency-graph",
- figure=graph_hdrh_latency(
- hdrh_data, self._graph_layout
- )
- )
- ])
- ])
- ]
- else:
+ if not trigger.value:
raise PreventUpdate
-
- metadata = [
- dbc.Card(
- class_name="gy-2 p-0",
- children=[
- dbc.CardHeader(children=[
- dcc.Clipboard(
- target_id="tput-lat-metadata",
- title="Copy",
- style={"display": "inline-block"}
- ),
- title
- ]),
- dbc.CardBody(
- id="tput-lat-metadata",
- class_name="p-0",
- children=[dbc.ListGroup(children, flush=True), ]
- )
- ]
- )
- ]
-
- return metadata, graph, True
+
+ return show_trending_graph_data(
+ trigger, graph_data, self._graph_layout)
@app.callback(
Output("download-trending-data", "data"),
raise PreventUpdate
return dcc.send_data_frame(df.to_csv, file_name)
+
+ @app.callback(
+ Output("offcanvas-documentation", "is_open"),
+ Input("btn-documentation", "n_clicks"),
+ State("offcanvas-documentation", "is_open")
+ )
+ def toggle_offcanvas_documentation(n_clicks, is_open):
+ if n_clicks:
+ return not is_open
+ return is_open