diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
commit | e6918187568dbd01842d8d1d2c808ce16a894239 (patch) | |
tree | 64f88b554b444a49f656b6c656111a145cbbaa28 /monitoring/ceph-mixin/tests_dashboards/util.py | |
parent | Initial commit. (diff) | |
download | ceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip |
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | monitoring/ceph-mixin/tests_dashboards/util.py | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/monitoring/ceph-mixin/tests_dashboards/util.py b/monitoring/ceph-mixin/tests_dashboards/util.py new file mode 100644 index 000000000..1fce6559d --- /dev/null +++ b/monitoring/ceph-mixin/tests_dashboards/util.py @@ -0,0 +1,109 @@ +import json +import re +from pathlib import Path +from typing import Any, Dict, Tuple, Union + +from termcolor import cprint + +UNITS = ['ms', 's', 'm', 'h', 'd', 'w', 'y'] + + +def resolve_time_and_unit(time: str) -> Union[Tuple[int, str], Tuple[None, None]]: + """ + Divide time with its unit and return a tuple like (10, 'm') + Return None if its and invalid prometheus time + Valid units are inside UNITS. + """ + if time[-1] in UNITS: + return int(time[:-1]), time[-1] + if time[-2:] in UNITS: + return int(time[:-2]), time[-2:] + return None, None + + +def get_dashboards_data() -> Dict[str, Any]: + data: Dict[str, Any] = {'queries': {}, 'variables': {}, 'stats': {}} + for file in Path(__file__).parent.parent \ + .joinpath('dashboards_out').glob('*.json'): + with open(file, 'r') as f: + dashboard_data = json.load(f) + data['stats'][str(file)] = {'total': 0, 'tested': 0} + add_dashboard_queries(data, dashboard_data, str(file)) + add_dashboard_variables(data, dashboard_data) + add_default_dashboards_variables(data) + return data + + +def add_dashboard_queries(data: Dict[str, Any], dashboard_data: Dict[str, Any], path: str) -> None: + """ + Grafana panels can have more than one target/query, in order to identify each + query in the panel we append the "legendFormat" of the target to the panel name. + format: panel_name-legendFormat + """ + if 'panels' not in dashboard_data: + return + error = 0 + for panel in dashboard_data['panels']: + if ( + 'title' in panel + and 'targets' in panel + and len(panel['targets']) > 0 + and 'expr' in panel['targets'][0] + ): + for target in panel['targets']: + title = panel['title'] + legend_format = target['legendFormat'] if 'legendFormat' in target else "" + query_id = f'{title}-{legend_format}' + if query_id in data['queries']: + # NOTE: If two or more panels have the same name and legend it + # might suggest a refactoring is needed or add something else + # to identify each query. + conflict_file = Path(data['queries'][query_id]['path']).name + file = Path(path).name + cprint((f'ERROR: Query in panel "{title}" with legend "{legend_format}"' + f' already exists. Conflict "{conflict_file}" ' + f'with: "{file}"'), 'red') + error = 1 + data['queries'][query_id] = {'query': target['expr'], 'path': path} + data['stats'][path]['total'] += 1 + if error: + raise ValueError('Missing legend_format in queries, please add a proper value.') + + +def add_dashboard_variables(data: Dict[str, Any], dashboard_data: Dict[str, Any]) -> None: + if 'templating' not in dashboard_data or 'list' not in dashboard_data['templating']: + return + for variable in dashboard_data['templating']['list']: + if 'name' in variable: + data['variables'][variable['name']] = 'UNSET VARIABLE' + +def add_default_dashboards_variables(data: Dict[str, Any]) -> None: + data['variables']['job'] = 'ceph' + data['variables']['job_haproxy'] = 'haproxy' + data['variables']['__rate_interval'] = '1m' + +def replace_grafana_expr_variables(expr: str, variable: str, value: Any) -> str: + """ Replace grafana variables in expression with a value + + It should match the whole word, 'osd' musn't match with the 'osd' prefix in 'osd_hosts' + >>> replace_grafana_expr_variables('metric{name~="$osd_hosts|$other|$osd"}', \ + 'osd', 'replacement') + 'metric{name~="$osd_hosts|$other|replacement"}' + + >>> replace_grafana_expr_variables('metric{name~="$osd_hosts|$other|$osd"}', \ + 'other', 'replacement') + 'metric{name~="$osd_hosts|replacement|$osd"}' + + It replaces words with dollar prefix + >>> replace_grafana_expr_variables('metric{name~="no_dollar|$other|$osd"}', \ + 'no_dollar', 'replacement') + 'metric{name~="no_dollar|$other|$osd"}' + + It shouldn't replace the next char after the variable (positive lookahead test). + >>> replace_grafana_expr_variables('metric{name~="$osd"}', \ + 'osd', 'replacement') + 'metric{name~="replacement"}' + """ + regex = fr'\${variable}(?=\W)' + new_expr = re.sub(regex, fr'{value}', expr) + return new_expr |