diff --git a/dashboards/dashboard_base.py b/dashboards/dashboard_base.py index f95efd88e5a8b4d575f23e08fd2fea0c41b834c7..d6dfa481871e7d258219f46ef1ddfe0461cb6cae 100644 --- a/dashboards/dashboard_base.py +++ b/dashboards/dashboard_base.py @@ -14,9 +14,10 @@ from dashboards.annotations import Annotation from dashboards.influx_queries import Query -def get_influx_target(target_query: str, **kwargs) -> InfluxDBTarget: +def get_influx_target(target_query: str, result_format: str = 'time_series', **kwargs) -> InfluxDBTarget: return InfluxDBTarget( query=target_query, + format=result_format, **{k: v for k, v in kwargs.items() if v is not None}, ) diff --git a/dashboards/dashboard_walberla.py b/dashboards/dashboard_walberla.py index e1257443d521069ebd494da6b58bd864706b28d5..501f453887a6a3ba685ebdbce3c5e021847ba558 100644 --- a/dashboards/dashboard_walberla.py +++ b/dashboards/dashboard_walberla.py @@ -18,14 +18,15 @@ from dashboards.dashboard_base import ( get_grid_pos, pack_in_row, ) -from dashboards.influx_queries import join_variable_and +from dashboards.influx_queries import join_variable_and, get_variable_condition_with_tag from dashboards.legends import Units from dashboards.overrides import get_color_regex_override -from dashboards.panels import PanelInfos, get_time_series_panel +from dashboards.panels import PanelInfos, get_time_series_panel, get_table_panel, get_bar_chart_panel from dashboards.variables import ( Filter, get_dashboard_variable, get_time_dependend_dashboard_variable, + get_field_keys_dashboard_variable, ) @@ -282,6 +283,114 @@ def dashboard_uniformgridgpu_profile(): ) + +def dashboard_uniformgridcpu_relativeperformance(): + data_source = "InfluxDB-1" + arch = "CPU" + measurment_name = f"UniformGrid{arch}" + measurment_name2 = f"roofline" + row_repeat = "host" + + options = DashboardOptions( + title=f"Uniform Grid {arch} - Relative Performance", + description=f"Relative performance benchmark dashboard for the Uniform Grid {arch} Benchmark from walberla", + tags=[arch, "walberla"], + timezone="browser", + ) + + filters = [ + Filter("host", multi=True, default_value="icx36"), + Filter("cellsPerBlock_0", multi=True, default_value="128"), + Filter("collisionSetup"), + Filter("project_id", multi=True, default_value="walberla/walberla"), + Filter("branch", multi=True, default_value="master"), + Filter("BandwidthBenchmark", multi=True, default_value="bw_stream"), + ] + + fields = [ + PanelInfos("Relative Performance", Units.number, absthreshold=80), + PanelInfos("Bandwidth", Units.number, absthreshold=80), + PanelInfos("Relative Performance", Units.mbytes_per_second, absthreshold=80), + ] + + filter_vars = [ + get_dashboard_variable(filter, measurment_name, data_source) + for filter in filters[0:5] + ] + filter_vars = [ + *filter_vars, + get_field_keys_dashboard_variable( + filters[5], measurment_name2, data_source + ), + ] + + row_repeat_var = [fv for fv in filter_vars if fv.name == row_repeat][0] + + where = [ + join_variable_and([f.name for f in filters]), + get_variable_condition_with_tag(filters[0].name), + join_variable_and([f.name for f in filters]) + ] + annotations = get_commit_annotation( + data_source, "red", "commits", measurment_name2) + + selected_columns = [ + ", ".join([ + "host", + "collisionSetup", + "MLUPSperProcess", + "mpi_num_processes"]), + ", ".join([ + 'last($BandwidthBenchmark) as "BW[MByte/s]"', + 'last($BandwidthBenchmark) / (27 * 2 * 8) as "P_max[MLUPS]"']), + ", ".join([ + "host", + "collisionSetup", + "MLUPSperProcess", + "mpi_num_processes"]), + ] + + panels = [ + # Panel 0 + get_table_panel( + fields[0], + selected_columns[0], + data_source, + measurment_name, + where=where[0], + group_by=[f.name for f in filters], + ), + # Panel 1 + get_table_panel( + fields[1], + selected_columns[1], + data_source, + measurment_name2, + where=where[1], + group_by=[filters[0].name], + ), + # Panel 2 + get_bar_chart_panel( + fields[2], + selected_columns[2], + data_source, + measurment_name, + where=where[2], + group_by=[f.name for f in filters], + ), + ] + + row = pack_in_row( + title=f"{row_repeat}: ${row_repeat_var.name}", + panels=[*panels], + repeat=Repeat("v", row_repeat_var.name), + ) + return build_dashboard( + options, rows=[row], templating=[*filter_vars], annotations=annotations + ) + + + def dashboard_fslbmgravitywave(): data_source = "InfluxDB-1" arch = "CPU" diff --git a/dashboards/influx_queries.py b/dashboards/influx_queries.py index d2113cfa50d8c7a1d4d9df3e3362c15ccbb4a8ae..7bd23de2fb11aad7acc1460de54204a98b777326 100644 --- a/dashboards/influx_queries.py +++ b/dashboards/influx_queries.py @@ -25,7 +25,7 @@ class Query: return f"FROM {self.from_} " def _get_where(self): - return f"WHERE ({self.where_}) AND $timeFilter " + return f"WHERE ({self.where_}) " def _get_group_by(self): if self.group_by: @@ -60,6 +60,16 @@ def get_tag_values(table: str, key_name: str, *, inner_field_key="") -> str: return f'SELECT distinct("{key_name}") FROM ({inner_query}) GROUP BY {key_name}' +def show_field_keys(table: str) -> str: + """Return influx query to get all field keys from a measurment.""" + base = "SHOW FIELD KEYS" + from_part = "" + if table != "": + from_part = f'from "{table}" ' + + return f'{base} {from_part}' + + def get_variable_condition(variable_name: str, *, tag_key: str = None) -> str: clean_rhs = variable_name.strip() if tag_key: @@ -70,8 +80,18 @@ def get_variable_condition(variable_name: str, *, tag_key: str = None) -> str: raise ValueError("Empty variable name") return f'"{clean_lhs}" =~ /^${{{clean_rhs}:regex}}$/' +def get_variable_condition_with_tag(variable_name: str, *, tag_key: str = None) -> str: + clean_rhs = variable_name.strip() + if tag_key: + clean_lhs = tag_key.strip() + else: + clean_lhs = clean_rhs + if not clean_rhs: + raise ValueError("Empty variable name") + return f'"{clean_lhs}"::tag =~ /^${clean_rhs}$/' -def join_conditions(conditions: List[str], operators: Union[List[str], str]): + +def join_conditions(conditions: List[str], operators: Union[List[str], str], include_time_filter: bool = True): ops = operators if isinstance(operators, str): ops = repeat(operators, len(conditions) - 1) @@ -84,10 +104,14 @@ def join_conditions(conditions: List[str], operators: Union[List[str], str]): ret = conditions[0] for op, cond in zip(ops, conditions[1:]): ret += f" {op} {cond}" + + if include_time_filter: + ret += ' AND $timeFilter' + return ret -def join_variable_and(variable_names: List[str]) -> str: +def join_variable_and(variable_names: List[str], include_time_filter: bool = True) -> str: return join_conditions( - [get_variable_condition(name) for name in variable_names], "AND" + [get_variable_condition(name) for name in variable_names], "AND", include_time_filter ) diff --git a/dashboards/panels.py b/dashboards/panels.py index 8fd80e149ed86016e313551b5944891a2cc02731..1b153e073f39c882294950ecee62b8936c79670a 100644 --- a/dashboards/panels.py +++ b/dashboards/panels.py @@ -1,7 +1,7 @@ from dataclasses import dataclass, field # from collections import namedtuple from dashboards.influx_queries import Query -from grafanalib.core import TimeSeries, Text, Stat, Template, Repeat, Threshold +from grafanalib.core import TimeSeries, Text, Stat, Template, Repeat, Threshold, Table, BarChart from dashboards.dashboard_base import get_influx_target from dashboards.legends import Units from numbers import Number @@ -93,3 +93,71 @@ def get_stat_panel(title: str, thresholds=[Threshold('green', 0, 0.0), Threshold('yellow', 1, 50.0), Threshold('red', 2, 80.0)], ** new_kwargs, ) + + +def get_table_panel(panel_infos: PanelInfos, + selected_columns: str, + data_source: str, + measurment_name: str, + *, + where=None, + group_by=None, + overrides=None, + **kwargs): + query = Query(select_=selected_columns, + from_=measurment_name, + where_=where, + group_by=group_by, + from_string=not is_regex(measurment_name), + select_string=False) + new_kwargs = {**kwargs} + if panel_infos.absthreshold is not None: + new_kwargs.update({'thresholdType': 'absolute', + 'thresholds': [Threshold('green', 0, 0.0), + Threshold('red', index=1, value=float(panel_infos.absthreshold), op='lt'), ], + } + ) + result_format = ['table'] + + return Table( + title=panel_infos.name, + dataSource=data_source, + targets=[get_influx_target(str(query), result_format[0])], + unit=panel_infos.unit, + overrides=overrides, + **new_kwargs, + + ) + + +def get_bar_chart_panel(panel_infos: PanelInfos, + selected_columns: str, + data_source: str, + measurment_name: str, + *, + where=None, + group_by=None, + overrides=None, + **kwargs): + query = Query(select_=selected_columns, + from_=measurment_name, + where_=where, + group_by=group_by, + from_string=not is_regex(measurment_name), + select_string=False) + new_kwargs = {**kwargs} + if panel_infos.absthreshold is not None: + new_kwargs.update({'thresholdType': 'absolute', + 'thresholds': [Threshold('green', 0, 0.0), + Threshold('red', index=1, value=float(panel_infos.absthreshold), op='lt'), ], + } + ) + result_format = ['table'] + + return BarChart( + title=panel_infos.name, + dataSource=data_source, + targets=[get_influx_target(str(query), result_format[0])], + **new_kwargs, + + ) diff --git a/dashboards/variables.py b/dashboards/variables.py index 63dc836494edb2daf61dc0fdc8b82c4a45de7b9f..088aed7e13fc3b10159a32b3f0d6758df77b038b 100644 --- a/dashboards/variables.py +++ b/dashboards/variables.py @@ -1,6 +1,6 @@ from grafanalib.core import Template from collections import namedtuple -from dashboards.influx_queries import show_tag_values, get_tag_values +from dashboards.influx_queries import show_tag_values, get_tag_values, show_field_keys Filter = namedtuple( "Filter", ("name", "multi", "default_value"), defaults=("", True, "") @@ -46,6 +46,17 @@ def get_time_dependend_dashboard_variable( return get_dashboard_variable_query(filter.name, query, data_source, **kwargs) +def get_field_keys_dashboard_variable(filter: Filter, measurment_name: str, data_source: str): + query = show_field_keys(measurment_name) + kwargs = { + "includeAll": filter.multi, + "multi": filter.multi, + } + if filter.default_value: + kwargs.update({"default": filter.default_value}) + return get_dashboard_variable_query(filter.name, query, data_source, **kwargs) + + def get_dashboard_variable_query( name: str, template_query: str,