From 814d7ca838a5e7275e0c8b14fe7bc49f6eb50584 Mon Sep 17 00:00:00 2001 From: "dementii.priadko" <45518657+DEMNERD@users.noreply.github.com> Date: Fri, 7 Nov 2025 20:07:02 +0200 Subject: [PATCH 1/2] Added a table for the aggregated table stats dashboard --- .../dashboards/Dashboard_8_Table_Stats.json | 428 +++++++++++++++- flask-backend/app.py | 459 ++++++++++++------ 2 files changed, 725 insertions(+), 162 deletions(-) diff --git a/config/grafana/dashboards/Dashboard_8_Table_Stats.json b/config/grafana/dashboards/Dashboard_8_Table_Stats.json index 118d312..6c2ef7e 100644 --- a/config/grafana/dashboards/Dashboard_8_Table_Stats.json +++ b/config/grafana/dashboards/Dashboard_8_Table_Stats.json @@ -22,13 +22,439 @@ "links": [], "panels": [ { - "collapsed": false, + "collapsed": true, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 }, + "id": 44, + "panels": [ + { + "datasource": { + "type": "yesoreyeram-infinity-datasource", + "uid": "aerffb0z8rjlsc" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Total Size" + }, + "properties": [ + { + "id": "unit", + "value": "bytes" + }, + { + "id": "custom.width", + "value": 150 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Table Size" + }, + "properties": [ + { + "id": "unit", + "value": "bytes" + }, + { + "id": "custom.width", + "value": 140 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Index Size" + }, + "properties": [ + { + "id": "unit", + "value": "bytes" + }, + { + "id": "custom.width", + "value": 140 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "TOAST Size" + }, + "properties": [ + { + "id": "unit", + "value": "bytes" + }, + { + "id": "custom.width", + "value": 140 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Seq Scans" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.width", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Idx Scans" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "custom.width", + "value": 120 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Inserts" + }, + "properties": [ + { + "id": "unit", + "value": "short" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Updates" + }, + "properties": [ + { + "id": "unit", + "value": "short" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Deletes" + }, + "properties": [ + { + "id": "unit", + "value": "short" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "HOT Updates" + }, + "properties": [ + { + "id": "unit", + "value": "short" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Heap Blks Read" + }, + "properties": [ + { + "id": "unit", + "value": "short" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Heap Blks Hit" + }, + "properties": [ + { + "id": "unit", + "value": "short" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Idx Blks Read" + }, + "properties": [ + { + "id": "unit", + "value": "short" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Idx Blks Hit" + }, + "properties": [ + { + "id": "unit", + "value": "short" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Schema" + }, + "properties": [ + { + "id": "custom.width", + "value": 150 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Table Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 300 + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Single Table Analysis", + "url": "/d/9-single-table-analysis/9-single-table-analysis?orgId=1&var-cluster_name=${cluster_name}&var-node_name=${node_name}&var-db_name=${db_name}&var-schema_name=${__data.fields[\"Schema\"]}&var-table_name=${__data.fields[\"Table Name\"]}&from=${__from:date}&to=${__to:date}" + } + ] + } + ] + } + ] + }, + "gridPos": { + "h": 19, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 45, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Total Size" + } + ] + }, + "pluginVersion": "12.0.2", + "targets": [ + { + "columns": [ + { + "selector": "schema", + "text": "Schema", + "type": "string" + }, + { + "selector": "table_name", + "text": "Table Name", + "type": "string" + }, + { + "selector": "total_size", + "text": "Total Size", + "type": "number" + }, + { + "selector": "table_size", + "text": "Table Size", + "type": "number" + }, + { + "selector": "index_size", + "text": "Index Size", + "type": "number" + }, + { + "selector": "toast_size", + "text": "TOAST Size", + "type": "number" + }, + { + "selector": "seq_scan", + "text": "Seq Scans", + "type": "number" + }, + { + "selector": "idx_scan", + "text": "Idx Scans", + "type": "number" + }, + { + "selector": "n_tup_ins", + "text": "Inserts", + "type": "number" + }, + { + "selector": "n_tup_upd", + "text": "Updates", + "type": "number" + }, + { + "selector": "n_tup_del", + "text": "Deletes", + "type": "number" + }, + { + "selector": "n_tup_hot_upd", + "text": "HOT Updates", + "type": "number" + }, + { + "selector": "heap_blks_read", + "text": "Heap Blks Read", + "type": "number" + }, + { + "selector": "heap_blks_hit", + "text": "Heap Blks Hit", + "type": "number" + }, + { + "selector": "idx_blks_read", + "text": "Idx Blks Read", + "type": "number" + }, + { + "selector": "idx_blks_hit", + "text": "Idx Blks Hit", + "type": "number" + } + ], + "computed_columns": [], + "datasource": { + "type": "yesoreyeram-infinity-datasource", + "uid": "aerffb0z8rjlsc" + }, + "filters": [], + "format": "table", + "global_query_id": "", + "parser": "backend", + "refId": "A", + "root_selector": "", + "source": "url", + "type": "csv", + "url": "http://flask-pgss-api:5000/table_info/csv", + "url_options": { + "data": "", + "method": "GET", + "params": [ + { + "key": "db_name", + "value": "${db_name}" + }, + { + "key": "cluster_name", + "value": "${cluster_name}" + }, + { + "key": "node_name", + "value": "${node_name}" + }, + { + "key": "schemaname", + "value": "${schema_name}" + } + ] + } + } + ], + "title": "", + "transformations": [], + "type": "table" + } + ], + "title": "Detailed table view (aggregated table statistics)", + "type": "row" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1 + }, "id": 27, "panels": [], "title": "Size stats", diff --git a/flask-backend/app.py b/flask-backend/app.py index 9580158..5e193bd 100644 --- a/flask-backend/app.py +++ b/flask-backend/app.py @@ -487,17 +487,43 @@ def get_btree_bloat_csv(): @app.route('/table_info/csv', methods=['GET']) def get_table_info_csv(): """ - Get comprehensive table information including bloat metrics, detailed size information, and I/O statistics as a CSV table. - Combines pg_table_bloat, table_size_detailed, and pg_statio_all_tables metrics for complete table analysis. + Get comprehensive table information including size metrics, tuple statistics, and I/O statistics as a CSV table. + Supports both instant queries (without time parameters) and rate calculations over a time period. + + Query parameters: + - time_start: Start time (ISO format or Unix timestamp) - optional + - time_end: End time (ISO format or Unix timestamp) - optional + - cluster_name: Cluster name filter (optional) + - node_name: Node name filter (optional) + - db_name: Database name filter (optional) + - schemaname: Schema name filter (optional, supports regex with ~) + - tblname: Table name filter (optional) """ try: # Get query parameters + time_start = request.args.get('time_start') + time_end = request.args.get('time_end') cluster_name = request.args.get('cluster_name') node_name = request.args.get('node_name') db_name = request.args.get('db_name') schemaname = request.args.get('schemaname') tblname = request.args.get('tblname') + # Determine if we should calculate rates + calculate_rates = bool(time_start and time_end) + + if calculate_rates: + # Parse time parameters + try: + start_dt = datetime.fromtimestamp(float(time_start), tz=timezone.utc) + except ValueError: + start_dt = datetime.fromisoformat(time_start.replace('Z', '+00:00')) + + try: + end_dt = datetime.fromtimestamp(float(time_end), tz=timezone.utc) + except ValueError: + end_dt = datetime.fromisoformat(time_end.replace('Z', '+00:00')) + # Build label filters filters = [] if cluster_name: @@ -505,7 +531,8 @@ def get_table_info_csv(): if node_name: filters.append(f'node_name="{node_name}"') if schemaname: - filters.append(f'schemaname="{schemaname}"') + # Support regex pattern matching with =~ + filters.append(f'schemaname=~"{schemaname}"') if tblname: filters.append(f'tblname="{tblname}"') if db_name: @@ -513,170 +540,141 @@ def get_table_info_csv(): filter_str = '{' + ','.join(filters) + '}' if filters else '' - # Metrics to fetch with last_over_time to get only the most recent value - # Include bloat metrics, detailed size metrics, and I/O metrics - metric_queries = [ - # Bloat metrics - f'last_over_time(pgwatch_pg_table_bloat_real_size_mib{filter_str}[1d])', - f'last_over_time(pgwatch_pg_table_bloat_extra_size{filter_str}[1d])', - f'last_over_time(pgwatch_pg_table_bloat_extra_pct{filter_str}[1d])', - f'last_over_time(pgwatch_pg_table_bloat_fillfactor{filter_str}[1d])', - f'last_over_time(pgwatch_pg_table_bloat_bloat_size{filter_str}[1d])', - f'last_over_time(pgwatch_pg_table_bloat_bloat_pct{filter_str}[1d])', - f'last_over_time(pgwatch_pg_table_bloat_is_na{filter_str}[1d])', - # Detailed size metrics - f'last_over_time(pgwatch_table_size_detailed_table_main_size_b{filter_str}[1d])', - f'last_over_time(pgwatch_table_size_detailed_table_fsm_size_b{filter_str}[1d])', - f'last_over_time(pgwatch_table_size_detailed_table_vm_size_b{filter_str}[1d])', - f'last_over_time(pgwatch_table_size_detailed_table_indexes_size_b{filter_str}[1d])', - f'last_over_time(pgwatch_table_size_detailed_toast_main_size_b{filter_str}[1d])', - f'last_over_time(pgwatch_table_size_detailed_toast_fsm_size_b{filter_str}[1d])', - f'last_over_time(pgwatch_table_size_detailed_toast_vm_size_b{filter_str}[1d])', - f'last_over_time(pgwatch_table_size_detailed_toast_indexes_size_b{filter_str}[1d])', - f'last_over_time(pgwatch_table_size_detailed_total_relation_size_b{filter_str}[1d])', - f'last_over_time(pgwatch_table_size_detailed_total_toast_size_b{filter_str}[1d])', - # I/O metrics - f'last_over_time(pgwatch_pg_statio_all_tables_heap_blks_read{filter_str}[1d])', - f'last_over_time(pgwatch_pg_statio_all_tables_heap_blks_hit{filter_str}[1d])', - f'last_over_time(pgwatch_pg_statio_all_tables_idx_blks_read{filter_str}[1d])', - f'last_over_time(pgwatch_pg_statio_all_tables_idx_blks_hit{filter_str}[1d])', - f'last_over_time(pgwatch_pg_statio_all_tables_toast_blks_read{filter_str}[1d])', - f'last_over_time(pgwatch_pg_statio_all_tables_toast_blks_hit{filter_str}[1d])', - f'last_over_time(pgwatch_pg_statio_all_tables_tidx_blks_read{filter_str}[1d])', - f'last_over_time(pgwatch_pg_statio_all_tables_tidx_blks_hit{filter_str}[1d])', - ] - prom = get_prometheus_client() - metric_results = {} - - for query in metric_queries: - try: - result = prom.custom_query(query=query) - for entry in result: - metric_labels = entry.get('metric', {}) - key = ( - metric_labels.get('datname', ''), - metric_labels.get('schemaname', ''), - metric_labels.get('tblname', ''), + + # Define base metrics to query (without last_over_time wrapper for rate calculation) + base_metrics = { + # Size metrics + 'total_size': f'pgwatch_pg_class_total_relation_size_bytes{filter_str}', + 'table_size': f'pgwatch_table_size_detailed_table_main_size_b{filter_str}', + 'index_size': f'pgwatch_table_size_detailed_table_indexes_size_b{filter_str}', + 'toast_size': f'pgwatch_table_size_detailed_total_toast_size_b{filter_str}', + # Scan statistics + 'seq_scan': f'pgwatch_pg_stat_all_tables_seq_scan{filter_str}', + 'idx_scan': f'pgwatch_pg_stat_all_tables_idx_scan{filter_str}', + # Tuple statistics + 'n_tup_ins': f'pgwatch_table_stats_n_tup_ins{filter_str}', + 'n_tup_upd': f'pgwatch_table_stats_n_tup_upd{filter_str}', + 'n_tup_del': f'pgwatch_table_stats_n_tup_del{filter_str}', + 'n_tup_hot_upd': f'pgwatch_table_stats_n_tup_hot_upd{filter_str}', + # I/O statistics + 'heap_blks_read': f'pgwatch_pg_statio_all_tables_heap_blks_read{filter_str}', + 'heap_blks_hit': f'pgwatch_pg_statio_all_tables_heap_blks_hit{filter_str}', + 'idx_blks_read': f'pgwatch_pg_statio_all_tables_idx_blks_read{filter_str}', + 'idx_blks_hit': f'pgwatch_pg_statio_all_tables_idx_blks_hit{filter_str}', + } + + if calculate_rates: + # Get metrics at start and end times + start_data = {} + end_data = {} + + for metric_name, metric_query in base_metrics.items(): + try: + # Get data at start time + start_result = prom.get_metric_range_data( + metric_name=metric_query, + start_time=start_dt - timedelta(minutes=1), + end_time=start_dt + timedelta(minutes=1) ) - if key not in metric_results: - metric_results[key] = { - 'database': metric_labels.get('datname', ''), - 'schemaname': metric_labels.get('schemaname', ''), - 'tblname': metric_labels.get('tblname', ''), - } - value = float(entry['value'][1]) + if start_result: + start_data[metric_name] = start_result - # Bloat metrics - if 'real_size_mib' in query: - metric_results[key]['real_size_mib'] = value - elif 'extra_size' in query and 'extra_pct' not in query: - metric_results[key]['extra_size'] = value - elif 'extra_pct' in query: - metric_results[key]['extra_pct'] = value - elif 'fillfactor' in query: - metric_results[key]['fillfactor'] = value - elif 'bloat_size' in query: - metric_results[key]['bloat_size'] = value - elif 'bloat_pct' in query: - metric_results[key]['bloat_pct'] = value - elif 'is_na' in query: - metric_results[key]['is_na'] = int(value) - - # Size metrics (convert bytes to MiB for consistency) - elif 'table_main_size_b' in query: - metric_results[key]['table_main_size_mib'] = value / (1024 * 1024) - elif 'table_fsm_size_b' in query: - metric_results[key]['table_fsm_size_mib'] = value / (1024 * 1024) - elif 'table_vm_size_b' in query: - metric_results[key]['table_vm_size_mib'] = value / (1024 * 1024) - elif 'table_indexes_size_b' in query: - metric_results[key]['table_indexes_size_mib'] = value / (1024 * 1024) - elif 'toast_main_size_b' in query: - metric_results[key]['toast_main_size_mib'] = value / (1024 * 1024) - elif 'toast_fsm_size_b' in query: - metric_results[key]['toast_fsm_size_mib'] = value / (1024 * 1024) - elif 'toast_vm_size_b' in query: - metric_results[key]['toast_vm_size_mib'] = value / (1024 * 1024) - elif 'toast_indexes_size_b' in query: - metric_results[key]['toast_indexes_size_mib'] = value / (1024 * 1024) - elif 'total_relation_size_b' in query: - metric_results[key]['total_relation_size_mib'] = value / (1024 * 1024) - elif 'total_toast_size_b' in query: - metric_results[key]['total_toast_size_mib'] = value / (1024 * 1024) - - # I/O metrics - elif 'heap_blks_read' in query: - metric_results[key]['heap_blks_read'] = int(value) - elif 'heap_blks_hit' in query: - metric_results[key]['heap_blks_hit'] = int(value) - elif 'idx_blks_read' in query: - metric_results[key]['idx_blks_read'] = int(value) - elif 'idx_blks_hit' in query: - metric_results[key]['idx_blks_hit'] = int(value) - elif 'toast_blks_read' in query: - metric_results[key]['toast_blks_read'] = int(value) - elif 'toast_blks_hit' in query: - metric_results[key]['toast_blks_hit'] = int(value) - elif 'tidx_blks_read' in query: - metric_results[key]['tidx_blks_read'] = int(value) - elif 'tidx_blks_hit' in query: - metric_results[key]['tidx_blks_hit'] = int(value) - except Exception as e: - logger.warning(f"Failed to query: {query}, error: {e}") - continue - - # Calculate I/O hit ratios - for key, row in metric_results.items(): - # Heap hit ratio - heap_total = row.get('heap_blks_read', 0) + row.get('heap_blks_hit', 0) - if heap_total > 0: - row['heap_hit_ratio'] = round(row.get('heap_blks_hit', 0) / heap_total * 100, 2) - else: - row['heap_hit_ratio'] = 0.0 - - # Index hit ratio - idx_total = row.get('idx_blks_read', 0) + row.get('idx_blks_hit', 0) - if idx_total > 0: - row['idx_hit_ratio'] = round(row.get('idx_blks_hit', 0) / idx_total * 100, 2) - else: - row['idx_hit_ratio'] = 0.0 - - # TOAST hit ratio - toast_total = row.get('toast_blks_read', 0) + row.get('toast_blks_hit', 0) - if toast_total > 0: - row['toast_hit_ratio'] = round(row.get('toast_blks_hit', 0) / toast_total * 100, 2) - else: - row['toast_hit_ratio'] = 0.0 - - # TOAST index hit ratio - tidx_total = row.get('tidx_blks_read', 0) + row.get('tidx_blks_hit', 0) - if tidx_total > 0: - row['tidx_hit_ratio'] = round(row.get('tidx_blks_hit', 0) / tidx_total * 100, 2) - else: - row['tidx_hit_ratio'] = 0.0 + # Get data at end time + end_result = prom.get_metric_range_data( + metric_name=metric_query, + start_time=end_dt - timedelta(minutes=1), + end_time=end_dt + timedelta(minutes=1) + ) + if end_result: + end_data[metric_name] = end_result + except Exception as e: + logger.warning(f"Failed to query metric {metric_name}: {e}") + continue + + # Process the data to calculate rates + metric_results = process_table_stats_with_rates(start_data, end_data, start_dt, end_dt) + else: + # Get instant values using last_over_time + metric_results = {} + for metric_name, metric_query in base_metrics.items(): + try: + result = prom.custom_query(query=f'last_over_time({metric_query}[1d])') + for entry in result: + metric_labels = entry.get('metric', {}) + + # Use different key depending on label names + schema_label = metric_labels.get('schemaname') or metric_labels.get('schema', '') + table_label = metric_labels.get('relname') or metric_labels.get('table_name') or metric_labels.get('tblname', '') + + key = ( + metric_labels.get('datname', ''), + schema_label, + table_label, + ) + + if key not in metric_results: + metric_results[key] = { + 'database': metric_labels.get('datname', ''), + 'schema': schema_label, + 'table_name': table_label, + } + + value = float(entry['value'][1]) + metric_results[key][metric_name] = value + except Exception as e: + logger.warning(f"Failed to query metric {metric_name}: {e}") + continue # Prepare CSV output output = io.StringIO() - fieldnames = [ - 'database', 'schemaname', 'tblname', - # Bloat metrics - 'real_size_mib', 'extra_size', 'extra_pct', 'fillfactor', - 'bloat_size', 'bloat_pct', 'is_na', - # Size metrics (all in MiB) - 'table_main_size_mib', 'table_fsm_size_mib', 'table_vm_size_mib', - 'table_indexes_size_mib', 'toast_main_size_mib', 'toast_fsm_size_mib', - 'toast_vm_size_mib', 'toast_indexes_size_mib', 'total_relation_size_mib', - 'total_toast_size_mib', - # I/O metrics - 'heap_blks_read', 'heap_blks_hit', 'heap_hit_ratio', - 'idx_blks_read', 'idx_blks_hit', 'idx_hit_ratio', - 'toast_blks_read', 'toast_blks_hit', 'toast_hit_ratio', - 'tidx_blks_read', 'tidx_blks_hit', 'tidx_hit_ratio' - ] + + if calculate_rates: + # Fields with rate calculations + fieldnames = [ + 'schema', 'table_name', + # Size metrics (bytes) + 'total_size', 'table_size', 'index_size', 'toast_size', + # Scan statistics with rates + 'seq_scans', 'seq_scans_per_sec', + 'idx_scans', 'idx_scans_per_sec', + # Tuple statistics with rates + 'inserts', 'inserts_per_sec', + 'updates', 'updates_per_sec', + 'deletes', 'deletes_per_sec', + 'hot_updates', 'hot_updates_per_sec', + # I/O statistics with rates (in bytes using block_size) + 'heap_blks_read', 'heap_blks_read_per_sec', + 'heap_blks_hit', 'heap_blks_hit_per_sec', + 'idx_blks_read', 'idx_blks_read_per_sec', + 'idx_blks_hit', 'idx_blks_hit_per_sec', + 'duration_seconds' + ] + else: + # Fields without rate calculations + fieldnames = [ + 'schema', 'table_name', + 'total_size', 'table_size', 'index_size', 'toast_size', + 'seq_scan', 'idx_scan', + 'n_tup_ins', 'n_tup_upd', 'n_tup_del', 'n_tup_hot_upd', + 'heap_blks_read', 'heap_blks_hit', + 'idx_blks_read', 'idx_blks_hit' + ] + + # Remove 'database' field from rows if present (not in fieldnames) + for row in metric_results.values(): + row.pop('database', None) + writer = csv.DictWriter(output, fieldnames=fieldnames) writer.writeheader() - for row in metric_results.values(): + + # Write rows (handle both dict and list) + if isinstance(metric_results, dict): + rows = metric_results.values() + else: + rows = metric_results + + for row in rows: writer.writerow(row) csv_content = output.getvalue() @@ -685,12 +683,151 @@ def get_table_info_csv(): # Create response response = make_response(csv_content) response.headers['Content-Type'] = 'text/csv' - response.headers['Content-Disposition'] = 'attachment; filename=table_info_latest.csv' + + if calculate_rates: + filename = f'table_stats_{start_dt.strftime("%Y%m%d_%H%M%S")}_{end_dt.strftime("%Y%m%d_%H%M%S")}.csv' + else: + filename = 'table_stats_latest.csv' + + response.headers['Content-Disposition'] = f'attachment; filename={filename}' return response except Exception as e: - logger.error(f"Error processing table info request: {e}") + logger.error(f"Error processing table stats request: {e}") return jsonify({"error": str(e)}), 500 +def process_table_stats_with_rates(start_data, end_data, start_time, end_time): + """ + Process table statistics and calculate rates between start and end times + """ + # Convert data to dictionaries + start_metrics = prometheus_table_to_dict(start_data, start_time) + end_metrics = prometheus_table_to_dict(end_data, end_time) + + if not start_metrics and not end_metrics: + return [] + + # Get all unique table identifiers + all_keys = set() + all_keys.update(start_metrics.keys()) + all_keys.update(end_metrics.keys()) + + result_rows = [] + + for key in all_keys: + start_metric = start_metrics.get(key, {}) + end_metric = end_metrics.get(key, {}) + + # Extract identifier components from key + db_name, schema_name, table_name = key + + # Calculate actual duration + start_timestamp = start_metric.get('timestamp') + end_timestamp = end_metric.get('timestamp') + + if start_timestamp and end_timestamp: + start_dt = datetime.fromisoformat(start_timestamp) + end_dt = datetime.fromisoformat(end_timestamp) + actual_duration = (end_dt - start_dt).total_seconds() + else: + actual_duration = (end_time - start_time).total_seconds() + + # Create result row + row = { + 'schema': schema_name, + 'table_name': table_name, + 'duration_seconds': actual_duration + } + + # Counter metrics to calculate differences and rates + counter_metrics = [ + 'seq_scan', 'idx_scan', 'n_tup_ins', 'n_tup_upd', + 'n_tup_del', 'n_tup_hot_upd', 'heap_blks_read', 'heap_blks_hit', + 'idx_blks_read', 'idx_blks_hit' + ] + + # Mapping for display names + display_names = { + 'seq_scan': 'seq_scans', + 'idx_scan': 'idx_scans', + 'n_tup_ins': 'inserts', + 'n_tup_upd': 'updates', + 'n_tup_del': 'deletes', + 'n_tup_hot_upd': 'hot_updates', + } + + # Calculate differences and rates + for metric in counter_metrics: + start_val = start_metric.get(metric, 0) + end_val = end_metric.get(metric, 0) + diff = end_val - start_val + + # Use display name if available + display_name = display_names.get(metric, metric) + + row[display_name] = diff + + # Calculate rate per second + if actual_duration > 0: + row[f'{display_name}_per_sec'] = diff / actual_duration + else: + row[f'{display_name}_per_sec'] = 0 + + # Size metrics (just use end values, these don't need rates) + for size_metric in ['total_size', 'table_size', 'index_size', 'toast_size']: + row[size_metric] = end_metric.get(size_metric, 0) + + result_rows.append(row) + + # Sort by total size descending + result_rows.sort(key=lambda x: x.get('total_size', 0), reverse=True) + + return result_rows + +def prometheus_table_to_dict(prom_data, timestamp): + """ + Convert Prometheus table metrics to dictionary keyed by table identifiers + """ + if not prom_data: + return {} + + metrics_dict = {} + + for metric_name, metric_results in prom_data.items(): + for metric_data in metric_results: + metric = metric_data.get('metric', {}) + values = metric_data.get('values', []) + + if not values: + continue + + # Get the closest value to our timestamp + closest_value = min(values, key=lambda x: abs(float(x[0]) - timestamp.timestamp())) + + # Handle different label names + schema_label = metric.get('schemaname') or metric.get('schema', '') + table_label = metric.get('relname') or metric.get('table_name') or metric.get('tblname', '') + + # Create unique key for this table + key = ( + metric.get('datname', ''), + schema_label, + table_label, + ) + + # Initialize metric dict if not exists + if key not in metrics_dict: + metrics_dict[key] = { + 'timestamp': datetime.fromtimestamp(float(closest_value[0]), tz=timezone.utc).isoformat(), + } + + # Add metric value + try: + metrics_dict[key][metric_name] = float(closest_value[1]) + except (ValueError, IndexError): + metrics_dict[key][metric_name] = 0 + + return metrics_dict + if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True) \ No newline at end of file -- GitLab From 213fe889b561a0b65cc5b7f463b5fa0fd18900f4 Mon Sep 17 00:00:00 2001 From: "dementii.priadko" <45518657+DEMNERD@users.noreply.github.com> Date: Sat, 8 Nov 2025 01:29:15 +0200 Subject: [PATCH 2/2] Added more high-level metrics instead of using pgss on dashboard 1 --- ...Dashboard_1_Node_performance_overview.json | 2249 +++-------------- 1 file changed, 293 insertions(+), 1956 deletions(-) diff --git a/config/grafana/dashboards/Dashboard_1_Node_performance_overview.json b/config/grafana/dashboards/Dashboard_1_Node_performance_overview.json index 08efa86..bb6de5d 100644 --- a/config/grafana/dashboards/Dashboard_1_Node_performance_overview.json +++ b/config/grafana/dashboards/Dashboard_1_Node_performance_overview.json @@ -18,7 +18,7 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 1, - "id": 1, + "id": 2, "links": [], "panels": [ { @@ -296,26 +296,13 @@ "title": "Active session history", "type": "timeseries" }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 19 - }, - "id": 2, - "panels": [], - "title": "Host stats", - "type": "row" - }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, - "y": 20 + "y": 19 }, "id": 3, "panels": [], @@ -483,7 +470,7 @@ "h": 8, "w": 12, "x": 0, - "y": 21 + "y": 20 }, "id": 4, "options": { @@ -716,7 +703,7 @@ "h": 8, "w": 12, "x": 12, - "y": 21 + "y": 20 }, "id": 39, "options": { @@ -772,109 +759,6 @@ "title": "Non-idle Sessions", "type": "timeseries" }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "ops/s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 29 - }, - "id": 6, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ - { - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "includeNullMetadata": true, - "interval": "20", - "legendFormat": "Calls", - "range": true, - "refId": "A", - "useBackend": false - } - ], - "title": "Calls (pg_stat_statements)", - "type": "timeseries" - }, { "datasource": { "type": "prometheus", @@ -970,8 +854,8 @@ "gridPos": { "h": 8, "w": 12, - "x": 12, - "y": 29 + "x": 0, + "y": 28 }, "id": 7, "options": { @@ -1012,7 +896,7 @@ "refId": "A" } ], - "title": "Transactions", + "title": "TPS", "type": "timeseries" }, { @@ -1035,7 +919,7 @@ "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", - "fillOpacity": 0, + "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, @@ -1071,21 +955,26 @@ "value": 80 } ] - } + }, + "unit": "ops/s" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, - "x": 0, - "y": 37 + "x": 12, + "y": 28 }, - "id": 9, + "id": 6, "options": { "legend": { - "calcs": [], - "displayMode": "list", + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", "placement": "bottom", "showLegend": true }, @@ -1098,10 +987,19 @@ "pluginVersion": "12.0.2", "targets": [ { - "refId": "A" + "disableTextWrap": false, + "editorMode": "code", + "expr": "sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", + "fullMetaSearch": false, + "includeNullMetadata": true, + "interval": "20", + "legendFormat": "Calls", + "range": true, + "refId": "A", + "useBackend": false } ], - "title": "TODO: Postgres logs", + "title": "QPS (pg_stat_statements)", "type": "timeseries" }, { @@ -1109,6 +1007,7 @@ "type": "prometheus", "uid": "P7A0D6631BB10B34F" }, + "description": "To see planning time, enable pg_stat_statements.track_planning", "fieldConfig": { "defaults": { "color": { @@ -1142,14 +1041,13 @@ "spanNulls": false, "stacking": { "group": "A", - "mode": "none" + "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], - "max": 100, "thresholds": { "mode": "absolute", "steps": [ @@ -1162,48 +1060,17 @@ } ] }, - "unit": "percent" + "unit": "s/s" }, - "overrides": [ - { - "matcher": { - "id": "byFrameRefID", - "options": "A" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "green", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byFrameRefID", - "options": "B" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "red", - "mode": "fixed" - } - } - ] - } - ] + "overrides": [] }, "gridPos": { "h": 8, "w": 12, - "x": 12, - "y": 37 + "x": 0, + "y": 36 }, - "id": 8, + "id": 10, "options": { "legend": { "calcs": [ @@ -1223,30 +1090,30 @@ }, "pluginVersion": "12.0.2", "targets": [ + { + "editorMode": "code", + "expr": "sum(irate(pgwatch_pg_stat_statements_exec_time_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/1000", + "interval": "20", + "legendFormat": "Execution time", + "range": true, + "refId": "A" + }, { "datasource": { "type": "prometheus", "uid": "P7A0D6631BB10B34F" }, "editorMode": "code", - "expr": "sum(irate(pgwatch_db_stats_xact_rollback{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/(sum(irate(pgwatch_db_stats_xact_commit{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))+sum(irate(pgwatch_db_stats_xact_rollback{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))) * 100", + "expr": "sum(irate(pgwatch_pg_stat_statements_plan_time_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/1000", "hide": false, "instant": false, "interval": "20", - "legendFormat": "Rollbacks", + "legendFormat": "Planning time", "range": true, "refId": "B" - }, - { - "editorMode": "code", - "expr": "sum(irate(pgwatch_db_stats_xact_commit{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/(sum(irate(pgwatch_db_stats_xact_commit{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))+sum(irate(pgwatch_db_stats_xact_rollback{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))) * 100", - "interval": "20", - "legendFormat": "Commits", - "range": true, - "refId": "A" } ], - "title": "Commit vs Rollback ratio", + "title": "Query total time (pg_stat_statements)", "type": "timeseries" }, { @@ -1254,6 +1121,7 @@ "type": "prometheus", "uid": "P7A0D6631BB10B34F" }, + "description": "To see planning time, enable pg_stat_statements.track_planning", "fieldConfig": { "defaults": { "color": { @@ -1287,7 +1155,7 @@ "spanNulls": false, "stacking": { "group": "A", - "mode": "none" + "mode": "normal" }, "thresholdsStyle": { "mode": "off" @@ -1306,17 +1174,17 @@ } ] }, - "unit": "s/s" + "unit": "s" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, - "x": 0, - "y": 45 + "x": 12, + "y": 36 }, - "id": 10, + "id": 48, "options": { "legend": { "calcs": [ @@ -1338,14 +1206,28 @@ "targets": [ { "editorMode": "code", - "expr": "(sum(irate(pgwatch_pg_stat_statements_exec_time_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval])) + sum(irate(pgwatch_pg_stat_statements_plan_time_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval])))/1000", + "expr": "sum(irate(pgwatch_pg_stat_statements_exec_time_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/1000/ sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", "interval": "20", - "legendFormat": "Statements total time", + "legendFormat": "Execution time per call", "range": true, "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "P7A0D6631BB10B34F" + }, + "editorMode": "code", + "expr": "sum(irate(pgwatch_pg_stat_statements_plan_time_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/1000/ sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", + "hide": false, + "instant": false, + "interval": "20", + "legendFormat": "Planning time per call", + "range": true, + "refId": "B" } ], - "title": "Statements total time (pg_stat_statements)", + "title": "Query time per call (latency) (pg_stat_statements)", "type": "timeseries" }, { @@ -1368,7 +1250,7 @@ "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", - "fillOpacity": 100, + "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, @@ -1405,17 +1287,17 @@ } ] }, - "unit": "s" + "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, - "x": 12, - "y": 45 + "x": 0, + "y": 44 }, - "id": 11, + "id": 12, "options": { "legend": { "calcs": [ @@ -1438,17 +1320,34 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "(sum(irate(pgwatch_pg_stat_statements_exec_time_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval])) + sum(irate(pgwatch_pg_stat_statements_plan_time_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))) / sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", + "expr": "irate(pgwatch_db_stats_tup_returned{cluster=\"$cluster_name\", node_name=\"$node_name\", datname=\"$db_name\"}[$__rate_interval])", "fullMetaSearch": false, "includeNullMetadata": true, "interval": "20", - "legendFormat": "Statements time per call", + "legendFormat": "Tuples returned", "range": true, "refId": "A", "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "P7A0D6631BB10B34F" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "irate(pgwatch_db_stats_tup_fetched{cluster=\"$cluster_name\", node_name=\"$node_name\", datname=\"$db_name\"}[$__rate_interval])", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "interval": "20", + "legendFormat": "Tuples fetched", + "range": true, + "refId": "B", + "useBackend": false } ], - "title": "Statements time per call (pg_stat_statements) aka latency", + "title": "Tuples fetched and tuples returned per second", "type": "timeseries" }, { @@ -1489,7 +1388,7 @@ "spanNulls": false, "stacking": { "group": "A", - "mode": "none" + "mode": "normal" }, "thresholdsStyle": { "mode": "off" @@ -1507,115 +1406,34 @@ "value": 80 } ] - } + }, + "unit": "ops" }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 53 - }, - "id": 12, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ - { - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_rows[$__rate_interval]))", - "interval": "20", - "legendFormat": "No. of rows ", - "range": true, - "refId": "A" - } - ], - "title": "Total rows (pg_stat_statements)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Tuples deleted" }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, + "properties": [ { - "color": "red", - "value": 80 + "id": "color", + "value": { + "fixedColor": "dark-red", + "mode": "fixed" + } } ] } - }, - "overrides": [] + ] }, "gridPos": { "h": 8, "w": 12, "x": 12, - "y": 53 + "y": 44 }, - "id": 13, + "id": 47, "options": { "legend": { "calcs": [ @@ -1629,134 +1447,60 @@ }, "tooltip": { "hideZeros": false, - "mode": "single", + "mode": "multi", "sort": "none" } }, "pluginVersion": "12.0.2", "targets": [ { - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_rows{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", + "disableTextWrap": false, + "editorMode": "builder", + "expr": "irate(pgwatch_db_stats_tup_inserted{cluster=\"$cluster_name\", node_name=\"$node_name\", datname=\"$db_name\"}[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": true, "interval": "20", - "legendFormat": "Rows per call", + "legendFormat": "Tuples inserted", "range": true, - "refId": "A" - } - ], - "title": "Rows per call (pg_stat_statements)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s/s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 61 - }, - "id": 14, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true + "refId": "A", + "useBackend": false }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ { + "datasource": { + "type": "prometheus", + "uid": "P7A0D6631BB10B34F" + }, + "disableTextWrap": false, "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_block_read_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", + "expr": "irate(pgwatch_db_stats_tup_updated{cluster=\"$cluster_name\", node_name=\"$node_name\", datname=\"$db_name\"}[$__rate_interval])", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, "interval": "20", - "legendFormat": "blk_read_time", + "legendFormat": "Tuples updated (HOT + non-HOT)", "range": true, - "refId": "A" + "refId": "B", + "useBackend": false }, { "datasource": { "type": "prometheus", "uid": "P7A0D6631BB10B34F" }, + "disableTextWrap": false, "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_block_write_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", + "expr": "irate(pgwatch_db_stats_tup_deleted{cluster=\"$cluster_name\", node_name=\"$node_name\", datname=\"$db_name\"}[$__rate_interval])", + "fullMetaSearch": false, "hide": false, + "includeNullMetadata": true, "interval": "20", - "legendFormat": "blk_write_time", + "legendFormat": "Tuples deleted", "range": true, - "refId": "B" + "refId": "C", + "useBackend": false } ], - "title": "blk_read_time vs blk_write_time (s/s) (pg_stat_statements)", + "title": "Tuples operations per second", "type": "timeseries" }, { @@ -1797,7 +1541,7 @@ "spanNulls": false, "stacking": { "group": "A", - "mode": "none" + "mode": "normal" }, "thresholdsStyle": { "mode": "off" @@ -1816,17 +1560,17 @@ } ] }, - "unit": "ms" + "unit": "binBps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, - "x": 12, - "y": 61 + "x": 0, + "y": 52 }, - "id": 15, + "id": 14, "options": { "legend": { "calcs": [ @@ -1840,1367 +1584,126 @@ }, "tooltip": { "hideZeros": false, - "mode": "single", + "mode": "multi", "sort": "none" } }, "pluginVersion": "12.0.2", "targets": [ { - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_block_read_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", + "disableTextWrap": false, + "editorMode": "builder", + "expr": "irate(pgwatch_db_stats_blks_read{cluster=\"$cluster_name\", node_name=\"$node_name\", datname=\"$db_name\"}[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": true, "interval": "20", - "legendFormat": "blk_read_time", + "legendFormat": "blks_read", "range": true, - "refId": "A" + "refId": "A", + "useBackend": false }, { "datasource": { "type": "prometheus", "uid": "P7A0D6631BB10B34F" }, - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_block_write_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", + "disableTextWrap": false, + "editorMode": "builder", + "expr": "irate(pgwatch_db_stats_blks_hit{cluster=\"$cluster_name\", node_name=\"$node_name\", datname=\"$db_name\"}[$__rate_interval])", + "fullMetaSearch": false, "hide": false, + "includeNullMetadata": true, "interval": "20", - "legendFormat": "blk_write_time", + "legendFormat": "blks_hit", "range": true, - "refId": "B" + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "P7A0D6631BB10B34F" + }, + "editorMode": "code", + "expr": "last_over_time(pgwatch_settings_numeric_value{setting_name=\"block_size\"}[1h])", + "hide": false, + "instant": false, + "legendFormat": "block_size", + "range": true, + "refId": "C" } ], - "title": "blk_read_time vs blk_write_time per call (pg_stat_statements)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "binBps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 69 - }, - "id": 16, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ - { - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_shared_bytes_hit_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "includeNullMetadata": true, - "interval": "20", - "legendFormat": "shared bytes", - "range": true, - "refId": "A", - "useBackend": false - } - ], - "title": "shared_blks_hit (bytes) (pg_stat_statements)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 69 - }, - "id": 17, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ - { - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_shared_bytes_hit_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "includeNullMetadata": true, - "interval": "20", - "legendFormat": "shared bytes per call", - "range": true, - "refId": "A", - "useBackend": false - } - ], - "title": "shared_blks_hit (bytes) per call (pg_stat_statements)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "binBps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 77 - }, - "id": 18, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ - { - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_shared_bytes_read_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "includeNullMetadata": true, - "interval": "20", - "legendFormat": "shared bytes", - "range": true, - "refId": "A", - "useBackend": false - } - ], - "title": "shared_blks_read (bytes) (pg_stat_statements)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 77 - }, - "id": 19, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ - { - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_shared_bytes_read_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "includeNullMetadata": true, - "interval": "20", - "legendFormat": "shared bytes per call", - "range": true, - "refId": "A", - "useBackend": false - } - ], - "title": "shared_blks_read (bytes) per call (pg_stat_statements)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "binBps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 85 - }, - "id": 20, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ - { - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_shared_bytes_written_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "includeNullMetadata": true, - "interval": "20", - "legendFormat": "shared bytes", - "range": true, - "refId": "A", - "useBackend": false - } - ], - "title": "shared_blks_written (bytes) (pg_stat_statements)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 85 - }, - "id": 21, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ - { - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_shared_bytes_written_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "includeNullMetadata": true, - "interval": "20", - "legendFormat": "shared bytes per call", - "range": true, - "refId": "A", - "useBackend": false - } - ], - "title": "shared_blks_written (bytes) per call (pg_stat_statements)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "binBps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 93 - }, - "id": 22, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ - { - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_shared_bytes_dirtied_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "includeNullMetadata": true, - "interval": "20", - "legendFormat": "shared bytes", - "range": true, - "refId": "A", - "useBackend": false - } - ], - "title": "shared_blks_dirtied (bytes) (pg_stat_statements)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 93 - }, - "id": 23, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ - { - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_shared_bytes_written_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "includeNullMetadata": true, - "interval": "20", - "legendFormat": "shared bytes per call", - "range": true, - "refId": "A", - "useBackend": false - } - ], - "title": "shared_blks_dirtied (bytes) per call (pg_stat_statements)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "max": 100, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 24, - "x": 0, - "y": 101 - }, - "id": 24, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ - { - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_shared_bytes_hit_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/(sum(irate(pgwatch_pg_stat_statements_shared_bytes_hit_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval])) + sum(irate(pgwatch_pg_stat_statements_shared_bytes_read_total{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))) * 100", - "interval": "20", - "legendFormat": "shared_blks_read_ratio", - "range": true, - "refId": "A" - } - ], - "title": "shared_blks_read_ratio (pg_stat_statements)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "binBps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 109 - }, - "id": 25, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ - { - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum(irate(pgwatch_wal_xlog_location_b{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "includeNullMetadata": true, - "interval": "20", - "legendFormat": "shared bytes", - "range": true, - "refId": "A", - "useBackend": false - } - ], - "title": "WAL bytes (pg_current_wal_lsn)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" + "title": "blk_reads and blk_hits per second (bytes)", + "transformations": [ + { + "id": "calculateField", + "options": { + "alias": "blks_read (bytes)", + "binary": { + "left": { + "matcher": { + "id": "byName", + "options": "blks_read" + } }, - { - "color": "red", - "value": 80 + "operator": "*", + "right": { + "matcher": { + "id": "byName", + "options": "block_size" + } } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 109 - }, - "id": 26, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ - { - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum(irate(pgwatch_wal_xlog_location_b{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "includeNullMetadata": true, - "interval": "20", - "legendFormat": "shared bytes", - "range": true, - "refId": "A", - "useBackend": false - } - ], - "title": "WAL bytes per call (pg_current_wal_lsn)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" + "mode": "binary", + "reduce": { + "reducer": "sum" }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "binBps" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 117 - }, - "id": 27, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false + "replaceFields": false + } }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ { - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_wal_fpi{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "includeNullMetadata": true, - "interval": "20", - "legendFormat": "shared bytes", - "range": true, - "refId": "A", - "useBackend": false - } - ], - "title": "WAL fpi (pg_stat_statements)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "axisSoftMin": 0, - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 100, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 1, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" + "id": "calculateField", + "options": { + "alias": "blks_hit (bytes)", + "binary": { + "left": { + "matcher": { + "id": "byName", + "options": "blks_hit" + } }, - { - "color": "red", - "value": 80 + "operator": "*", + "right": { + "matcher": { + "id": "byName", + "options": "block_size" + } } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 117 - }, - "id": 28, - "options": { - "legend": { - "calcs": [ - "min", - "max", - "mean" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": false + }, + "mode": "binary", + "reduce": { + "reducer": "sum" + }, + "replaceFields": false + } }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.0.2", - "targets": [ { - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_wal_fpi{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "includeNullMetadata": true, - "interval": "20", - "legendFormat": "shared bytes", - "range": true, - "refId": "A", - "useBackend": false + "id": "organize", + "options": { + "excludeByName": { + "blks_hit": true, + "blks_read": true, + "block_size": true + }, + "includeByName": {}, + "indexByName": {}, + "renameByName": { + "blks_hit (bytes)": "blks_hit", + "blks_read (bytes)": "blks_read" + } + } } ], - "title": "WAL fpi per call (pg_current_wal_lsn)", "type": "timeseries" }, { @@ -3208,6 +1711,7 @@ "type": "prometheus", "uid": "P7A0D6631BB10B34F" }, + "description": "To see planning time, enable track_io_timing", "fieldConfig": { "defaults": { "color": { @@ -3241,7 +1745,7 @@ "spanNulls": false, "stacking": { "group": "A", - "mode": "none" + "mode": "normal" }, "thresholdsStyle": { "mode": "off" @@ -3260,17 +1764,17 @@ } ] }, - "unit": "binBps" + "unit": "s/s" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, - "x": 0, - "y": 125 + "x": 12, + "y": 52 }, - "id": 29, + "id": 49, "options": { "legend": { "calcs": [ @@ -3293,11 +1797,11 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_temp_bytes_read{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", + "expr": "irate(pgwatch_db_stats_blk_read_time{cluster=\"$cluster_name\", node_name=\"$node_name\", datname=\"$db_name\"}[$__rate_interval])", "fullMetaSearch": false, "includeNullMetadata": true, "interval": "20", - "legendFormat": "Temp bytes read", + "legendFormat": "blk_read_time", "range": true, "refId": "A", "useBackend": false @@ -3308,15 +1812,15 @@ "uid": "P7A0D6631BB10B34F" }, "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_temp_bytes_written{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", + "expr": "irate(pgwatch_db_stats_blk_write_time{cluster=\"$cluster_name\", node_name=\"$node_name\", datname=\"$db_name\"}[$__rate_interval])", "hide": false, "interval": "20", - "legendFormat": "Temp bytes written", + "legendFormat": "blk_write_time", "range": true, "refId": "B" } ], - "title": "temp_bytes_read vs temp_bytes_written (pg_stat_statements)", + "title": "blk_read_time and blk_write_time (s/s)", "type": "timeseries" }, { @@ -3376,17 +1880,17 @@ } ] }, - "unit": "bytes" + "unit": "binBps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, - "x": 12, - "y": 125 + "x": 0, + "y": 60 }, - "id": 31, + "id": 25, "options": { "legend": { "calcs": [ @@ -3396,7 +1900,7 @@ ], "displayMode": "table", "placement": "bottom", - "showLegend": true + "showLegend": false }, "tooltip": { "hideZeros": false, @@ -3409,30 +1913,17 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_temp_bytes_read{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", + "expr": "sum(irate(pgwatch_wal_xlog_location_b{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", "fullMetaSearch": false, "includeNullMetadata": true, "interval": "20", - "legendFormat": "Temp bytes read", + "legendFormat": "shared bytes", "range": true, "refId": "A", "useBackend": false - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "editorMode": "code", - "expr": "sum(irate(pgwatch_pg_stat_statements_temp_bytes_written{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))/sum(irate(pgwatch_pg_stat_statements_calls{cluster='$cluster_name', node_name='$node_name', datname=\"$db_name\"}[$__rate_interval]))", - "hide": false, - "interval": "20", - "legendFormat": "Temp bytes written", - "range": true, - "refId": "B" } ], - "title": "temp_bytes_read vs temp_bytes_written per call (pg_stat_statements)", + "title": "WAL bytes per second (pg_current_wal_lsn)", "type": "timeseries" }, { @@ -3473,7 +1964,7 @@ "spanNulls": false, "stacking": { "group": "A", - "mode": "normal" + "mode": "none" }, "thresholdsStyle": { "mode": "off" @@ -3492,78 +1983,17 @@ } ] }, - "unit": "ops" + "unit": "binBps" }, - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Inserts" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "dark-green", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Deletes" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "dark-red", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "HOT updates" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "orange", - "mode": "fixed" - } - } - ] - }, - { - "matcher": { - "id": "byName", - "options": "Non-HOT updates" - }, - "properties": [ - { - "id": "color", - "value": { - "fixedColor": "yellow", - "mode": "fixed" - } - } - ] - } - ] + "overrides": [] }, "gridPos": { - "h": 13, - "w": 24, - "x": 0, - "y": 133 + "h": 8, + "w": 12, + "x": 12, + "y": 60 }, - "id": 45, + "id": 29, "options": { "legend": { "calcs": [ @@ -3573,127 +2003,30 @@ ], "displayMode": "table", "placement": "bottom", - "showLegend": true, - "sortBy": "Max", - "sortDesc": true + "showLegend": true }, "tooltip": { "hideZeros": false, - "mode": "multi", + "mode": "single", "sort": "none" } }, "pluginVersion": "12.0.2", "targets": [ { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, "disableTextWrap": false, "editorMode": "code", - "expr": "sum by (node_name, dbname, cluster) (irate(pgwatch_table_stats_n_tup_ins{datname=\"$db_name\", cluster=\"$cluster_name\", node_name=\"$node_name\"}[$__rate_interval]))", + "expr": "irate(pgwatch_db_stats_temp_bytes{cluster=\"$cluster_name\", node_name=\"$node_name\", datname=\"$db_name\"}[$__rate_interval])", "fullMetaSearch": false, "includeNullMetadata": true, - "interval": "60", - "legendFormat": "Inserts", + "interval": "20", + "legendFormat": "Temp bytes", "range": true, "refId": "A", "useBackend": false - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum by (node_name, dbname, cluster) (irate(pgwatch_table_stats_n_tup_upd{datname=\"$db_name\", cluster=\"$cluster_name\", node_name=\"$node_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "hide": false, - "includeNullMetadata": true, - "interval": "60", - "legendFormat": "Updates", - "range": true, - "refId": "B", - "useBackend": false - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum by (node_name, dbname, cluster) (irate(pgwatch_table_stats_n_tup_hot_upd{datname=\"$db_name\", cluster=\"$cluster_name\", node_name=\"$node_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "hide": false, - "includeNullMetadata": true, - "interval": "60", - "legendFormat": "HOT updates", - "range": true, - "refId": "C", - "useBackend": false - }, - { - "datasource": { - "type": "prometheus", - "uid": "P7A0D6631BB10B34F" - }, - "disableTextWrap": false, - "editorMode": "code", - "expr": "sum by (node_name, dbname, cluster) (irate(pgwatch_table_stats_n_tup_del{datname=\"$db_name\", cluster=\"$cluster_name\", node_name=\"$node_name\"}[$__rate_interval]))", - "fullMetaSearch": false, - "hide": false, - "includeNullMetadata": true, - "interval": "60", - "legendFormat": "Deletes", - "range": true, - "refId": "D", - "useBackend": false - } - ], - "title": "Tuple operations", - "transformations": [ - { - "id": "calculateField", - "options": { - "alias": "Non-HOT updates", - "binary": { - "left": { - "matcher": { - "id": "byName", - "options": "Updates" - } - }, - "operator": "-", - "right": { - "matcher": { - "id": "byName", - "options": "HOT updates" - } - } - }, - "mode": "binary", - "reduce": { - "reducer": "sum" - } - } - }, - { - "id": "organize", - "options": { - "excludeByName": { - "Updates": true - }, - "includeByName": {}, - "indexByName": {}, - "renameByName": { - "Hot Updates": "HOT Updates" - } - } } ], + "title": "temp_bytes written per second", "type": "timeseries" }, { @@ -3764,7 +2097,7 @@ "h": 8, "w": 12, "x": 0, - "y": 146 + "y": 68 }, "id": 32, "options": { @@ -3901,7 +2234,7 @@ "h": 8, "w": 12, "x": 12, - "y": 146 + "y": 68 }, "id": 33, "options": { @@ -3999,7 +2332,7 @@ "h": 8, "w": 12, "x": 0, - "y": 154 + "y": 76 }, "id": 34, "options": { @@ -4052,7 +2385,7 @@ "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", - "fillOpacity": 0, + "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, @@ -4096,7 +2429,7 @@ "h": 8, "w": 12, "x": 12, - "y": 154 + "y": 76 }, "id": 35, "options": { @@ -4149,7 +2482,7 @@ "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", - "fillOpacity": 0, + "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, @@ -4164,10 +2497,10 @@ "type": "linear" }, "showPoints": "auto", - "spanNulls": false, + "spanNulls": true, "stacking": { "group": "A", - "mode": "none" + "mode": "normal" }, "thresholdsStyle": { "mode": "off" @@ -4194,7 +2527,7 @@ "h": 10, "w": 24, "x": 0, - "y": 162 + "y": 84 }, "id": 41, "options": { @@ -4218,8 +2551,8 @@ "targets": [ { "disableTextWrap": false, - "editorMode": "code", - "expr": "rate(pgwatch_bgwriter_buffers_checkpoint{datname=\"$db_name\"}[$__rate_interval]) * on(datname) pgwatch_settings_numeric_value{datname=\"$db_name\", setting_name=\"block_size\"}", + "editorMode": "builder", + "expr": "irate(pgwatch_checkpointer_buffers_written{datname=\"$db_name\"}[$__rate_interval]) * on(datname) pgwatch_settings_numeric_value{datname=\"$db_name\", setting_name=\"block_size\"}", "fullMetaSearch": false, "includeNullMetadata": true, "interval": "20", @@ -4233,7 +2566,7 @@ "type": "prometheus", "uid": "P7A0D6631BB10B34F" }, - "editorMode": "code", + "editorMode": "builder", "expr": "irate(pgwatch_bgwriter_buffers_clean[$__rate_interval]) * on(datname) pgwatch_settings_numeric_value{datname=\"$db_name\", setting_name=\"block_size\"}", "hide": false, "instant": false, @@ -4247,14 +2580,18 @@ "type": "prometheus", "uid": "P7A0D6631BB10B34F" }, - "editorMode": "code", - "expr": "irate(pgwatch_bgwriter_buffers_backend[$__rate_interval]) * on(datname) pgwatch_settings_numeric_value{datname=\"$db_name\", setting_name=\"block_size\"}", + "disableTextWrap": false, + "editorMode": "builder", + "expr": "irate(pg_stat_bgwriter_buffers_backend_total[$__rate_interval]) * on(datname) pgwatch_settings_numeric_value{datname=\"$db_name\", setting_name=\"block_size\"}", + "fullMetaSearch": false, "hide": false, + "includeNullMetadata": true, "instant": false, "interval": "20", "legendFormat": "Cleaned by backends", "range": true, - "refId": "C" + "refId": "C", + "useBackend": false } ], "title": "bgwriter and checkpointer", @@ -4356,7 +2693,7 @@ "h": 11, "w": 24, "x": 0, - "y": 172 + "y": 94 }, "id": 42, "options": { @@ -4477,7 +2814,7 @@ "h": 14, "w": 24, "x": 0, - "y": 183 + "y": 105 }, "id": 44, "options": { @@ -4679,7 +3016,7 @@ "h": 12, "w": 24, "x": 0, - "y": 197 + "y": 119 }, "id": 46, "options": { @@ -4736,7 +3073,7 @@ "h": 3, "w": 24, "x": 0, - "y": 209 + "y": 131 }, "id": 40, "options": { @@ -4822,5 +3159,5 @@ "timezone": "utc", "title": "01. Single node performance overview (high-level)", "uid": "f90500a0-a12e-4081-a2f0-07ed96f27915", - "version": 4 + "version": 31 } \ No newline at end of file -- GitLab