/** (C) 2022 - ntop.org */ import { ntopng_utility, ntopng_url_manager } from "../services/context/ntopng_globals_services.js"; import metricsConsts from "../constants/metrics-consts.js" import NtopUtils from "./ntop-utils.js"; const set_timeseries_groups_in_url = (timeseries_groups) => { let params_timeseries_groups = []; timeseries_groups.forEach((ts_group) => { let param = get_ts_group_url_param(ts_group); params_timeseries_groups.push(param); }); let url_timeseries_groups = params_timeseries_groups.join(";;"); ntopng_url_manager.set_key_to_url("timeseries_groups", url_timeseries_groups); }; function get_ts_group_url_param(ts_group) { let timeseries = []; ts_group.timeseries.forEach((ts) => { timeseries.push(`${ts.id}=${ts.raw}:${ts.past}:${ts.avg}:${ts.perc_95}`); }); let metric_schema_query = ts_group.metric.schema; if (ts_group.metric.query != null) { metric_schema_query = `${metric_schema_query}+${ts_group.metric.query}`; } let timeseries_param = timeseries.join("|"); let source_value_array_query = ts_group.source_array.map((source) => source.value).join("+"); let param = `${ts_group.source_type.id};${source_value_array_query};${metric_schema_query};${timeseries_param}`; return param; } const get_timeseries_groups_from_url = async (http_prefix, url_timeseries_groups) => { if (url_timeseries_groups == null) { url_timeseries_groups = ntopng_url_manager.get_url_entry("timeseries_groups"); } if (url_timeseries_groups == null || url_timeseries_groups == "") { return null; } let groups = url_timeseries_groups.split(";;"); groups.map(async (g) => { let ts_group = await get_url_param_from_ts_group(g); return ts_group; }); let timeseries_groups = Promise.all(groups.map(async (g) => { let ts_group = await get_url_param_from_ts_group(g); return ts_group; })); return timeseries_groups; }; const get_ts_group = (source_type, source_array, metric, customized_ts) => { let ts_config = { raw: true, past: true, /* By default enable the past serie */ avg: false, perc_95: false, } if (customized_ts && customized_ts.raw != null) ts_config.raw = customized_ts.raw; if (customized_ts && customized_ts.past != null) ts_config.past = customized_ts.past; if (customized_ts && customized_ts.avg != null) ts_config.avg = customized_ts.avg; if (customized_ts && customized_ts.perc_95 != null) ts_config.perc_95 = customized_ts.perc_95; let id = get_ts_group_id(source_type, source_array, metric); let timeseries = []; for (let key in metric.timeseries) { let ts = metric.timeseries[key]; ts_config.id = key; ts_config.label = ts.label; timeseries.push(ts_config); } return { id, source_type, source_array, metric, timeseries, }; }; const get_default_timeseries_groups = async (http_prefix, metric_ts_schema, metric_query) => { let source_type = get_current_page_source_type(); let source_array = await get_default_source_array(http_prefix, source_type); let metrics = await get_metrics(http_prefix, source_type, source_array); let metric = get_default_metric(metrics, metric_ts_schema, metric_query); let ts_group = get_ts_group(source_type, source_array, metric); return [ts_group]; }; async function get_url_param_from_ts_group(ts_group_url_param) { let g = ts_group_url_param; let info = g.split(";"); let source_type_id = info[0]; let source_value_query = info[1]; let source_value_array = source_value_query.split("+"); let metric_schema_query = info[2]; let metric_schema_query_array = metric_schema_query.split("+"); if (metric_schema_query_array.length < 2) { metric_schema_query_array.push(null); } let timeseries_url = info[3]; let source_type = get_source_type_from_id(source_type_id); let source_array = await get_source_array_from_value_array(http_prefix, source_type, source_value_array); let metric = await get_metric_from_schema(http_prefix, source_type, source_array, metric_schema_query_array[0], metric_schema_query_array[1]); let timeseries = get_timeseries(timeseries_url, metric); return { id: get_ts_group_id(source_type, source_array, metric), source_type, source_array, metric, timeseries, }; } const get_ts_group_id = (source_type, source_array, metric, enable_source_def_value_dict, set_source_type_id_group) => { let metric_id = ""; if (metric != null) { metric_id = metric.schema; if (metric.query != null) { metric_id = `${metric_id} - ${metric.query}`; } } let source_def_array = source_type.source_def_array; let source_value_array = source_array.map((source, i) => { let source_def_value = source_def_array[i].value; if (enable_source_def_value_dict != null && !enable_source_def_value_dict[source_def_value]) { return null; } return source.value; }).filter((s) => s != null).join("_"); let source_type_id = source_type.id; if (set_source_type_id_group && source_type.id_group != null) { source_type_id = source_type.id_group; } return `${source_type_id} - ${source_value_array} - ${metric_id}`; }; function get_timeseries(timeseries_url, metric) { let ts_url_array = timeseries_url.split("|"); let r = /(.+)=(.+):(.+):(.+):(.+)/; let timeseries = []; ts_url_array.forEach((ts_url) => { let values = r.exec(ts_url); if (values.length > 0) { let id = values[1]; let label = metric.timeseries[id].label; let raw = JSON.parse(values[2]); let past = JSON.parse(values[3]); let avg = JSON.parse(values[4]); let perc_95 = JSON.parse(values[5]); timeseries.push({ id, label, raw, past, avg, perc_95, }); } }); return timeseries; } const ui_types = metricsConsts.ui_types; // dictionary of functions to convert an element of source_url rest result to a source ({label, value }) const sources_url_el_to_source = metricsConsts.sources_url_el_to_source; const sources_types = metricsConsts.sources_types; const sources_types_tables = metricsConsts.sources_types_tables; const get_source_type_from_id = (source_type_id) => { return sources_types.find((st) => st.id == source_type_id); }; const get_default_source_array = async (http_prefix, source_type) => { let source_value_array = get_default_source_value_array(source_type); let source_array = await get_source_array_from_value_array(http_prefix, source_type, source_value_array); return source_array; }; async function get_source_array_from_value_dict(http_prefix, source_type, source_value_dict) { let source_value_array = source_type.source_def_array.map((source_def) => source_value_dict[source_def.value]); let source_array = await get_source_array_from_value_array(http_prefix, source_type, source_value_array); return source_array; } const get_source_array_from_value_array = async (http_prefix, source_type, source_value_array) => { if (source_type == null) { source_type = get_current_page_source_type(); } let source_array = []; let source; for (let i = 0; i < source_value_array.length; i++) { let source_value = source_value_array[i]; let source_def = source_type.source_def_array[i]; if (source_def.sources_url || source_def.sources_function) { let sources = []; sources = await get_sources(http_prefix, source_type.id, source_def, source_value_array); source = sources.find((s) => s.value == source_value); if (source == null) { source = sources[0]; } } else { source = { label: source_value, value: source_value }; } source_array.push(source); } return source_array; }; let cache_sources = {}; function get_source_def_key(id, source_def, selected_source_value_array) { let key = `${id}_${source_def.value}`; if (!source_def.refresh_on_sources_change) { return key; } const value_array = selected_source_value_array.join("_"); key = `${key}_${value_array}`; return key; } const get_sources = async (http_prefix, id, source_def, selected_source_value_array) => { let key = get_source_def_key(id, source_def, selected_source_value_array); if (cache_sources[key] == null) { if (source_def.sources_url) { let url = `${http_prefix}/${source_def.sources_url}`; cache_sources[key] = ntopng_utility.http_request(url); } else if (source_def.sources_function) { cache_sources[key] = source_def.sources_function(selected_source_value_array); } else { return []; } } let sources = await cache_sources[key]; if (source_def.sources_url) { let f_map_source_element = sources_url_el_to_source[source_def.value_map_sources_res]; if (f_map_source_element == null) { f_map_source_element = sources_url_el_to_source[source_def.value]; } if (f_map_source_element == null) { throw `:Error: metrics-manager.js, missing sources_url_to_source ${source_def.value} key`; } sources = sources.map((s) => f_map_source_element(s)); } return sources.sort(NtopUtils.sortAlphabetically); }; function set_source_value_object_in_url(source_type, source_value_object) { source_type.source_def_array.forEach((source_def) => { let source_value = source_value_object[source_def.value]; if (source_value == null) { return; } if (source_def.f_set_value_url != null) { source_def.f_set_value_url(); } else if (source_def.value_url != null) { ntopng_url_manager.set_key_to_url(source_def.value_url, source_value); } else { ntopng_url_manager.set_key_to_url(source_def.value, source_value); } }); } const get_default_source_value_array = (source_type) => { if (source_type == null) { source_type = get_current_page_source_type(); } let source_value_array = source_type.source_def_array.map((source_def) => { if (source_def.f_get_value_url != null) { return source_def.f_get_value_url(); } let source_def_value = source_def.value_url; if (source_def_value == null) { source_def_value = source_def.value; } let source_value = ntopng_url_manager.get_url_entry(source_def_value); return source_value; }); return source_value_array; }; function get_metrics_url(http_prefix, source_type, source_array, epoch) { let params = source_type.source_def_array.map((source_def, i) => { return `${source_def.value}=${source_array[i].value}`; }).join("&"); let epoch_string = ``; if (epoch != null) { epoch_string = `epoch_end=${epoch.epoch_end}&epoch_begin=${epoch.epoch_begin}` } let url = `${http_prefix}/lua/rest/v2/get/timeseries/type/consts.lua?query=${source_type.query}&${params}&${epoch_string}`; return url; } function get_metric_key(source_type, source_array) { let source_array_key = source_array.map((source) => source.value).join("_"); let key = `${source_type.id}_${source_array_key}`; return key; } let cache_metrics = {}; let last_metrics_time_interval = null; const get_metrics = async (http_prefix, source_type, source_array, status) => { let epoch_begin = status?.epoch_begin || ntopng_url_manager.get_url_entry("epoch_begin"); let epoch_end = status?.epoch_end || ntopng_url_manager.get_url_entry("epoch_end"); let current_last_metrics_time_interval = `${epoch_begin}_${epoch_end}`; if (source_type == null) { source_type = get_current_page_source_type(); } if (source_array == null) { source_array = await get_default_source_array(http_prefix, source_type); } // let url = `${http_prefix}/lua/rest/v2/get/timeseries/type/consts.lua?query=${source_type.value}`; let url = get_metrics_url(http_prefix, source_type, source_array, { epoch_begin: epoch_begin, epoch_end: epoch_end }); let key = get_metric_key(source_type, source_array); if (current_last_metrics_time_interval != last_metrics_time_interval) { cache_metrics[key] = null; last_metrics_time_interval = current_last_metrics_time_interval; } if (cache_metrics[key] == null) { cache_metrics[key] = ntopng_utility.http_request(url); } let metrics = await cache_metrics[key]; if (metrics == null || metrics.length == 0) { return [{}]; } if (metrics.some((m) => m.default_visible == true) == false) { metrics[0].default_visible = true; } return ntopng_utility.clone(metrics); }; const get_current_page_source_type = () => { let pathname = window.location.pathname; for (let i = 0; i < sources_types.length; i += 1) { let regExp = new RegExp(sources_types[i].regex_page_url); if (regExp.test(pathname) == true) { return sources_types[i]; } } throw `source_type not found for ${pathname}`; }; const get_metric_from_schema = async (http_prefix, source_type, source_array, metric_schema, metric_query, status) => { let metrics = await get_metrics(http_prefix, source_type, source_array, status); if (metric_schema === 'top:iface:ndpi') { return metrics.find((m) => m.schema == metric_schema && m.query == metric_query) || metrics.find((m) => m.schema == 'top:iface:ndpi_full' && m.query == metric_query) } const metric = metrics.find((m) => m.schema == metric_schema && m.query == metric_query); return metric }; const get_metric_query_from_ts_query = (ts_query, source_type) => { if (source_type == null) { source_type = get_current_page_source_type(); } let source_def_dict = {}; source_type.source_def_array.forEach((s_def) => source_def_dict[s_def.value] = true); let metric_query = null let ts_query_array = ts_query.split(","); for (let i = 0; i < ts_query_array.length; i += 1) { let ts_val_key = ts_query_array[i].split(":")[0]; if (source_def_dict[ts_val_key] == null) { if (!metric_query) { metric_query = `${ts_query_array[i]}` } else { metric_query = `${metric_query},${ts_query_array[i]}` } } } return metric_query; }; const get_default_metric = (metrics, metric_ts_schema, metric_query) => { let default_metric; if (metric_ts_schema != null) { default_metric = metrics.find((m) => m.schema == metric_ts_schema && (metric_query == null || m.query == metric_query)); } if (default_metric == null) { default_metric = metrics.find((m) => m.default_visible == true); } if (default_metric != null) { return default_metric; } return metrics[0]; }; const metricsManager = function () { return { set_timeseries_groups_in_url, get_timeseries_groups_from_url, get_default_timeseries_groups, get_ts_group, get_ts_group_id, sources_types, sources_types_tables, get_source_type_from_id, get_current_page_source_type, get_sources, get_default_source_array, get_source_array_from_value_dict, get_source_array_from_value_array, get_default_source_value_array, get_metrics, get_metric_from_schema, get_metric_query_from_ts_query, get_default_metric, set_source_value_object_in_url, ui_types, }; }(); export default metricsManager;