From 8632b36ffacd357deae1bba978cce54b8ef4bd6b Mon Sep 17 00:00:00 2001 From: Evgeny Sharaev Date: Thu, 26 Oct 2023 12:35:57 +0800 Subject: [PATCH] Frontend V4.3 --- data/import_queries.sql | 249 +++++++++++++++++-- data/report_struct.sql | 465 +++++++++++++++++++++++++++++------- data/static/css/style.css | 62 ++++- data/static/js/chart.js | 6 +- data/static/js/generate.js | 24 +- data/static/js/highlight.js | 20 +- data/static/js/main.js | 2 +- data/static/js/navigator.js | 62 ++++- data/static/js/popup.js | 12 +- data/static/js/utilities.js | 12 +- 10 files changed, 775 insertions(+), 139 deletions(-) diff --git a/data/import_queries.sql b/data/import_queries.sql index 2260506..b5980de 100644 --- a/data/import_queries.sql +++ b/data/import_queries.sql @@ -10,7 +10,8 @@ INSERT INTO import_queries_version_order VALUES ('pg_profile','3.9','pg_profile','3.8'), ('pg_profile','4.0','pg_profile','3.9'), ('pg_profile','4.1','pg_profile','4.0'), -('pg_profile','4.2','pg_profile','4.1') +('pg_profile','4.2','pg_profile','4.1'), +('pg_profile','4.3','pg_profile','4.2') ; /* ==== Data importing queries ==== */ @@ -648,7 +649,8 @@ INSERT INTO import_queries VALUES 'last_autovacuum,last_analyze,last_autoanalyze,vacuum_count,autovacuum_count,' 'analyze_count,autoanalyze_count,heap_blks_read,heap_blks_hit,idx_blks_read,' 'idx_blks_hit,toast_blks_read,toast_blks_hit,tidx_blks_read,tidx_blks_hit,' - 'relsize,relsize_diff,relpages_bytes,relpages_bytes_diff)' + 'relsize,relsize_diff,relpages_bytes,relpages_bytes_diff,last_seq_scan,' + 'last_idx_scan,n_tup_newpage_upd)' 'SELECT ' 'srv_map.local_srv_id, ' 'dt.sample_id, ' @@ -686,7 +688,10 @@ INSERT INTO import_queries VALUES 'dt.relsize, ' 'dt.relsize_diff, ' 'dt.relpages_bytes, ' - 'dt.relpages_bytes_diff ' + 'dt.relpages_bytes_diff, ' + 'dt.last_seq_scan, ' + 'dt.last_idx_scan, ' + 'dt.n_tup_newpage_upd ' 'FROM %1$s imp ' 'CROSS JOIN json_to_record(imp.row_data) AS ' 'dt ( ' @@ -726,7 +731,10 @@ INSERT INTO import_queries VALUES 'relsize bigint, ' 'relsize_diff bigint, ' 'relpages_bytes bigint, ' - 'relpages_bytes_diff bigint ' + 'relpages_bytes_diff bigint, ' + 'last_seq_scan timestamp with time zone,' + 'last_idx_scan timestamp with time zone,' + 'n_tup_newpage_upd bigint ' ') ' 'JOIN tmp_srv_map srv_map ON ' '(srv_map.imp_srv_id = dt.server_id) ' @@ -750,7 +758,7 @@ INSERT INTO import_queries VALUES ('pg_profile','0.3.1', 1,'sample_stat_indexes', 'INSERT INTO sample_stat_indexes (server_id,sample_id,datid,indexrelid,tablespaceid,' 'idx_scan,idx_tup_read,idx_tup_fetch,idx_blks_read,idx_blks_hit,relsize,' - 'relsize_diff,indisunique,relpages_bytes,relpages_bytes_diff)' + 'relsize_diff,indisunique,relpages_bytes,relpages_bytes_diff,last_idx_scan)' 'SELECT ' 'srv_map.local_srv_id, ' 'dt.sample_id, ' @@ -766,7 +774,8 @@ INSERT INTO import_queries VALUES 'dt.relsize_diff, ' 'dt.indisunique, ' 'dt.relpages_bytes, ' - 'dt.relpages_bytes_diff ' + 'dt.relpages_bytes_diff, ' + 'dt.last_idx_scan ' 'FROM %1$s imp ' 'CROSS JOIN json_to_record(imp.row_data) AS ' 'dt ( ' @@ -784,7 +793,8 @@ INSERT INTO import_queries VALUES 'relsize_diff bigint, ' 'indisunique boolean, ' 'relpages_bytes bigint, ' - 'relpages_bytes_diff bigint' + 'relpages_bytes_diff bigint, ' + 'last_idx_scan timestamp with time zone' ') ' 'JOIN tmp_srv_map srv_map ON ' '(srv_map.imp_srv_id = dt.server_id) ' @@ -1258,7 +1268,7 @@ INSERT INTO import_queries VALUES 'autovacuum_count,analyze_count,autoanalyze_count,heap_blks_read,heap_blks_hit,' 'idx_blks_read,idx_blks_hit,toast_blks_read,toast_blks_hit,tidx_blks_read,' 'tidx_blks_hit,relsize,relsize_diff,tablespaceid,reltoastrelid,relkind,in_sample,' - 'relpages_bytes, relpages_bytes_diff)' + 'relpages_bytes,relpages_bytes_diff,last_seq_scan,last_idx_scan,n_tup_newpage_upd)' 'SELECT ' 'srv_map.local_srv_id, ' 'dt.sample_id, ' @@ -1301,7 +1311,10 @@ INSERT INTO import_queries VALUES 'dt.relkind, ' 'COALESCE(dt.in_sample, false), ' 'dt.relpages_bytes, ' - 'dt.relpages_bytes_diff ' + 'dt.relpages_bytes_diff, ' + 'dt.last_seq_scan, ' + 'dt.last_idx_scan, ' + 'dt.n_tup_newpage_upd ' 'FROM %1$s imp ' 'CROSS JOIN json_to_record(imp.row_data) AS ' 'dt ( ' @@ -1346,7 +1359,10 @@ INSERT INTO import_queries VALUES 'relkind character(1), ' 'in_sample boolean, ' 'relpages_bytes bigint, ' - 'relpages_bytes_diff bigint ' + 'relpages_bytes_diff bigint, ' + 'last_seq_scan timestamp with time zone,' + 'last_idx_scan timestamp with time zone,' + 'n_tup_newpage_upd bigint ' ') ' 'JOIN tmp_srv_map srv_map ON ' '(srv_map.imp_srv_id = dt.server_id) ' @@ -1359,7 +1375,7 @@ INSERT INTO import_queries VALUES 'seq_scan,seq_tup_read,idx_scan,idx_tup_fetch,n_tup_ins,n_tup_upd,n_tup_del,' 'n_tup_hot_upd,vacuum_count,autovacuum_count,analyze_count,autoanalyze_count,' 'heap_blks_read,heap_blks_hit,idx_blks_read,idx_blks_hit,toast_blks_read,' - 'toast_blks_hit,tidx_blks_read,tidx_blks_hit,relsize_diff)' + 'toast_blks_hit,tidx_blks_read,tidx_blks_hit,relsize_diff,n_tup_newpage_upd)' 'SELECT ' 'srv_map.local_srv_id, ' 'dt.sample_id, ' @@ -1386,7 +1402,8 @@ INSERT INTO import_queries VALUES 'dt.toast_blks_hit, ' 'dt.tidx_blks_read, ' 'dt.tidx_blks_hit, ' - 'dt.relsize_diff ' + 'dt.relsize_diff, ' + 'dt.n_tup_newpage_upd ' 'FROM %1$s imp ' 'CROSS JOIN json_to_record(imp.row_data) AS ' 'dt ( ' @@ -1415,7 +1432,8 @@ INSERT INTO import_queries VALUES 'toast_blks_hit bigint, ' 'tidx_blks_read bigint, ' 'tidx_blks_hit bigint, ' - 'relsize_diff bigint ' + 'relsize_diff bigint, ' + 'n_tup_newpage_upd bigint ' ') ' 'JOIN tmp_srv_map srv_map ON ' '(srv_map.imp_srv_id = dt.server_id) ' @@ -1427,7 +1445,7 @@ INSERT INTO import_queries VALUES 'INSERT INTO last_stat_indexes (server_id,sample_id,datid,relid,indexrelid,' 'schemaname,relname,indexrelname,idx_scan,idx_tup_read,idx_tup_fetch,' 'idx_blks_read,idx_blks_hit,relsize,relsize_diff,tablespaceid,indisunique,' - 'in_sample,relpages_bytes,relpages_bytes_diff)' + 'in_sample,relpages_bytes,relpages_bytes_diff,last_idx_scan)' 'SELECT ' 'srv_map.local_srv_id, ' 'dt.sample_id, ' @@ -1448,7 +1466,8 @@ INSERT INTO import_queries VALUES 'dt.indisunique, ' 'COALESCE(dt.in_sample, false), ' 'dt.relpages_bytes, ' - 'dt.relpages_bytes_diff ' + 'dt.relpages_bytes_diff, ' + 'dt.last_idx_scan ' 'FROM %1$s imp ' 'CROSS JOIN json_to_record(imp.row_data) AS ' 'dt ( ' @@ -1471,7 +1490,8 @@ INSERT INTO import_queries VALUES 'indisunique boolean, ' 'in_sample boolean, ' 'relpages_bytes bigint, ' - 'relpages_bytes_diff bigint' + 'relpages_bytes_diff bigint, ' + 'last_idx_scan timestamp with time zone' ') ' 'JOIN tmp_srv_map srv_map ON ' '(srv_map.imp_srv_id = dt.server_id) ' @@ -2384,3 +2404,200 @@ INSERT INTO import_queries VALUES 'WHERE ld.server_id IS NULL AND imp.section_id = $1 ' ) ; + /* + * Support import from pg_profile 4.3 + */ +INSERT INTO import_queries VALUES +('pg_profile','4.3', 1,'sample_stat_io', + 'INSERT INTO sample_stat_io (server_id,sample_id,backend_type,object,context,reads,' + 'read_time,writes,write_time,writebacks,writeback_time,extends,extend_time,' + 'op_bytes,hits,evictions,reuses,fsyncs,fsync_time,stats_reset' + ') ' + 'SELECT ' + 'srv_map.local_srv_id, ' + 'dt.sample_id, ' + 'dt.backend_type, ' + 'dt.object, ' + 'dt.context, ' + 'dt.reads, ' + 'dt.read_time, ' + 'dt.writes, ' + 'dt.write_time, ' + 'dt.writebacks, ' + 'dt.writeback_time, ' + 'dt.extends, ' + 'dt.extend_time, ' + 'dt.op_bytes, ' + 'dt.hits, ' + 'dt.evictions, ' + 'dt.reuses, ' + 'dt.fsyncs, ' + 'dt.fsync_time, ' + 'dt.stats_reset ' + 'FROM %1$s imp ' + 'CROSS JOIN json_to_record(imp.row_data) AS ' + 'dt ( ' + 'server_id integer, ' + 'sample_id integer, ' + 'backend_type text, ' + 'object text, ' + 'context text, ' + 'reads bigint, ' + 'read_time double precision, ' + 'writes bigint, ' + 'write_time double precision, ' + 'writebacks bigint, ' + 'writeback_time double precision, ' + 'extends bigint, ' + 'extend_time double precision, ' + 'op_bytes bigint, ' + 'hits bigint, ' + 'evictions bigint, ' + 'reuses bigint, ' + 'fsyncs bigint, ' + 'fsync_time double precision, ' + 'stats_reset timestamp with time zone ' + ') ' + 'JOIN tmp_srv_map srv_map ON ' + '(srv_map.imp_srv_id = dt.server_id) ' + 'LEFT OUTER JOIN sample_stat_io ld ON ' + '(ld.server_id, ld.sample_id, ld.backend_type, ld.object, ld.context) = ' + '(srv_map.local_srv_id, dt.sample_id, dt.backend_type, dt.object, dt.context) ' + 'WHERE ld.server_id IS NULL AND imp.section_id = $1 ' +), +('pg_profile','4.3', 1,'last_stat_io', + 'INSERT INTO last_stat_io (server_id,sample_id,backend_type,object,context,reads,' + 'read_time,writes,write_time,writebacks,writeback_time,extends,extend_time,' + 'op_bytes,hits,evictions,reuses,fsyncs,fsync_time,stats_reset' + ') ' + 'SELECT ' + 'srv_map.local_srv_id, ' + 'dt.sample_id, ' + 'dt.backend_type, ' + 'dt.object, ' + 'dt.context, ' + 'dt.reads, ' + 'dt.read_time, ' + 'dt.writes, ' + 'dt.write_time, ' + 'dt.writebacks, ' + 'dt.writeback_time, ' + 'dt.extends, ' + 'dt.extend_time, ' + 'dt.op_bytes, ' + 'dt.hits, ' + 'dt.evictions, ' + 'dt.reuses, ' + 'dt.fsyncs, ' + 'dt.fsync_time, ' + 'dt.stats_reset ' + 'FROM %1$s imp ' + 'CROSS JOIN json_to_record(imp.row_data) AS ' + 'dt ( ' + 'server_id integer, ' + 'sample_id integer, ' + 'backend_type text, ' + 'object text, ' + 'context text, ' + 'reads bigint, ' + 'read_time double precision, ' + 'writes bigint, ' + 'write_time double precision, ' + 'writebacks bigint, ' + 'writeback_time double precision, ' + 'extends bigint, ' + 'extend_time double precision, ' + 'op_bytes bigint, ' + 'hits bigint, ' + 'evictions bigint, ' + 'reuses bigint, ' + 'fsyncs bigint, ' + 'fsync_time double precision, ' + 'stats_reset timestamp with time zone ' + ') ' + 'JOIN tmp_srv_map srv_map ON ' + '(srv_map.imp_srv_id = dt.server_id) ' + 'LEFT OUTER JOIN last_stat_io ld ON ' + '(ld.server_id, ld.sample_id, ld.backend_type, ld.object, ld.context) = ' + '(srv_map.local_srv_id, dt.sample_id, dt.backend_type, dt.object, dt.context) ' + 'WHERE ld.server_id IS NULL AND imp.section_id = $1 ' +), +('pg_profile','4.3', 1,'sample_stat_slru', + 'INSERT INTO sample_stat_slru (server_id,sample_id,name,blks_zeroed,' + 'blks_hit,blks_read,blks_written,blks_exists,flushes,truncates,' + 'stats_reset' + ') ' + 'SELECT ' + 'srv_map.local_srv_id, ' + 'dt.sample_id, ' + 'dt.name, ' + 'dt.blks_zeroed, ' + 'dt.blks_hit, ' + 'dt.blks_read, ' + 'dt.blks_written, ' + 'dt.blks_exists, ' + 'dt.flushes, ' + 'dt.truncates, ' + 'dt.stats_reset ' + 'FROM %1$s imp ' + 'CROSS JOIN json_to_record(imp.row_data) AS ' + 'dt ( ' + 'server_id integer, ' + 'sample_id integer, ' + 'name text, ' + 'blks_zeroed bigint, ' + 'blks_hit bigint, ' + 'blks_read bigint, ' + 'blks_written bigint, ' + 'blks_exists bigint, ' + 'flushes bigint, ' + 'truncates bigint, ' + 'stats_reset timestamp with time zone ' + ') ' + 'JOIN tmp_srv_map srv_map ON ' + '(srv_map.imp_srv_id = dt.server_id) ' + 'LEFT OUTER JOIN sample_stat_slru ld ON ' + '(ld.server_id, ld.sample_id, ld.name) = ' + '(srv_map.local_srv_id, dt.sample_id, dt.name) ' + 'WHERE ld.server_id IS NULL AND imp.section_id = $1 ' +), +('pg_profile','4.3', 1,'last_stat_slru', + 'INSERT INTO last_stat_slru (server_id,sample_id,name,blks_zeroed,' + 'blks_hit,blks_read,blks_written,blks_exists,flushes,truncates,' + 'stats_reset' + ') ' + 'SELECT ' + 'srv_map.local_srv_id, ' + 'dt.sample_id, ' + 'dt.name, ' + 'dt.blks_zeroed, ' + 'dt.blks_hit, ' + 'dt.blks_read, ' + 'dt.blks_written, ' + 'dt.blks_exists, ' + 'dt.flushes, ' + 'dt.truncates, ' + 'dt.stats_reset ' + 'FROM %1$s imp ' + 'CROSS JOIN json_to_record(imp.row_data) AS ' + 'dt ( ' + 'server_id integer, ' + 'sample_id integer, ' + 'name text, ' + 'blks_zeroed bigint, ' + 'blks_hit bigint, ' + 'blks_read bigint, ' + 'blks_written bigint, ' + 'blks_exists bigint, ' + 'flushes bigint, ' + 'truncates bigint, ' + 'stats_reset timestamp with time zone ' + ') ' + 'JOIN tmp_srv_map srv_map ON ' + '(srv_map.imp_srv_id = dt.server_id) ' + 'LEFT OUTER JOIN last_stat_slru ld ON ' + '(ld.server_id, ld.sample_id, ld.name) = ' + '(srv_map.local_srv_id, dt.sample_id, dt.name) ' + 'WHERE ld.server_id IS NULL AND imp.section_id = $1 ' +) +; diff --git a/data/report_struct.sql b/data/report_struct.sql index f083560..2f122a2 100644 --- a/data/report_struct.sql +++ b/data/report_struct.sql @@ -25,7 +25,7 @@ VALUES (1, 'funchdr', NULL, 500, 'User function statistics', 'User function statistics', 'function_stats', NULL, 'func_stat', NULL, NULL), (1, 'vachdr', NULL, 600, 'Vacuum-related statistics', 'Vacuum-related statistics', NULL, NULL, 'vacuum_stats', NULL, NULL), (1, 'settings', NULL, 700, 'Cluster settings during the report interval', 'Cluster settings during the report interval', NULL, NULL, 'pg_settings', NULL, NULL), -(1, 'stmt_warn', NULL, 800, NULL, 'Warning!', 'stmt_cnt_all', NULL, NULL, NULL, +(1, 'stmt_warn', NULL, 800, NULL, 'Warning!', 'stmt_cnt_all', NULL, 'stmt_warn', NULL, '[{' '"type": "row_table", ' '"source": "stmt_cnt_all",' @@ -44,8 +44,8 @@ INSERT INTO report_struct ( report_id, sect_id, parent_sect_id, s_ord, toc_cap, tbl_cap, feature, function_name, href, content, sect_struct) VALUES -(1, 'dbstat1', 'srvstat', 100, 'Database statistics', 'Database statistics', NULL, NULL, 'db_stat', NULL, NULL), -(1, 'dbstat2', 'srvstat', 200, NULL, NULL, 'dbstats_reset', NULL, NULL, +(1, 'dbstat', 'srvstat', 100, 'Database statistics', 'Database statistics', NULL, NULL, 'db_stat', NULL, NULL), +(1, 'dbstatreset', 'dbstat', 200, NULL, NULL, 'dbstats_reset', NULL, NULL, '

Warning!

' '

Database statistics reset detected during report interval!

' '{func_output}' @@ -56,12 +56,12 @@ VALUES '"source": "dbstats_reset",' '"ordering": "sample_id",' '"columns": [' - '{"caption": "Database", "id": "datname", "class": "table_obj_name"},' + '{"caption": "Database", "id": "dbname", "class": "table_obj_name"},' '{"caption": "Sample", "id": "sample_id", "class": "table_obj_value"},' '{"caption": "Reset time", "id": "stats_reset", "class": "table_obj_value"}' ']' '}]'::jsonb), -(1, 'dbstat3', 'srvstat', 300, NULL, NULL, NULL, NULL, NULL, NULL, +(1, 'dbstatmain', 'dbstat', 300, NULL, NULL, NULL, NULL, NULL, NULL, '[{' '"type": "row_table",' '"class": "stat",' @@ -121,6 +121,133 @@ VALUES '"title": "Database size increment during report interval"}' ']' '}]'::jsonb), +(1, 'iostat', 'srvstat', 328, 'Cluster I/O statistics', 'Cluster I/O statistics', 'stat_io', NULL, 'stat_io', NULL, NULL), +(1, 'iostatrst', 'srvstat', 329, NULL, NULL, 'stat_io_reset', NULL, 'stat_io_reset', +'

Warning! IO stats reset was detected during report interval. Statistic values may be affected

', +'[{' + '"type": "row_table",' + '"class": "stat",' + '"source": "stat_io_reset",' + '"columns": [' + '{"caption": "Sample ID", "id": "sample_id", "class": "table_obj_name", ' + '"title": "Sample identifier with detected reset"},' + '{"caption": "Object", "id": "object", "class": "table_obj_name", ' + '"title": "Target object of an I/O operation"},' + '{"caption": "Backend", "id": "backend_type", "class": "table_obj_name", ' + '"title": "Type of backend (see stat_activity)"},' + '{"caption": "Context", "id": "context", "class": "table_obj_name", ' + '"title": "The context of an I/O operation"},' + '{"caption": "Reset time", "id": "stats_reset", "class": "table_obj_value", ' + '"title": "Date and time of the last reset performed in sample"}' + ']' + '}]'::jsonb), +(1, 'iostatmain', 'srvstat', 330, NULL, NULL, 'stat_io', NULL, 'stat_io', NULL, +'[{' + '"type": "row_table",' + '"class": "stat",' + '"source": "stat_io",' + '"columns": [' + '{"caption": "Object", "id": "object", "class": "table_obj_name", ' + '"title": "Target object of an I/O operation"},' + '{"caption": "Backend", "id": "backend_type", "class": "table_obj_name", ' + '"title": "Type of backend (see stat_activity)"},' + '{"caption": "Context", "id": "context", "class": "table_obj_name", ' + '"title": "The context of an I/O operation"},' + '{"caption": "Reads", "columns": [' + '{"caption": "Count", "id": "reads", "class": "table_obj_value", ' + '"title": "Number of read operations"},' + '{"caption": "Bytes", "id": "read_sz", "class": "table_obj_value", ' + '"title": "Read data amount"},' + '{"caption": "Time", "id": "read_time", "class": "table_obj_value", ' + '"condition": "io_times", ' + '"title": "Time spent in reading operation (seconds)"}' + ']},' + '{"caption": "Writes", "columns": [' + '{"caption": "Count", "id": "writes", "class": "table_obj_value", ' + '"title": "Number of write operations"},' + '{"caption": "Bytes", "id": "write_sz", "class": "table_obj_value", ' + '"title": "Written data amount"},' + '{"caption": "Time", "id": "write_time", "class": "table_obj_value", ' + '"condition": "io_times", ' + '"title": "Time spent in writing operations (seconds)"}' + ']},' + '{"caption": "Writebacks", "columns": [' + '{"caption": "Count", "id": "writebacks", "class": "table_obj_value", ' + '"title": "Number of blocks which the process requested the kernel write out to permanent storage"},' + '{"caption": "Bytes", "id": "writeback_sz", "class": "table_obj_value", ' + '"title": "The amount of data requested for write out to permanent storage"},' + '{"caption": "Time", "id": "writeback_time", "class": "table_obj_value", ' + '"condition": "io_times", ' + '"title": "Time spent in writeback operations (seconds)"}' + ']},' + '{"caption": "Extends", "columns": [' + '{"caption": "Count", "id": "extends", "class": "table_obj_value", ' + '"title": "Number of relation extend operations"},' + '{"caption": "Bytes", "id": "extend_sz", "class": "table_obj_value", ' + '"title": "The amount of space used by extend operations"},' + '{"caption": "Time", "id": "extend_time", "class": "table_obj_value", ' + '"condition": "io_times", ' + '"title": "Time spent in extend operations (seconds)"}' + ']},' + '{"caption": "Hits", "id": "hits", "class": "table_obj_value", ' + '"title": "The number of times a desired block was found in a shared buffer"},' + '{"caption": "Evictions", "id": "evictions", "class": "table_obj_value", ' + '"title": "Number of times a block has been written out from a shared or local buffer in order to make it available for another use"},' + '{"caption": "Reuses", "id": "reuses", "class": "table_obj_value", ' + '"title": "The number of times an existing buffer in a size-limited ring buffer outside of shared buffers was reused as part of an I/O operation in the bulkread, bulkwrite, or vacuum contexts"},' + '{"caption": "Fsyncs", "columns": [' + '{"caption": "Count", "id": "fsyncs", "class": "table_obj_value", ' + '"title": "Number of fsync calls. These are only tracked in context normal"},' + '{"caption": "Time", "id": "fsync_time", "class": "table_obj_value", ' + '"condition": "io_times", ' + '"title": "Time spent in fsync operations (seconds)"}' + ']}' + ']' + '}]'::jsonb), +(1, 'slrustat', 'srvstat', 358, 'Cluster SLRU statistics', 'Cluster SLRU statistics', 'stat_slru', NULL, 'stat_slru', NULL, NULL), +(1, 'slrustatrst', 'slrustat', 359, NULL, NULL, 'stat_slru_reset', NULL, 'stat_slru_reset', +'

Warning! SLRU stats reset was detected during report interval. Statistic values may be affected

', +'[{' + '"type": "row_table",' + '"class": "stat",' + '"source": "stat_slru_reset",' + '"columns": [' + '{"caption": "Sample ID", "id": "sample_id", "class": "table_obj_name", ' + '"title": "Sample identifier with detected reset"},' + '{"caption": "Name", "id": "name", "class": "table_obj_name", ' + '"title": "Name of the SLRU"},' + '{"caption": "Reset time", "id": "stats_reset", "class": "table_obj_value", ' + '"title": "Date and time of the last reset performed in sample"}' + ']' + '}]'::jsonb), +(1, 'slrustatmain', 'slrustat', 360, NULL, NULL, 'stat_slru', NULL, 'stat_slru', NULL, +'[{' + '"type": "row_table",' + '"class": "stat",' + '"source": "stat_slru",' + '"columns": [' + '{"caption": "Name", "id": "name", "class": "table_obj_name", ' + '"title": "Name of the SLRU"},' + '{"caption": "Zeroed", "id": "blks_zeroed", "class": "table_obj_value", ' + '"title": "Number of blocks zeroed during initializations"},' + '{"caption": "Hits", "id": "blks_hit", "class": "table_obj_value", ' + '"title": "Number of times disk blocks were found already in the SLRU, so that a ' + 'read was not necessary (this only includes hits in the SLRU, not the operating ' + 'system''s file system cache)"},' + '{"caption": "Reads", "id": "blks_read", "class": "table_obj_value", ' + '"title": "Number of disk blocks read for this SLRU"},' + '{"caption": "%Hit", "id": "hit_pct", "class": "table_obj_value", ' + '"title": "Number of disk blocks hits for this SLRU as a percentage of reads + hits"},' + '{"caption": "Writes", "id": "blks_written", "class": "table_obj_value", ' + '"title": "Number of disk blocks written for this SLRU"},' + '{"caption": "Checked", "id": "blks_exists", "class": "table_obj_value", ' + '"title": "Number of blocks checked for existence for this SLRU (blks_exists field)"},' + '{"caption": "Flushes", "id": "flushes", "class": "table_obj_value", ' + '"title": "Number of flushes of dirty data for this SLRU"},' + '{"caption": "Truncates", "id": "truncates", "class": "table_obj_value", ' + '"title": "Number of truncates for this SLRU"}' + ']' + '}]'::jsonb), (1, 'sesstat', 'srvstat', 400, 'Session statistics by database', 'Session statistics by database', 'sess_stats', NULL, 'db_stat_sessions', NULL, '[{' '"type": "row_table",' @@ -392,7 +519,7 @@ VALUES '"type": "row_table", ' '"class": "stat", ' '"source": "wait_sampling_events",' - '"filter": "stmt_filter",' + '"filter": {"type": "exists", "field": "stmt_filter"},' '"ordering": "-stmt_waited",' '"limit": "topn",' '"columns": [' @@ -406,7 +533,7 @@ VALUES '"type": "row_table", ' '"class": "stat", ' '"source": "wait_sampling_events",' - '"filter": "total_filter",' + '"filter": {"type": "exists", "field": "total_filter"},' '"ordering": "-tot_waited",' '"limit": "topn",' '"columns": [' @@ -428,7 +555,7 @@ VALUES '"class": "stat", ' '"source": "top_statements",' '"ordering": "ord_total_time",' - '"filter": "total_time",' + '"filter": {"type": "exists", "field": "total_time"},' '"limit": "topn",' '"columns": [' '{"id": "hexqueryid", "class": "mono queryId", "caption": "Query ID"}, ' @@ -459,7 +586,7 @@ VALUES '"class": "stat", ' '"source": "top_statements",' '"ordering": "ord_plan_time",' - '"filter": "total_plan_time",' + '"filter": {"type": "exists", "field": "total_plan_time"},' '"limit": "topn",' '"columns": [' '{"id": "hexqueryid", "class": "mono queryId", "caption": "Query ID"}, ' @@ -483,7 +610,7 @@ VALUES '"class": "stat", ' '"source": "top_statements",' '"ordering": "ord_exec_time",' - '"filter": "total_exec_time",' + '"filter": {"type": "exists", "field": "total_exec_time"},' '"limit": "topn",' '"columns": [' '{"id": "hexqueryid", "caption": "Query ID", "class": "mono queryId"}, ' @@ -538,7 +665,7 @@ VALUES '"class": "stat", ' '"source": "top_statements",' '"ordering": "ord_io_time",' - '"filter": "io_time",' + '"filter": {"type": "exists", "field": "io_time"},' '"limit": "topn",' '"columns": [' '{"id": "hexqueryid", "class": "mono queryId", "caption": "Query ID"}, ' @@ -567,7 +694,7 @@ VALUES '"class": "stat", ' '"source": "top_statements",' '"ordering": "ord_shared_blocks_fetched",' - '"filter": "shared_blks_fetched",' + '"filter": {"type": "exists", "field": "shared_blks_fetched"},' '"limit": "topn",' '"columns": [' '{"id": "hexqueryid", "class": "mono queryId", "caption": "Query ID"}, ' @@ -585,7 +712,7 @@ VALUES '"type": "row_table", ' '"class": "stat", ' '"source": "top_statements",' - '"filter": "shared_blks_read",' + '"filter": {"type": "exists", "field": "shared_blks_read"},' '"ordering": "ord_shared_blocks_read",' '"limit": "topn",' '"columns": [' @@ -604,7 +731,7 @@ VALUES '"type": "row_table", ' '"class": "stat",' '"source": "top_statements",' - '"filter": "shared_blks_dirtied",' + '"filter": {"type": "exists", "field": "shared_blks_dirtied"},' '"ordering": "ord_shared_blocks_dirt",' '"limit": "topn",' '"columns": [' @@ -627,7 +754,7 @@ VALUES '"type": "row_table", ' '"class": "stat", ' '"source": "top_statements",' - '"filter": "shared_blks_written",' + '"filter": {"type": "exists", "field": "shared_blks_written"},' '"ordering": "ord_shared_blocks_written",' '"limit": "topn",' '"columns": [' @@ -648,7 +775,7 @@ VALUES '"type": "row_table", ' '"class": "stat", ' '"source": "top_statements",' - '"filter": "wal_bytes",' + '"filter": {"type": "exists", "field": "wal_bytes"},' '"ordering": "ord_wal",' '"limit": "topn",' '"columns": [' @@ -667,7 +794,7 @@ VALUES '"type": "row_table", ' '"class": "stat", ' '"source": "top_statements",' - '"filter": "sum_tmp_blks",' + '"filter": {"type": "exists", "field": "sum_tmp_blks"},' '"ordering": "ord_temp",' '"limit": "topn",' '"columns": [' @@ -698,7 +825,7 @@ VALUES '"type": "row_table", ' '"class": "stat", ' '"source": "top_statements",' - '"filter": "ord_temp_io_time",' + '"filter": {"type": "exists", "field": "ord_temp_io_time"},' '"ordering": "ord_temp_io_time",' '"limit": "topn",' '"columns": [' @@ -726,7 +853,7 @@ VALUES '"type": "row_table", ' '"class": "stat", ' '"source": "top_statements",' - '"filter": "sum_jit_time",' + '"filter": {"type": "exists", "field": "sum_jit_time"},' '"ordering": "ord_jit",' '"limit": "topn",' '"columns": [' @@ -765,7 +892,7 @@ VALUES '"type": "row_table", ' '"class": "stat", ' '"source": "top_rusage_statements",' - '"filter": "sum_cpu_time",' + '"filter": {"type": "exists", "field": "sum_cpu_time"},' '"ordering": "ord_cpu_time",' '"limit": "topn",' '"columns": [' @@ -789,7 +916,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_rusage_statements",' - '"filter": "sum_io_bytes",' + '"filter": {"type": "exists", "field": "sum_io_bytes"},' '"ordering": "ord_io_bytes",' '"limit": "topn",' '"columns": [' @@ -798,12 +925,12 @@ VALUES '{"id": "username", "class": "table_obj_name", "caption": "User"},' '{"title": "Filesystem reads", "caption": "Read Bytes", "columns": [' '{"id": "plan_reads", "class": "table_obj_value", "title": "Filesystem read amount during planning", "caption": "Plan", "condition": "rusage_planstats"},' - '{"id": "exec_reads", "class": "table_obj_value", "title": "Filesystem read amount during execution", "caption": "Exec"},' + '{"id": "exec_reads", "class": "table_obj_value", "title": "Filesystem read amount during execution", "caption": "Bytes"},' '{"id": "reads_total_pct", "class": "table_obj_value", "title": "Filesystem read amount of this statement as a percentage of all statements FS read amount", "caption": "%Total"}' ']},' '{"title": "Filesystem writes", "caption": "Write Bytes", "columns": [' '{"id": "plan_writes", "class": "table_obj_value", "title": "Filesystem write amount during planning", "caption": "Plan", "condition": "rusage_planstats"},' - '{"id": "exec_writes", "class": "table_obj_value", "title": "Filesystem write amount during execution", "caption": "Exec"},' + '{"id": "exec_writes", "class": "table_obj_value", "title": "Filesystem write amount during execution", "caption": "Bytes"},' '{"id": "writes_total_pct", "class": "table_obj_value", "title": "Filesystem write amount of this statement as a percentage of all statements FS read amount", "caption": "%Total"}' ']}' ']' @@ -830,7 +957,7 @@ VALUES '"type": "row_table",' '"class": "toast",' '"source": "top_tables",' - '"filter": "ord_seq_scan",' + '"filter": {"type": "exists", "field": "ord_seq_scan"},' '"ordering": "ord_seq_scan",' '"limit": "topn",' '"columns": [' @@ -869,7 +996,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_io_tables",' - '"filter": "ord_fetch",' + '"filter": {"type": "exists", "field": "ord_fetch"},' '"ordering": "ord_fetch",' '"limit": "topn",' '"columns": [' @@ -900,7 +1027,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_io_tables",' - '"filter": "ord_read",' + '"filter": {"type": "exists", "field": "ord_read"},' '"ordering": "ord_read",' '"limit": "topn",' '"columns": [' @@ -932,7 +1059,7 @@ VALUES '"type": "row_table",' '"class": "toast",' '"source": "top_tables",' - '"filter": "ord_dml",' + '"filter": {"type": "exists", "field": "ord_dml"},' '"ordering": "ord_dml",' '"limit": "topn",' '"columns": [' @@ -950,12 +1077,12 @@ VALUES '{"caption": "IxFet", "id": ["idx_tup_fetch", "toastidx_tup_fetch"], "title": "Number of live rows fetched by index scans", "class": "table_obj_value"}' ']' '}]'::jsonb), -(1, 'tblud', 'objects', 500, 'Top tables by updated/deleted tuples', 'Top tables by updated/deleted tuples', NULL, NULL, 'vac_tbl', NULL, +(1, 'tblud', 'objects', 500, 'Top tables by updated/deleted tuples', 'Top tables by updated/deleted tuples', NULL, NULL, 'upd_del_tbl', NULL, '[{' '"type": "row_table",' '"class": "toast",' '"source": "top_tables",' - '"filter": "ord_upd",' + '"filter": {"type": "exists", "field": "ord_upd"},' '"ordering": "ord_upd",' '"limit": "topn",' '"columns": [' @@ -972,13 +1099,35 @@ VALUES '{"caption": "AutoAnalyze", "id": ["autoanalyze_count", "toastautoanalyze_count"], "title": "Number of times this table has been analyzed by the autovacuum daemon", "class": "table_obj_value"}' ']' '}]'::jsonb), +(1, 'tblupd_np', 'objects', 550, 'Top tables by new-page updated tuples', 'Top tables by new-page updated tuples', 'table_new_page_updates', NULL, 'upd_np_tbl', + '

Top tables by number of rows updated where the successor version goes onto a new heap page, ' + 'leaving behind an original version with a t_ctid field that points to a different heap page. ' + 'These are always non-HOT updates.

', + '[{' + '"type": "row_table",' + '"class": "toast",' + '"source": "top_tables",' + '"filter": {"type": "exists", "field": "ord_upd_np"},' + '"ordering": "ord_upd_np",' + '"limit": "topn",' + '"columns": [' + '{"caption": "DB", "id": "dbname", "class": "hdr", "rowspan": true},' + '{"caption": "Tablespace", "id": "tablespacename", "class": "hdr", "rowspan": true},' + '{"caption": "Schema", "id": "schemaname", "class": "hdr", "rowspan": true},' + '{"caption": "Table", "id": ["relname", "toastrelname"], "class": "table_obj_name"},' + '{"caption": "NP Upd", "id": ["n_tup_newpage_upd", "toastn_tup_newpage_upd"], "title": "Number of rows updated to a new heap page", "class": "table_obj_value"},' + '{"caption": "%Upd", "id": ["np_upd_pct", "toastnp_upd_pct"], "title": "Number of new-page updated rows as a percentage of all rows updated", "class": "table_obj_value"},' + '{"caption": "Upd", "id": ["n_tup_upd", "toastn_tup_upd"], "title": "Number of rows updated (includes HOT updated rows)", "class": "table_obj_value"},' + '{"caption": "Upd(HOT)", "id": ["n_tup_hot_upd", "toastn_tup_hot_upd"], "title": "Number of rows HOT updated (i.e., with no separate index update required)", "class": "table_obj_value"}' + ']' + '}]'::jsonb), (1, 'tblgrw', 'objects', 600, 'Top growing tables', 'Top growing tables', NULL, NULL, 'growth_tbl', '{func_output}', '[{' '"type": "row_table",' '"class": "toast",' '"source": "top_tables",' - '"filter": "ord_growth",' + '"filter": {"type": "exists", "field": "ord_growth"},' '"ordering": "ord_growth",' '"limit": "topn",' '"columns": [' @@ -999,7 +1148,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_io_indexes",' - '"filter": "ord_fetch",' + '"filter": {"type": "exists", "field": "ord_fetch"},' '"ordering": "ord_fetch",' '"limit": "topn",' '"columns": [' @@ -1018,7 +1167,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_io_indexes",' - '"filter": "ord_read",' + '"filter": {"type": "exists", "field": "ord_read"},' '"ordering": "ord_read",' '"limit": "topn",' '"columns": [' @@ -1039,7 +1188,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_indexes",' - '"filter": "ord_growth",' + '"filter": {"type": "exists", "field": "ord_growth"},' '"ordering": "ord_growth",' '"limit": "topn",' '"columns": [' @@ -1066,7 +1215,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_indexes",' - '"filter": "ord_unused",' + '"filter": {"type": "exists", "field": "ord_unused"},' '"ordering": "ord_unused",' '"limit": "topn",' '"columns": [' @@ -1098,7 +1247,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_functions",' - '"filter": "ord_time",' + '"filter": {"type": "exists", "field": "ord_time"},' '"ordering": "ord_time",' '"limit": "topn",' '"columns": [' @@ -1119,7 +1268,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_functions",' - '"filter": "ord_calls",' + '"filter": {"type": "exists", "field": "ord_calls"},' '"ordering": "ord_calls",' '"limit": "topn",' '"columns": [' @@ -1140,7 +1289,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_functions",' - '"filter": "ord_trgtime",' + '"filter": {"type": "exists", "field": "ord_trgtime"},' '"ordering": "ord_trgtime",' '"limit": "topn",' '"columns": [' @@ -1168,7 +1317,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_tables",' - '"filter": "ord_vac",' + '"filter": {"type": "exists", "field": "ord_vac"},' '"ordering": "ord_vac",' '"limit": "topn",' '"columns": [' @@ -1189,7 +1338,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_tables",' - '"filter": "ord_anl",' + '"filter": {"type": "exists", "field": "ord_anl"},' '"ordering": "ord_anl",' '"limit": "topn",' '"columns": [' @@ -1209,7 +1358,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_indexes",' - '"filter": "ord_vac",' + '"filter": {"type": "exists", "field": "ord_vac"},' '"ordering": "ord_vac",' '"limit": "topn",' '"columns": [' @@ -1231,7 +1380,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_tbl_last_sample",' - '"filter": "ord_dead",' + '"filter": {"type": "exists", "field": "ord_dead"},' '"ordering": "ord_dead",' '"limit": "topn",' '"columns": [' @@ -1252,7 +1401,7 @@ VALUES '"type": "row_table",' '"class": "stat",' '"source": "top_tbl_last_sample",' - '"filter": "ord_mod",' + '"filter": {"type": "exists", "field": "ord_mod"},' '"ordering": "ord_mod",' '"limit": "topn",' '"columns": [' @@ -1280,7 +1429,7 @@ VALUES '"type": "row_table",' '"class": "setlist",' '"source": "settings",' - '"filter": "defined_val",' + '"filter": {"type": "exists", "field": "defined_val"},' '"columns": [' '{"caption": "Defined settings", "columns": [' '{"caption": "Setting", "id": "name", "class": "table_obj_value"},' @@ -1295,7 +1444,7 @@ VALUES '"type": "row_table",' '"class": "setlist",' '"source": "settings",' - '"filter": "default_val",' + '"filter": {"type": "exists", "field": "default_val"},' '"columns": [' '{"caption": "Default settings", "columns": [' '{"caption": "Setting", "id": "name", "class": "table_obj_value"},' @@ -1335,7 +1484,7 @@ VALUES (2, 'funchdr', NULL, 600, 'User function statistics', 'User function statistics', 'function_stats', NULL, 'func_stat', NULL, NULL), (2, 'vachdr', NULL, 700, 'Vacuum-related statistics', 'Vacuum-related statistics', NULL, NULL, 'vacuum_stats', NULL, NULL), (2, 'settings', NULL, 800, 'Cluster settings during the report interval', 'Cluster settings during the report interval', NULL, NULL, 'pg_settings', NULL, NULL), -(2, 'stmt_warn', NULL, 900, NULL, 'Warning!', 'stmt_cnt_all', NULL, NULL, NULL, +(2, 'stmt_warn', NULL, 900, NULL, 'Warning!', 'stmt_cnt_all', NULL, 'stmt_warn', NULL, '[{' '"type": "row_table", ' '"source": "stmt_cnt_all",' @@ -1367,7 +1516,7 @@ VALUES '"ordering": "sample_id",' '"columns": [' '{"id": "interval_num", "class": "table_obj_value", "caption": "I"}, ' - '{"id": "datname", "class": "table_obj_name", "caption": "Database"}, ' + '{"id": "dbname", "class": "table_obj_name", "caption": "Database"}, ' '{"id": "sample_id", "class": "table_obj_value", "caption": "Sample"}, ' '{"id": "stats_reset", "class": "table_obj_value", "caption": "Reset time"}' ']' @@ -1413,6 +1562,135 @@ VALUES '{"id": ["datsize1", "datsize2"], "class": "table_obj_value", "title": "Database size as is was at the moment of last sample in report interval", "caption": "Size"}, ' '{"id": ["datsize_delta1", "datsize_delta2"], "class": "table_obj_value", "title": "Database size increment during report interval", "caption": "Growth"} ' ']}]'::jsonb), +(2, 'iostat', 'srvstat', 328, 'Cluster I/O statistics', 'Cluster I/O statistics', 'stat_io', NULL, 'stat_io', NULL, NULL), +(2, 'iostatrst', 'srvstat', 329, NULL, NULL, 'stat_io_reset', NULL, 'stat_io_reset', +'

Warning! IO stats reset was detected during report interval. Statistic values may be affected

', +'[{' + '"type": "row_table",' + '"class": "stat",' + '"source": "stat_io_reset",' + '"columns": [' + '{"caption": "Sample ID", "id": "sample_id", "class": "table_obj_name", ' + '"title": "Sample identifier with detected reset"},' + '{"caption": "Object", "id": "object", "class": "table_obj_name", ' + '"title": "Target object of an I/O operation"},' + '{"caption": "Backend", "id": "backend_type", "class": "table_obj_name", ' + '"title": "Type of backend (see stat_activity)"},' + '{"caption": "Context", "id": "context", "class": "table_obj_name", ' + '"title": "The context of an I/O operation"},' + '{"caption": "Reset time", "id": "stats_reset", "class": "table_obj_value", ' + '"title": "Date and time of the last reset performed in sample"}' + ']' + '}]'::jsonb), +(2, 'iostatmain', 'srvstat', 330, NULL, NULL, 'stat_io', NULL, 'stat_io', NULL, +'[{' + '"type": "row_table",' + '"class": "diff",' + '"source": "stat_io",' + '"columns": [' + '{"caption": "Object", "id": "object", "class": "hdr", "rowspan": true, ' + '"title": "Target object of an I/O operation"},' + '{"caption": "Backend", "id": "backend_type", "class": "hdr", "rowspan": true, ' + '"title": "Type of backend (see stat_activity)"},' + '{"caption": "Context", "id": "context", "class": "hdr", "rowspan": true, ' + '"title": "The context of an I/O operation"},' + '{"id": ["1", "2"], "class": "interval", "title":["properties.timePeriod1", "properties.timePeriod2"], "caption": "I"},' + '{"caption": "Reads", "columns": [' + '{"caption": "Count", "id": ["reads1", "reads2"], "class": "table_obj_value", ' + '"title": "Number of read operations"},' + '{"caption": "Bytes", "id": ["read_sz1", "read_sz2"], "class": "table_obj_value", ' + '"title": "Read data amount"},' + '{"caption": "Time", "id": ["read_time1", "read_time2"], "class": "table_obj_value", ' + '"condition": "io_times", ' + '"title": "Time spent in reading operation (seconds)"}' + ']},' + '{"caption": "Writes", "columns": [' + '{"caption": "Count", "id": ["writes1", "writes2"], "class": "table_obj_value", ' + '"title": "Number of write operations"},' + '{"caption": "Bytes", "id": ["write_sz1", "write_sz2"], "class": "table_obj_value", ' + '"title": "Written data amount"},' + '{"caption": "Time", "id": ["write_time1", "write_time2"], "class": "table_obj_value", ' + '"condition": "io_times", ' + '"title": "Time spent in writing operations (seconds)"}' + ']},' + '{"caption": "Writebacks", "columns": [' + '{"caption": "Count", "id": ["writebacks1", "writebacks2"], "class": "table_obj_value", ' + '"title": "Number of blocks which the process requested the kernel write out to permanent storage"},' + '{"caption": "Bytes", "id": ["writeback_sz1", "writeback_sz2"], "class": "table_obj_value", ' + '"title": "The amount of data requested for write out to permanent storage"},' + '{"caption": "Time", "id": ["writeback_time1", "writeback_time2"], "class": "table_obj_value", ' + '"condition": "io_times", ' + '"title": "Time spent in writeback operations (seconds)"}' + ']},' + '{"caption": "Extends", "columns": [' + '{"caption": "Count", "id": ["extends1", "extends2"], "class": "table_obj_value", ' + '"title": "Number of relation extend operations"},' + '{"caption": "Bytes", "id": ["extend_sz1", "extend_sz2"], "class": "table_obj_value", ' + '"title": "The amount of space used by extend operations"},' + '{"caption": "Time", "id": ["extend_time1", "extend_time2"], "class": "table_obj_value", ' + '"condition": "io_times", ' + '"title": "Time spent in extend operations (seconds)"}' + ']},' + '{"caption": "Hits", "id": ["hits1", "hits2"], "class": "table_obj_value", ' + '"title": "The number of times a desired block was found in a shared buffer"},' + '{"caption": "Evictions", "id": ["evictions1", "evictions2"], "class": "table_obj_value", ' + '"title": "Number of times a block has been written out from a shared or local buffer in order to make it available for another use"},' + '{"caption": "Reuses", "id": ["reuses1", "reuses2"], "class": "table_obj_value", ' + '"title": "The number of times an existing buffer in a size-limited ring buffer outside of shared buffers was reused as part of an I/O operation in the bulkread, bulkwrite, or vacuum contexts"},' + '{"caption": "Fsyncs", "columns": [' + '{"caption": "Count", "id": ["fsyncs1", "fsyncs2"], "class": "table_obj_value", ' + '"title": "Number of fsync calls. These are only tracked in context normal"},' + '{"caption": "Time", "id": ["fsync_time1", "fsync_time2"], "class": "table_obj_value", ' + '"condition": "io_times", ' + '"title": "Time spent in fsync operations (seconds)"}' + ']}' + ']' + '}]'::jsonb), +(2, 'slrustat', 'srvstat', 358, 'Cluster SLRU statistics', 'Cluster SLRU statistics', 'stat_slru', NULL, 'stat_slru', NULL, NULL), +(2, 'slrustatrst', 'slrustat', 359, NULL, NULL, 'stat_slru_reset', NULL, 'stat_slru_reset', +'

Warning! SLRU stats reset was detected during report interval. Statistic values may be affected

', +'[{' + '"type": "row_table",' + '"class": "stat",' + '"source": "stat_slru_reset",' + '"columns": [' + '{"caption": "Sample ID", "id": "sample_id", "class": "table_obj_name", ' + '"title": "Sample identifier with detected reset"},' + '{"caption": "Name", "id": "name", "class": "table_obj_name", ' + '"title": "Name of the SLRU"},' + '{"caption": "Reset time", "id": "stats_reset", "class": "table_obj_value", ' + '"title": "Date and time of the last reset performed in sample"}' + ']' + '}]'::jsonb), +(2, 'slrustatmain', 'slrustat', 360, NULL, NULL, 'stat_slru', NULL, 'stat_slru', NULL, +'[{' + '"type": "row_table",' + '"class": "diff",' + '"source": "stat_slru",' + '"columns": [' + '{"caption": "Name", "id": "name", "class": "hdr", "rowspan": true, ' + '"title": "Name of the SLRU"},' + '{"id": ["1", "2"], "class": "interval", "title":["properties.timePeriod1", "properties.timePeriod2"], "caption": "I"},' + '{"caption": "Zeroed", "id": ["blks_zeroed1", "blks_zeroed2"], "class": "table_obj_value", ' + '"title": "Number of blocks zeroed during initializations"},' + '{"caption": "Hits", "id": ["blks_hit1", "blks_hit2"], "class": "table_obj_value", ' + '"title": "Number of times disk blocks were found already in the SLRU, so that a ' + 'read was not necessary (this only includes hits in the SLRU, not the operating ' + 'system''s file system cache)"},' + '{"caption": "Reads", "id": ["blks_read1", "blks_read2"], "class": "table_obj_value", ' + '"title": "Number of disk blocks read for this SLRU"},' + '{"caption": "%Hit", "id": ["hit_pct1", "hit_pct2"], "class": "table_obj_value", ' + '"title": "Number of disk blocks hits for this SLRU as a percentage of reads + hits"},' + '{"caption": "Writes", "id": ["blks_written1", "blks_written2"], "class": "table_obj_value", ' + '"title": "Number of disk blocks written for this SLRU"},' + '{"caption": "Checked", "id": ["blks_exists1", "blks_exists2"], "class": "table_obj_value", ' + '"title": "Number of blocks checked for existence for this SLRU (blks_exists field)"},' + '{"caption": "Flushes", "id": ["flushes1", "flushes2"], "class": "table_obj_value", ' + '"title": "Number of flushes of dirty data for this SLRU"},' + '{"caption": "Truncates", "id": ["truncates1", "truncates2"], "class": "table_obj_value", ' + '"title": "Number of truncates for this SLRU"}' + ']' + '}]'::jsonb), (2, 'sesstat', 'srvstat', 400, 'Session statistics by database', 'Session statistics by database', 'sess_stats', NULL, 'db_stat_sessions', NULL, '[{' '"type": "row_table",' @@ -1711,7 +1989,7 @@ VALUES '"type": "row_table", ' '"class": "diff", ' '"source": "wait_sampling_events",' - '"filter": "stmt_filter",' + '"filter": {"type": "exists", "field": "stmt_filter"},' '"ordering": "stmt_ord",' '"limit": "topn",' '"columns": [' @@ -1726,7 +2004,7 @@ VALUES '"type": "row_table", ' '"class": "diff", ' '"source": "wait_sampling_events",' - '"filter": "total_filter",' + '"filter": {"type": "exists", "field": "total_filter"},' '"ordering": "tot_ord",' '"limit": "topn",' '"columns": [' @@ -1749,7 +2027,7 @@ VALUES '"class": "diff", ' '"source": "top_statements",' '"ordering": "ord_total_time",' - '"filter": "ord_total_time",' + '"filter": {"type": "exists", "field": "ord_total_time"},' '"limit": "topn",' '"columns": [' '{"id": "hexqueryid", "class": "hdr mono queryId", "caption": "Query ID", "rowspan": true}, ' @@ -1781,7 +2059,7 @@ VALUES '"class": "diff", ' '"source": "top_statements",' '"ordering": "ord_plan_time",' - '"filter": "ord_plan_time",' + '"filter": {"type": "exists", "field": "ord_plan_time"},' '"limit": "topn",' '"columns": [' '{"id": "hexqueryid", "class": "hdr mono queryId", "caption": "Query ID", "rowspan": true}, ' @@ -1806,7 +2084,7 @@ VALUES '"class": "diff", ' '"source": "top_statements",' '"ordering": "ord_exec_time",' - '"filter": "ord_exec_time",' + '"filter": {"type": "exists", "field": "ord_exec_time"},' '"limit": "topn",' '"columns": [' '{"id": "hexqueryid", "caption": "Query ID", "class": "hdr mono queryId", "rowspan": true}, ' @@ -1863,7 +2141,7 @@ VALUES '"class": "diff", ' '"source": "top_statements",' '"ordering": "ord_io_time",' - '"filter": "ord_io_time",' + '"filter": {"type": "exists", "field": "ord_io_time"},' '"limit": "topn",' '"columns": [' '{"id": "hexqueryid", "class": "hdr mono queryId", "caption": "Query ID", "rowspan": true}, ' @@ -1894,7 +2172,7 @@ VALUES '"class": "diff", ' '"source": "top_statements",' '"ordering": "ord_shared_blocks_fetched",' - '"filter": "ord_shared_blocks_fetched",' + '"filter": {"type": "exists", "field": "ord_shared_blocks_fetched"},' '"limit": "topn",' '"columns": [' '{"id": "hexqueryid", "class": "hdr mono queryId", "caption": "Query ID", "rowspan": true}, ' @@ -1913,7 +2191,7 @@ VALUES '"type": "row_table", ' '"class": "diff", ' '"source": "top_statements",' - '"filter": "ord_shared_blocks_read",' + '"filter": {"type": "exists", "field": "ord_shared_blocks_read"},' '"ordering": "ord_shared_blocks_read",' '"limit": "topn",' '"columns": [' @@ -1934,7 +2212,7 @@ VALUES '"type": "row_table", ' '"class": "diff", ' '"source": "top_statements",' - '"filter": "ord_shared_blocks_dirt",' + '"filter": {"type": "exists", "field": "ord_shared_blocks_dirt"},' '"ordering": "ord_shared_blocks_dirt",' '"limit": "topn",' '"columns": [' @@ -1958,7 +2236,7 @@ VALUES '"type": "row_table", ' '"class": "diff", ' '"source": "top_statements",' - '"filter": "ord_shared_blocks_written",' + '"filter": {"type": "exists", "field": "ord_shared_blocks_written"},' '"ordering": "ord_shared_blocks_written",' '"limit": "topn",' '"columns": [' @@ -1980,7 +2258,7 @@ VALUES '"type": "row_table", ' '"class": "diff", ' '"source": "top_statements",' - '"filter": "ord_wal",' + '"filter": {"type": "exists", "field": "ord_wal"},' '"ordering": "ord_wal",' '"limit": "topn",' '"columns": [' @@ -2000,7 +2278,7 @@ VALUES '"type": "row_table", ' '"class": "diff", ' '"source": "top_statements",' - '"filter": "ord_temp",' + '"filter": {"type": "exists", "field": "ord_temp"},' '"ordering": "ord_temp",' '"limit": "topn",' '"columns": [' @@ -2032,7 +2310,7 @@ VALUES '"type": "row_table", ' '"class": "diff", ' '"source": "top_statements",' - '"filter": "ord_temp_io_time",' + '"filter": {"type": "exists", "field": "ord_temp_io_time"},' '"ordering": "ord_temp_io_time",' '"limit": "topn",' '"columns": [' @@ -2061,7 +2339,7 @@ VALUES '"type": "row_table", ' '"class": "diff", ' '"source": "top_statements",' - '"filter": "ord_jit",' + '"filter": {"type": "exists", "field": "ord_jit"},' '"ordering": "ord_jit",' '"limit": "topn",' '"columns": [' @@ -2101,7 +2379,7 @@ VALUES '"type": "row_table", ' '"class": "diff", ' '"source": "top_rusage_statements",' - '"filter": "ord_cpu_time",' + '"filter": {"type": "exists", "field": "ord_cpu_time"},' '"ordering": "ord_cpu_time",' '"limit": "topn",' '"columns": [' @@ -2126,7 +2404,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_rusage_statements",' - '"filter": "ord_io_bytes",' + '"filter": {"type": "exists", "field": "ord_io_bytes"},' '"ordering": "ord_io_bytes",' '"limit": "topn",' '"columns": [' @@ -2136,12 +2414,12 @@ VALUES '{"id": ["1", "2"], "title":["properties.timePeriod1", "properties.timePeriod2"], "class": "interval", "caption": "I"},' '{"title": "Filesystem reads", "caption": "Read Bytes", "columns": [' '{"id": ["plan_reads1", "plan_reads2"], "class": "table_obj_value", "title": "Filesystem read amount during planning", "caption": "Plan", "condition": "rusage_planstats"},' - '{"id": ["exec_reads1", "exec_reads2"], "class": "table_obj_value", "title": "Filesystem read amount during execution", "caption": "Exec"},' + '{"id": ["exec_reads1", "exec_reads2"], "class": "table_obj_value", "title": "Filesystem read amount during execution", "caption": "Bytes"},' '{"id": ["reads_total_pct1", "reads_total_pct2"], "class": "table_obj_value", "title": "Filesystem read amount of this statement as a percentage of all statements FS read amount", "caption": "%Total"}' ']},' '{"title": "Filesystem writes", "caption": "Write Bytes", "columns": [' '{"id": ["plan_writes1", "plan_writes2"], "class": "table_obj_value", "title": "Filesystem write amount during planning", "caption": "Plan", "condition": "rusage_planstats"},' - '{"id": ["exec_writes1", "exec_writes2"], "class": "table_obj_value", "title": "Filesystem write amount during execution", "caption": "Exec"},' + '{"id": ["exec_writes1", "exec_writes2"], "class": "table_obj_value", "title": "Filesystem write amount during execution", "caption": "Bytes"},' '{"id": ["writes_total_pct1", "writes_total_pct2"], "class": "table_obj_value", "title": "Filesystem write amount of this statement as a percentage of all statements FS read amount", "caption": "%Total"}' ']}' ']' @@ -2168,7 +2446,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_tables",' - '"filter": "ord_seq_scan",' + '"filter": {"type": "exists", "field": "ord_seq_scan"},' '"ordering": "ord_seq_scan",' '"limit": "topn",' '"columns": [' @@ -2212,7 +2490,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_io_tables",' - '"filter": "ord_fetch",' + '"filter": {"type": "exists", "field": "ord_fetch"},' '"ordering": "ord_fetch",' '"limit": "topn",' '"columns": [' @@ -2244,7 +2522,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_io_tables",' - '"filter": "ord_read",' + '"filter": {"type": "exists", "field": "ord_read"},' '"ordering": "ord_read",' '"limit": "topn",' '"columns": [' @@ -2277,7 +2555,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_tables",' - '"filter": "ord_dml",' + '"filter": {"type": "exists", "field": "ord_dml"},' '"ordering": "ord_dml",' '"limit": "topn",' '"columns": [' @@ -2300,12 +2578,12 @@ VALUES ']}' ']' '}]'::jsonb), -(2, 'tblud', 'objects', 500, 'Top tables by updated/deleted tuples', 'Top tables by updated/deleted tuples', NULL, NULL, 'vac_tbl', NULL, +(2, 'tblud', 'objects', 500, 'Top tables by updated/deleted tuples', 'Top tables by updated/deleted tuples', NULL, NULL, 'upd_del_tbl', NULL, '[{' '"type": "row_table",' '"class": "diff",' '"source": "top_tables",' - '"filter": "ord_upd",' + '"filter": {"type": "exists", "field": "ord_upd"},' '"ordering": "ord_upd",' '"limit": "topn",' '"columns": [' @@ -2323,13 +2601,36 @@ VALUES '{"caption": "AutoAnalyze", "id": ["autoanalyze_count1", "autoanalyze_count2"], "title": "Number of times this table has been analyzed by the autovacuum daemon", "class": "table_obj_value"}' ']' '}]'::jsonb), +(2, 'tblupd_np', 'objects', 550, 'Top tables by new-page updated tuples', 'Top tables by new-page updated tuples', 'table_new_page_updates', NULL, 'upd_np_tbl', + '

Top tables by number of rows updated where the successor version goes onto a new heap page, ' + 'leaving behind an original version with a t_ctid field that points to a different heap page. ' + 'These are always non-HOT updates.

', + '[{' + '"type": "row_table",' + '"class": "diff",' + '"source": "top_tables",' + '"filter": {"type": "exists", "field": "ord_upd_np"},' + '"ordering": "ord_upd_np",' + '"limit": "topn",' + '"columns": [' + '{"caption": "DB", "id": "dbname", "class": "hdr", "rowspan": true},' + '{"caption": "Tablespace", "id": "tablespacename", "class": "hdr", "rowspan": true},' + '{"caption": "Schema", "id": "schemaname", "class": "hdr", "rowspan": true},' + '{"caption": "Table", "id": "relname", "class": "hdr", "rowspan": true},' + '{"caption": "I", "id": ["1", "2"], "title":["properties.timePeriod1", "properties.timePeriod2"], "class": "interval"},' + '{"caption": "NP Upd", "id": ["n_tup_newpage_upd1", "n_tup_newpage_upd2"], "title": "Number of rows updated to a new heap page", "class": "table_obj_value"},' + '{"caption": "%Upd", "id": ["np_upd_pct1", "np_upd_pct2"], "title": "Number of new-page updated rows as a percentage of all rows updated", "class": "table_obj_value"},' + '{"caption": "Upd", "id": ["n_tup_upd1", "n_tup_upd2"], "title": "Number of rows updated (includes HOT updated rows)", "class": "table_obj_value"},' + '{"caption": "Upd(HOT)", "id": ["n_tup_hot_upd1", "n_tup_hot_upd2"], "title": "Number of rows HOT updated (i.e., with no separate index update required)", "class": "table_obj_value"}' + ']' + '}]'::jsonb), (2, 'tblgrw', 'objects', 600, 'Top growing tables', 'Top growing tables', NULL, NULL, 'growth_tbl', '{func_output}', '[{' '"type": "row_table",' '"class": "diff",' '"source": "top_tables",' - '"filter": "ord_growth",' + '"filter": {"type": "exists", "field": "ord_growth"},' '"ordering": "ord_growth",' '"limit": "topn",' '"columns": [' @@ -2361,7 +2662,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_io_indexes",' - '"filter": "ord_fetch",' + '"filter": {"type": "exists", "field": "ord_fetch"},' '"ordering": "ord_fetch",' '"limit": "topn",' '"columns": [' @@ -2381,7 +2682,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_io_indexes",' - '"filter": "ord_read",' + '"filter": {"type": "exists", "field": "ord_read"},' '"ordering": "ord_read",' '"limit": "topn",' '"columns": [' @@ -2403,7 +2704,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_indexes",' - '"filter": "ord_growth",' + '"filter": {"type": "exists", "field": "ord_growth"},' '"ordering": "ord_growth",' '"limit": "topn",' '"columns": [' @@ -2436,7 +2737,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_functions",' - '"filter": "ord_time",' + '"filter": {"type": "exists", "field": "ord_time"},' '"ordering": "ord_time",' '"limit": "topn",' '"columns": [' @@ -2458,7 +2759,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_functions",' - '"filter": "ord_calls",' + '"filter": {"type": "exists", "field": "ord_calls"},' '"ordering": "ord_calls",' '"limit": "topn",' '"columns": [' @@ -2480,7 +2781,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_functions",' - '"filter": "ord_trgtime",' + '"filter": {"type": "exists", "field": "ord_trgtime"},' '"ordering": "ord_trgtime",' '"limit": "topn",' '"columns": [' @@ -2509,7 +2810,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_tables",' - '"filter": "ord_vac",' + '"filter": {"type": "exists", "field": "ord_vac"},' '"ordering": "ord_vac",' '"limit": "topn",' '"columns": [' @@ -2531,7 +2832,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_tables",' - '"filter": "ord_anl",' + '"filter": {"type": "exists", "field": "ord_anl"},' '"ordering": "ord_anl",' '"limit": "topn",' '"columns": [' @@ -2553,7 +2854,7 @@ VALUES '"type": "row_table",' '"class": "diff",' '"source": "top_indexes",' - '"filter": "ord_vac",' + '"filter": {"type": "exists", "field": "ord_vac"},' '"ordering": "ord_vac",' '"limit": "topn",' '"columns": [' @@ -2582,7 +2883,7 @@ VALUES '"type": "row_table",' '"class": "setlist",' '"source": "settings",' - '"filter": "defined_val",' + '"filter": {"type": "exists", "field": "defined_val"},' '"columns": [' '{"caption": "Defined settings", "columns": [' '{"caption": "Setting", "id": "name", "class": "table_obj_value"},' @@ -2597,7 +2898,7 @@ VALUES '"type": "row_table",' '"class": "setlist",' '"source": "settings",' - '"filter": "default_val",' + '"filter": {"type": "exists", "field": "default_val"},' '"columns": [' '{"caption": "Default settings", "columns": [' '{"caption": "Setting", "id": "name", "class": "table_obj_value"},' diff --git a/data/static/css/style.css b/data/static/css/style.css index 0270e5a..7c4ef91 100644 --- a/data/static/css/style.css +++ b/data/static/css/style.css @@ -23,26 +23,66 @@ a:hover { } #navigator { position: var(--main-position); - background-color: #ffffff; + background-color: transparent; border-radius: 4px; - padding: 10px 20px 20px 30px; - box-shadow: var(--main-box-shadow); visibility: hidden; top: 2%; height: 92%; - right: -15%; + right: 0; overflow: auto; - opacity: 0.2; + opacity: 0.9; transition: opacity 300ms linear, visibility 300ms linear, right 300ms linear; + display: flex; + flex-direction: row; + flex-wrap: nowrap; +} +#navigator div { + margin-top: 15px; + height: 100px; + background-color: royalblue; + writing-mode: vertical-lr; + font-size: 14px; + letter-spacing: 2px; + text-align: center; + transition: width 300ms linear; + color: white; +} +#navigator div:hover { + cursor: pointer; +} +#navigator ul { + background-color: white; +} +#navigator div.active { + width: 14px; +} +#navigator div.active:hover { + width: 20px; +} +#navigator div.hidden { + width: 48px; +} +#navigator div.hidden:hover { + width: 42px; +} +#navigator ul.active { + box-shadow: var(--main-box-shadow); + overflow: auto; + display: block; +} +#navigator ul.hidden { + display: none; } #navigator:hover { - opacity: 0.9; - right: 0; + opacity: 1; +} +#navigator li.current { + border: 2px solid black; + border-radius: 3px; } -#navigator li.active { +#navigator li.active{ background-color: var(--secondary-bg-color); border-radius: 3px; - padding: 2px; } #commonstat { display: flex; @@ -120,10 +160,10 @@ svg rect:hover, svg circle:hover, svg path:hover, a.copyButton svg:hover>rect{ } /* ----------- Differential report styles ----------- */ -.int1 td:not(.hdr), table.setlist tr.new_i1 { +td.int1, .int1 td:not(.hdr), table.setlist tr.new_i1 { background-color: #FFEEEE; } -.int2 td:not(.hdr), table.setlist tr.new_i2 { +td.int2, .int2 td:not(.hdr), table.setlist tr.new_i2 { background-color: #EEEEFF; } table.toast tr.int1:not(.active) td:not(.hdr) { diff --git a/data/static/js/chart.js b/data/static/js/chart.js index bb9d755..e64caa6 100644 --- a/data/static/js/chart.js +++ b/data/static/js/chart.js @@ -23,17 +23,17 @@ class PipeChart extends BaseChart { let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.setAttribute('width', '100%'); - svg.setAttribute('height', '100%'); + svg.setAttribute('height', '2em'); orderedData.forEach(elem => { - let width = Math.ceil(elem[value]); + let width = Math.floor(elem[value]); let nestedSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); nestedSvg.setAttribute('x', `${x}%`); nestedSvg.setAttribute('height', '2em'); nestedSvg.setAttribute('width', `${width}%`); let title = document.createElementNS('http://www.w3.org/2000/svg', 'title'); - title.innerHTML = `${elem.objname}: ${elem[key]}`; + title.innerHTML = `${elem.objname}: ${elem[value]}`; let text = document.createElementNS('http://www.w3.org/2000/svg', 'text'); text.setAttribute('y', '70%'); diff --git a/data/static/js/generate.js b/data/static/js/generate.js index a4712e3..52476f5 100644 --- a/data/static/js/generate.js +++ b/data/static/js/generate.js @@ -334,7 +334,7 @@ class BaseTable extends BaseSection { let newCell = newRow.insertCell(-1); /** Setting id on tr */ - newRow.setAttribute('id', `${row.wait_event_type}_${row.hexqueryid}_${row.hexplanid}`); + newRow.setAttribute('id', `${row.event_type}_${row.hexqueryid}_${row.hexplanid}`); /** Setting rowspan attributes to new cell */ if (column.rowspan) { @@ -351,24 +351,20 @@ class BaseTable extends BaseSection { for (let i = 0; i < row[column.id].length; i++) { let details = row[column.id][i]; - if (details.wait_event) { + if (details.event) { let p = document.createElement('p'); let a = document.createElement('a'); - if (row.wait_event_type === 'Total') { - a.href = `#${details.wait_event}_${details.hexqueryid}_${details.hexplanid}`; + if (row.event_type === 'Total') { + a.href = `#${details.event}_${row.hexqueryid}_${row.hexplanid}`; } - a.innerHTML = details.wait_event; + a.innerHTML = details.event; p.appendChild(a); let colons = document.createTextNode(': '); p.appendChild(colons); let strong = document.createElement('strong'); - strong.innerHTML = details.waited; + strong.innerHTML = details.wait; p.appendChild(strong); newCell.appendChild(p); - } else if (details.wait_event) { - let p = document.createElement('p'); - p.insertAdjacentHTML('afterbegin', `${details.wait_event}: ${details.waited}`); - newCell.appendChild(p); } } } @@ -634,8 +630,8 @@ class HorizontalTable extends BaseTable { 'hexplanid': 'data-hexplanid', 'toplevel': 'data-toplevel', 'userid': 'data-userid', - 'wait_event_type': 'data-waiteventtype', - 'wait_event': 'data-waitevent', + 'event_type': 'data-event_type', + 'event': 'data-event', 'tablespacename': 'data-tablespacename', 'schemaname': 'data-schemaname', 'relname': 'data-relname', @@ -684,8 +680,10 @@ class HorizontalTable extends BaseTable { /** Iterate over all unique columns */ for (let k = 0; k < columns[j].length; k++) { + let column = columns[j][k]; + /** Build cells inside */ - isEmpty.push(HorizontalTable.buildCell(newRow, columns[j][k], row)); + isEmpty.push(HorizontalTable.buildCell(newRow, column, row)); } /** Remove row, if all cells in row are empty */ diff --git a/data/static/js/highlight.js b/data/static/js/highlight.js index a518b75..c0d529f 100644 --- a/data/static/js/highlight.js +++ b/data/static/js/highlight.js @@ -41,6 +41,13 @@ class Highlighter { let isEqual = Highlighter.isDatasetEqual(tr.dataset, elem.dataset, elem); if (isEqual) { elem.classList.add('active'); + let navId = this.getClosestTag(elem, 0, 'div').firstChild.id; + if (navId) { + let navLi= document.getElementById(`navigator_${navId}`); + if (navLi && !navLi.classList.contains('active')) { + navLi.classList.add('active'); + } + } } }); } else { @@ -89,11 +96,19 @@ class Highlighter { elem.classList.remove('active'); } }) + let navigator = document.getElementById('navigator'); + if (navigator) { + let allItems = document.querySelectorAll('li'); + allItems.forEach(item => { + if (item.classList.contains('active')) { + item.classList.remove('active'); + } + }) + } } /** * If datasets in target and in row are the same - highlight the row. - * TODO: Продумать как подсвечивать отдельные ячейки при неполном совпадении дата-атрибутов * @param targetDataset * @param rowDataset * @param elem @@ -116,6 +131,9 @@ class Highlighter { /** If at least one data in datasets doesn't match */ for (let data in targetDataset) { + if (targetDataset[data] === '*' && rowDataset[data] !== undefined) { + continue; + } if (targetDataset[data] !== rowDataset[data]) { return false; } diff --git a/data/static/js/main.js b/data/static/js/main.js index 154eb34..e41c9f2 100644 --- a/data/static/js/main.js +++ b/data/static/js/main.js @@ -74,7 +74,7 @@ function main() { /** Add highlight feature */ Highlighter.init(); - /** Add highlight feature */ + /** Add copy feature */ Copier.init(); /** Add sort feature */ diff --git a/data/static/js/navigator.js b/data/static/js/navigator.js index 8e7063c..48d5150 100644 --- a/data/static/js/navigator.js +++ b/data/static/js/navigator.js @@ -8,29 +8,75 @@ class ReportNavigator { } document.querySelectorAll('h3').forEach(title => { let position = title.getBoundingClientRect().top; - if (position >= 0 && position < 50) { + if (position >= 0 && position < 100) { let li = `[href*=${title.id}]`; let elem = NAVIGATOR.querySelector(li).closest('li'); - if (!elem.classList.contains('active')) { + if (!elem.classList.contains('current')) { NAVIGATOR.querySelectorAll('li').forEach(item => { - item.removeAttribute('class'); + item.classList.remove('current'); }); - elem.setAttribute('class', 'active'); + elem.classList.add('current'); } } }) } } + static buildPageContent(data, parentNode) { + data.sections.forEach(section => { + let hasTableCap = ('tbl_cap' in section); + let hasNestedSections = ('sections' in section); + let ul = document.createElement('ul'); + let li = document.createElement('li'); + /** Creating
  • and tags inside
      */ + if (hasTableCap) { + + let a = document.createElement('a'); + + a.innerHTML = section.tbl_cap; + a.href = `#${section.href}`; + + li.setAttribute('id', `navigator_${section.href}`); + li.appendChild(a); + parentNode.appendChild(li); + } else { + ul = li; + } + /** Recursive call for building nested content */ + if (hasNestedSections) { + parentNode.appendChild(this.buildPageContent(section, ul)); + } + }) + + return parentNode; + } static init() { /** Create navigator, append it to the body and fill it with content */ const CONTENT = document.getElementById('content'); - const NAVIGATOR = document.createElement('ul'); + const NAVIGATOR = document.createElement('div'); NAVIGATOR.setAttribute('id', 'navigator'); - document.querySelector('body').appendChild(NAVIGATOR); - buildPageContent(data, NAVIGATOR); + let button = document.createElement('div'); + button.innerHTML = 'hide menu'; + button.setAttribute('class', 'active'); + button.setAttribute('title', 'Show / hide content'); + button.innerHTML = 'content'; + NAVIGATOR.appendChild(button); + let ul = document.createElement('ul'); + ul.setAttribute('class', 'active'); + NAVIGATOR.appendChild(ul); + button.addEventListener('click', event => { + if (ul.classList.contains('hidden')) { + ul.setAttribute('class', 'active'); + button.setAttribute('class', 'active'); + } else { + ul.setAttribute('class', 'hidden'); + button.setAttribute('class', 'hidden'); + } + }) + document.querySelector('body').appendChild(NAVIGATOR); + ReportNavigator.buildPageContent(data, ul); /** Add some useful events */ ReportNavigator.buildReportNavigator(CONTENT, NAVIGATOR); } -} \ No newline at end of file +} diff --git a/data/static/js/popup.js b/data/static/js/popup.js index 7af632b..9aae71f 100644 --- a/data/static/js/popup.js +++ b/data/static/js/popup.js @@ -25,7 +25,6 @@ class Popup { const POPUP = document.createElement('div'); POPUP.setAttribute('id', Popup.id); POPUP.setAttribute('class', Popup.klass); - POPUP.appendChild(document.createElement('p')); document.getElementById('container').appendChild(POPUP); return POPUP; @@ -46,6 +45,17 @@ class Popup { POPUP.style.setProperty('--main-bg-color', noticeProperties.bgColor); POPUP.style.setProperty('--main-font-color', noticeProperties.fontColor); POPUP.innerHTML = ''; /** Cleare all inside */ + + /** Add close link to popup */ + let close_link = document.createElement('a'); + close_link.innerHTML = 'x'; + close_link.onclick = function () { + POPUP.style.display = 'none'; + } + close_link.style.cursor = 'pointer'; + close_link.style.color = 'gray'; + + POPUP.appendChild(close_link); POPUP.appendChild(notice); if (noticeProperties.duration) { diff --git a/data/static/js/utilities.js b/data/static/js/utilities.js index 827cb21..5b5c5c0 100644 --- a/data/static/js/utilities.js +++ b/data/static/js/utilities.js @@ -22,10 +22,16 @@ class Utilities { static sum(data, key) { return data.reduce((partialSum, a) => partialSum + a[key], 0); } - /** Filter by boolean key */ + /** Advanced filter */ static filter(data, key) { - if (data.every(obj => key in obj)) { - return structuredClone(data.filter(obj => obj[key])); + if (key.type === "exists") { + if (data.every(obj => key["field"] in obj)) { + return structuredClone(data.filter(obj => obj[key["field"]])); + } + } else if (key.type === "equal") { + if (data.every(obj => key["field"] in obj)) { + return structuredClone(data.filter(obj => obj[key["field"]] === key["value"])); + } } return data; }