diff --git a/pandora_console/extras/mr/66.sql b/pandora_console/extras/mr/66.sql index 376a725662..b0022d31b0 100644 --- a/pandora_console/extras/mr/66.sql +++ b/pandora_console/extras/mr/66.sql @@ -1,5 +1,13 @@ START TRANSACTION; +CREATE TABLE IF NOT EXISTS `tgraph_analytics_filter` ( +`id` INT NOT NULL auto_increment, +`filter_name` VARCHAR(45) NULL, +`user_id` VARCHAR(255) NULL, +`graph_modules` TEXT NULL, +`interval` INT NULL, +PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; UPDATE `twelcome_tip` SET title = 'Scheduled downtimes', diff --git a/pandora_console/images/draggable.svg b/pandora_console/images/draggable.svg new file mode 100644 index 0000000000..3889fef861 --- /dev/null +++ b/pandora_console/images/draggable.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/pandora_console/include/constants.php b/pandora_console/include/constants.php index e8d4eb3a4f..889e32f693 100644 --- a/pandora_console/include/constants.php +++ b/pandora_console/include/constants.php @@ -807,6 +807,7 @@ define('AUDIT_LOG_FILE_MANAGER', 'File manager'); define('AUDIT_LOG_ALERT_MANAGEMENT', 'Alert management'); define('AUDIT_LOG_ALERT_CORRELATION_MANAGEMENT', 'Alert correlation management'); define('AUDIT_LOG_VISUAL_CONSOLE_MANAGEMENT', 'Visual Console Management'); +define('AUDIT_LOG_GRAPH_ANALYTICS_PUBLIC', 'Graph Analytics Public'); define('AUDIT_LOG_TAG_MANAGEMENT', 'Tag management'); define('AUDIT_LOG_SNMP_MANAGEMENT', 'SNMP management'); define('AUDIT_LOG_DASHBOARD_MANAGEMENT', 'Dashboard management'); diff --git a/pandora_console/include/functions.php b/pandora_console/include/functions.php index 4fa87f70cb..0895325ef5 100644 --- a/pandora_console/include/functions.php +++ b/pandora_console/include/functions.php @@ -270,7 +270,8 @@ function format_for_graph( $dec_point='.', $thousands_sep=',', $divider=1000, - $sufix='' + $sufix='', + $two_lines=false ) { // Exception to exclude modules whose unit is already formatted as KB (satellite modules) if (!empty($sufix) && $sufix == 'KB') { @@ -297,6 +298,10 @@ function format_for_graph( } // This will actually do the rounding and the decimals. + if ($two_lines === true) { + return remove_right_zeros(format_numeric($number, $decimals)).'
'.$shorts[$pos].$sufix; + } + return remove_right_zeros(format_numeric($number, $decimals)).$shorts[$pos].$sufix; } @@ -4046,25 +4051,49 @@ function series_type_graph_array($data, $show_elements_graph) } } else { $name_legend = ''; - if (isset($show_elements_graph['fullscale']) === true - && (int) $show_elements_graph['fullscale'] === 1 - ) { - $name_legend .= 'Tip: '; - } else { - $name_legend .= 'Avg: '; - } - if ($value['unit']) { - $name_legend .= $value['agent_alias']; - $name_legend .= ' / '; - $name_legend .= $value['module_name']; - $name_legend .= ' / '; - $name_legend .= __('Unit ').' '; - $name_legend .= $value['unit'].': '; + if ($show_elements_graph['graph_analytics'] === true) { + $name_legend .= '
'; + $name_legend .= '
'; + $name_legend .= ''; + $name_legend .= format_for_graph( + end(end($value['data'])), + 1, + $config['decimal_separator'], + $config['thousand_separator'], + 1000, + '', + true + ); + $name_legend .= ''; + $name_legend .= ''.$value['unit'].''; + $name_legend .= '
'; + $name_legend .= '
'; + $name_legend .= ''.$value['agent_alias'].''; + $name_legend .= ''.$value['module_name'].''; + $name_legend .= '
'; + $name_legend .= '
'; } else { - $name_legend .= $value['agent_alias']; - $name_legend .= ' / '; - $name_legend .= $value['module_name'].': '; + if (isset($show_elements_graph['fullscale']) === true + && (int) $show_elements_graph['fullscale'] === 1 + ) { + $name_legend .= 'Tip: '; + } else { + $name_legend .= 'Avg: '; + } + + if ($value['unit']) { + $name_legend .= $value['agent_alias']; + $name_legend .= ' / '; + $name_legend .= $value['module_name']; + $name_legend .= ' / '; + $name_legend .= __('Unit ').' '; + $name_legend .= $value['unit'].': '; + } else { + $name_legend .= $value['agent_alias']; + $name_legend .= ' / '; + $name_legend .= $value['module_name'].': '; + } } } } @@ -4085,28 +4114,30 @@ function series_type_graph_array($data, $show_elements_graph) $value['max'] = 0; } - $data_return['legend'][$key] .= ''.__('Min').' '.remove_right_zeros( - number_format( - $value['min'], - $config['graph_precision'], - $config['csv_decimal_separator'], - $config['csv_decimal_separator'] == ',' ? '.' : ',' - ) - ).' '.$value['unit'].' '.__('Max').' '.remove_right_zeros( - number_format( - $value['max'], - $config['graph_precision'], - $config['csv_decimal_separator'], - $config['csv_decimal_separator'] == ',' ? '.' : ',' - ) - ).' '.$value['unit'].' '._('Avg.').' '.remove_right_zeros( - number_format( - $value['avg'], - $config['graph_precision'], - $config['csv_decimal_separator'], - $config['csv_decimal_separator'] == ',' ? '.' : ',' - ) - ).' '.$value['unit'].' '.$str; + if (isset($show_elements_graph['graph_analytics']) === false) { + $data_return['legend'][$key] .= ''.__('Min').' '.remove_right_zeros( + number_format( + $value['min'], + $config['graph_precision'], + $config['csv_decimal_separator'], + $config['csv_decimal_separator'] == ',' ? '.' : ',' + ) + ).' '.$value['unit'].' '.__('Max').' '.remove_right_zeros( + number_format( + $value['max'], + $config['graph_precision'], + $config['csv_decimal_separator'], + $config['csv_decimal_separator'] == ',' ? '.' : ',' + ) + ).' '.$value['unit'].' '._('Avg.').' '.remove_right_zeros( + number_format( + $value['avg'], + $config['graph_precision'], + $config['csv_decimal_separator'], + $config['csv_decimal_separator'] == ',' ? '.' : ',' + ) + ).' '.$value['unit'].' '.$str; + } if ($show_elements_graph['compare'] == 'overlapped' && $key == 'sum2' diff --git a/pandora_console/include/functions_graph.php b/pandora_console/include/functions_graph.php index 1892b0cd31..6fa1e2a8d5 100644 --- a/pandora_console/include/functions_graph.php +++ b/pandora_console/include/functions_graph.php @@ -5540,3 +5540,23 @@ function graph_events_agent_by_group($id_group, $width=300, $height=200, $noWate $options ); } + + +function graph_analytics_filter_select() +{ + global $config; + + $result = []; + + if (check_acl($config['id_user'], 0, 'RW') === 1 || check_acl($config['id_user'], 0, 'RM') === 1) { + $filters = db_get_all_rows_sql('SELECT id, filter_name FROM tgraph_analytics_filter WHERE user_id = "'.$config['id_user'].'"'); + + if ($filters !== false) { + foreach ($filters as $filter) { + $result[$filter['id']] = $filter['filter_name']; + } + } + } + + return $result; +} diff --git a/pandora_console/include/functions_ui.php b/pandora_console/include/functions_ui.php index 13d984eba6..e1c04a45b5 100755 --- a/pandora_console/include/functions_ui.php +++ b/pandora_console/include/functions_ui.php @@ -4511,7 +4511,8 @@ function ui_toggle( $switch_on=null, $switch_name=null, $disableToggle=false, - $id_table=false + $id_table=false, + $position_tgl_div=false ) { // Generate unique Id. $uniqid = uniqid(''); @@ -4630,6 +4631,11 @@ function ui_toggle( } if ($disableToggle === false) { + $position_div = 'relative'; + if ($position_tgl_div !== false) { + $position_div = $position_tgl_div; + } + // JQuery Toggle. $output .= ' + "; + + echo $graph_return; + return; + } + + // Save filter. + if (empty($save_filter) === false) { + $graphs = get_parameter('graphs'); + $interval = (int) get_parameter('interval'); + + if (empty($save_filter) === true) { + echo __('Empty name'); + return; + } + + if (empty($graphs) === true) { + echo __('It is not possible to create the filter if you have not made any change'); + return; + } + + $id_filter = db_process_sql_insert( + 'tgraph_analytics_filter', + [ + 'filter_name' => $save_filter, + 'user_id' => $config['id_user'], + 'graph_modules' => json_encode($graphs), + 'interval' => $interval, + ] + ); + + if ($id_filter > 0) { + echo 'saved'; + return; + } else { + echo __('It is not possible to create the filter if you have not made any change'); + return; + } + } + + // Update filter. + if (empty($update_filter) === false) { + $graphs = get_parameter('graphs'); + $interval = (int) get_parameter('interval'); + + if (empty($graphs) === true) { + echo __('It is not possible to update the filter if you have not made any change'); + return; + } + + $update_filter = db_process_sql_update( + 'tgraph_analytics_filter', + [ + 'graph_modules' => json_encode($graphs), + 'interval' => $interval, + ], + ['id' => $update_filter] + ); + + if ($update_filter > 0) { + echo 'updated'; + return; + } else { + echo __('No updated'); + return; + } + + echo $update_filter; + return; + } + + // Load filter. + if (empty($load_filter) === false) { + $data = []; + $data['graphs'] = json_decode(db_get_value('graph_modules', 'tgraph_analytics_filter', 'id', $load_filter)); + $data['interval'] = db_get_value('tgraph_analytics_filter.interval', 'tgraph_analytics_filter', 'id', $load_filter); + + echo json_encode($data); + return; + } + + // Get new values. + if (empty($get_new_values) === false) { + $data = []; + + $agent_module_id = $get_new_values; + $date_array = get_parameter('date_array'); + $data_module_graph = get_parameter('data_module_graph'); + $params = get_parameter('params'); + $suffix = get_parameter('suffix'); + + // Stract data. + $array_data_module = grafico_modulo_sparse_data( + $agent_module_id, + $date_array, + $data_module_graph, + $params, + $suffix + ); + + echo json_encode($array_data_module); + return; + } + + // Export graphs. + if (empty($export_filter) === false) { + $counter = 0; + $filter = get_parameter('export_filter'); + $group = get_parameter('group'); + + $filter_name = db_get_value('filter_name', 'tgraph_analytics_filter', 'id', $filter); + $graphs = json_decode(db_get_value('graph_modules', 'tgraph_analytics_filter', 'id', $filter)); + $interval = db_get_value('tgraph_analytics_filter.interval', 'tgraph_analytics_filter', 'id', $filter); + + foreach ($graphs as $graph) { + $id_graph = db_process_sql_insert( + 'tgraph', + [ + 'id_user' => $config['id_user'], + 'id_group' => $group, + 'name' => $filter_name.' ('.__('Graph').' '.($counter + 1).')', + 'description' => __('Created from Graph analytics. Filter:').' '.$filter_name.'. '.__('Graph').' '.($counter + 1), + 'period' => $interval, + 'stacked' => 2, + ] + ); + + if ($id_graph > 0) { + $counter++; + $field_order = 1; + + foreach ($graph as $module) { + $id_graph_source = db_process_sql_insert( + 'tgraph_source', + [ + 'id_graph' => $id_graph, + 'id_server' => 0, + 'id_agent_module' => $module, + 'weight' => 1, + 'label' => '', + 'field_order' => $field_order, + ] + ); + + $field_order++; + } + } + } + + echo $counter; + } + + return; +} + +// Save filter modal. +echo ''; + +// Load filter modal. +$filters = graph_analytics_filter_select(); + +echo ''; + +// Share modal. +echo ''; + +// Export graphs. +echo ''; + + +// Header & Actions. +$title_tab = __('Start realtime'); +$tab_start_realtime = [ + 'text' => ''.html_print_image( + 'images/change-active.svg', + true, + [ + 'title' => $title_tab, + 'class' => 'invert_filter main_menu_icon', + ] + ).$title_tab.'', +]; + +$title_tab = __('Pause realtime'); +$tab_pause_realtime = [ + 'text' => ''.html_print_image( + 'images/change-pause.svg', + true, + [ + 'title' => $title_tab, + 'class' => 'invert_filter main_menu_icon', + ] + ).$title_tab.'', +]; + +$title_tab = __('New'); +$tab_new = [ + 'text' => ''.html_print_image( + 'images/plus-black.svg', + true, + [ + 'title' => $title_tab, + 'class' => 'invert_filter main_menu_icon', + ] + ).$title_tab.'', +]; + +$title_tab = __('Save'); +$tab_save = [ + 'text' => ''.html_print_image( + 'images/save_mc.png', + true, + [ + 'title' => $title_tab, + 'class' => 'invert_filter main_menu_icon', + ] + ).$title_tab.'', +]; + +$title_tab = __('Load'); +$tab_load = [ + 'text' => ''.html_print_image( + 'images/logs@svg.svg', + true, + [ + 'title' => $title_tab, + 'class' => 'invert_filter main_menu_icon', + ] + ).$title_tab.'', +]; + +// Hash for auto-auth in public link. +$hash = User::generatePublicHash(); + +$title_tab = __('Share'); +$tab_share = [ + 'text' => ''.html_print_image( + 'images/responses.svg', + true, + [ + 'title' => $title_tab, + 'class' => 'invert_filter main_menu_icon', + ] + ).$title_tab.' + ', +]; + +$title_tab = __('Export to custom graph'); +$tab_export = [ + 'text' => ''.html_print_image( + 'images/module-graph.svg', + true, + [ + 'title' => $title_tab, + 'class' => 'invert_filter main_menu_icon', + ] + ).$title_tab.'', +]; + +ui_print_standard_header( + __('Graph analytics'), + 'images/menu/reporting.svg', + false, + '', + false, + [ + $tab_export, + $tab_share, + $tab_load, + $tab_save, + $tab_new, + $tab_pause_realtime, + $tab_start_realtime, + ], + [ + [ + 'link' => '', + 'label' => __('Reporting'), + ], + ] +); + +// Content. +$left_content = ''; +$right_content = ''; + +$left_content .= ' +
+
+ +
+
+
+ +
+'.ui_toggle( + '', + __('Agents'), + 'agents-toggle', + 'agents-toggle', + true, + true, + '', + 'white-box-content', + 'box-flat white_table_graph', + 'images/arrow@svg.svg', + 'images/arrow@svg.svg', + false, + false, + false, + '', + '', + null, + null, + false, + false, + 'static' +).ui_toggle( + '', + __('Groups'), + 'groups-toggle', + 'groups-toggle', + true, + true, + '', + 'white-box-content', + 'box-flat white_table_graph', + 'images/arrow@svg.svg', + 'images/arrow@svg.svg', + false, + false, + false, + '', + '', + null, + null, + false, + false, + 'static' +).ui_toggle( + '', + __('Modules'), + 'modules-toggle', + 'modules-toggle', + true, + true, + '', + 'white-box-content', + 'box-flat white_table_graph', + 'images/arrow@svg.svg', + 'images/arrow@svg.svg', + false, + false, + false, + '', + '', + null, + null, + false, + false, + 'static' +).' +
+
+ + + +
+
+
+'; + +$intervals = []; +$intervals[SECONDS_1HOUR] = _('Last ').human_time_description_raw(SECONDS_1HOUR, true, 'large'); +$intervals[SECONDS_6HOURS] = _('Last ').human_time_description_raw(SECONDS_6HOURS, true, 'large'); +$intervals[SECONDS_12HOURS] = _('Last ').human_time_description_raw(SECONDS_12HOURS, true, 'large'); +$intervals[SECONDS_1DAY] = _('Last ').human_time_description_raw(SECONDS_1DAY, true, 'large'); +$intervals[SECONDS_2DAY] = _('Last ').human_time_description_raw(SECONDS_2DAY, true, 'large'); +$intervals[SECONDS_1WEEK] = _('Last ').human_time_description_raw(SECONDS_1WEEK, true, 'large'); + +$right_content .= '
'.html_print_select( + $intervals, + 'interval', + SECONDS_12HOURS, + '', + '', + 0, + true, + false, + false, + '' +).'
'; + +$right_content .= ' +
+
'.__('Drop here').'
+
+'; + +$filters_div = html_print_div( + [ + 'class' => 'filters-div-main', + 'content' => $left_content, + ], + true +); + +$graphs_div = html_print_div( + [ + 'class' => 'padding-div graphs-div-main', + 'content' => $right_content, + ], + true +); + +html_print_div( + [ + 'class' => 'white_box main-div', + 'content' => $filters_div.$graphs_div, + ] +); + +ui_require_javascript_file('graph_analytics', 'include/javascript/', true); +?> + + \ No newline at end of file diff --git a/pandora_console/operation/reporting/graph_analytics_public.php b/pandora_console/operation/reporting/graph_analytics_public.php new file mode 100644 index 0000000000..434bb89809 --- /dev/null +++ b/pandora_console/operation/reporting/graph_analytics_public.php @@ -0,0 +1,191 @@ + + + + + + + '.get_product_name().$text_subtitle.' +'; + +// CSS. +ui_require_css_file('common', 'include/styles/', true); +ui_require_css_file('pandora', 'include/styles/', true); +ui_require_css_file('discovery', 'include/styles/', true); +ui_require_css_file('register', 'include/styles/', true); +ui_require_css_file('order_interpreter', 'include/styles/', true); +ui_require_css_file('graph_analytics', 'include/styles/', true); +ui_require_css_file('jquery-ui.min', 'include/styles/js/', true); +ui_require_css_file('jquery-ui_custom', 'include/styles/js/', true); +ui_require_css_file('introjs', 'include/styles/js/', true); +ui_require_css_file('events', 'include/styles/', true); + +// JS. +ui_require_javascript_file('jquery.current', 'include/javascript/', true); +ui_require_javascript_file('jquery.pandora', 'include/javascript/', true); +ui_require_javascript_file('jquery-ui.min', 'include/javascript/', true); +ui_require_javascript_file('jquery.countdown', 'include/javascript/', true); +ui_require_javascript_file('pandora', 'include/javascript/', true); +ui_require_javascript_file('pandora_ui', 'include/javascript/', true); +ui_require_javascript_file('pandora_events', 'include/javascript/', true); +ui_require_javascript_file('select2.min', 'include/javascript/', true); +// ui_require_javascript_file('connection_check', 'include/javascript/', true); +ui_require_javascript_file('encode_decode_base64', 'include/javascript/', true); +ui_require_javascript_file('qrcode', 'include/javascript/', true); +ui_require_javascript_file('intro', 'include/javascript/', true); +ui_require_javascript_file('clippy', 'include/javascript/', true); +ui_require_javascript_file('underscore-min', 'include/javascript/', true); + +echo ' + +'; + + + +ui_require_javascript_file('date', 'include/javascript/timezone/src/', true); +ui_require_javascript_file('jquery.flot.min', 'include/graphs/flot/', true); +ui_require_javascript_file('jquery.flot.time', 'include/graphs/flot/', true); +ui_require_javascript_file('jquery.flot.pie', 'include/graphs/flot/', true); +ui_require_javascript_file('jquery.flot.crosshair.min', 'include/graphs/flot/', true); +ui_require_javascript_file('jquery.flot.stack.min', 'include/graphs/flot/', true); +ui_require_javascript_file('jquery.flot.selection.min', 'include/graphs/flot/', true); +ui_require_javascript_file('jquery.flot.resize.min', 'include/graphs/flot/', true); +ui_require_javascript_file('jquery.flot.threshold', 'include/graphs/flot/', true); +ui_require_javascript_file('jquery.flot.threshold.multiple', 'include/graphs/flot/', true); +ui_require_javascript_file('jquery.flot.symbol.min', 'include/graphs/flot/', true); +ui_require_javascript_file('jquery.flot.exportdata.pandora', 'include/graphs/flot/', true); +ui_require_javascript_file('jquery.flot.axislabels', 'include/graphs/flot/', true); +ui_require_javascript_file('pandora.flot', 'include/graphs/flot/', true); +ui_require_javascript_file('chart', 'include/graphs/chartjs/', true); +ui_require_javascript_file('chartjs-plugin-datalabels.min', 'include/graphs/chartjs/', true); + + + +ui_require_javascript_file('graph_analytics', 'include/javascript/', true); + + +echo ' + + +'; + +// Content. +$right_content = ''; + +$right_content .= ' +
+
'.__('Drop here').'
+
+'; + +$graphs_div = html_print_div( + [ + 'class' => 'padding-div graphs-div-main', + 'content' => $right_content, + ], + true +); + +html_print_div( + [ + 'class' => 'white_box main-div graph-analytics-public', + 'content' => $graphs_div, + ] +); + +?> + + + + + \ No newline at end of file diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 64d0b96813..9ddd3fafa0 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -4421,4 +4421,16 @@ CREATE TABLE IF NOT EXISTS `tsca` ( `remediation` text DEFAULT NULL, `compliance` text DEFAULT NULL, PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; + +-- --------------------------------------------------------------------- +-- Table `tgraph_analytics_filter` +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `tgraph_analytics_filter` ( +`id` INT NOT NULL auto_increment, +`filter_name` VARCHAR(45) NULL, +`user_id` VARCHAR(255) NULL, +`graph_modules` TEXT NULL, +`interval` INT NULL, +PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; \ No newline at end of file