diff --git a/grafana/Ditto-Dashboard.json b/grafana/Ditto-Dashboard.json new file mode 100644 index 00000000..222b727c --- /dev/null +++ b/grafana/Ditto-Dashboard.json @@ -0,0 +1,2117 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + }, + { + "name": "DS_DITTO-PG", + "label": "ditto-pg", + "description": "", + "type": "datasource", + "pluginId": "grafana-postgresql-datasource", + "pluginName": "PostgreSQL" + } + ], + "__elements": {}, + "__requires": [ + { + "type": "panel", + "id": "gauge", + "name": "Gauge", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "11.2.0" + }, + { + "type": "datasource", + "id": "grafana-postgresql-datasource", + "name": "PostgreSQL", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "piechart", + "name": "Pie chart", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Ditto application performance", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "panels": [ + { + "datasource": { + "default": false, + "type": "prometheus", + "uid": "${prometheus}" + }, + "description": "Responses sent back to users from the server. Organized by status code.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byFrameRefID", + "options": "Server Errors" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "semi-dark-red", + "mode": "shades" + } + } + ] + }, + { + "matcher": { + "id": "byFrameRefID", + "options": "Client Errors" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-blue", + "mode": "shades" + } + } + ] + }, + { + "matcher": { + "id": "byFrameRefID", + "options": "Redirects" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "semi-dark-yellow", + "mode": "shades" + } + } + ] + }, + { + "matcher": { + "id": "byFrameRefID", + "options": "Success" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "semi-dark-green", + "mode": "shades" + } + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": false, + "width": 225 + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "increase(ditto_http_responses_total{status=~\"5..\",path!=\"/relay\"}[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "{{method}} {{path}} ({{status}})", + "range": true, + "refId": "Server Errors" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prometheus}" + }, + "editorMode": "code", + "expr": "increase(ditto_http_responses_total{status=~\"4..\",path!=\"/relay\"}[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "{{method}} {{path}} ({{status}})", + "range": true, + "refId": "Client Errors" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "increase(ditto_http_responses_total{status=~\"3..\",path!=\"/relay\"}[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "{{method}} {{path}} ({{status}})", + "range": true, + "refId": "Redirects" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prometheus}" + }, + "editorMode": "code", + "expr": "increase(ditto_http_responses_total{status=~\"2..\",path!=\"/relay\"}[$__rate_interval])", + "instant": false, + "interval": "", + "legendFormat": "{{method}} {{path}} ({{status}})", + "range": true, + "refId": "Success" + } + ], + "title": "HTTP Responses", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of idle database connections available to the server. Higher is better. At 0, the site stops working.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "red", + "value": 0 + }, + { + "color": "#EAB839", + "value": 25 + }, + { + "color": "green", + "value": 50 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 10 + }, + "id": 8, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "11.2.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prometheus}" + }, + "editorMode": "code", + "expr": "ditto_db_available_connections", + "instant": false, + "legendFormat": "Connections", + "range": true, + "refId": "A" + } + ], + "title": "Database Available Connections", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "How hard the database is working on a per-query basis. It's query time divided by number of queries. Lower is better.", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "red", + "mode": "continuous-GrYlRd", + "seriesBy": "last" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "scheme", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "fieldMinMax": false, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 6, + "y": 10 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prometheus}" + }, + "editorMode": "code", + "expr": "rate(ditto_db_query_duration_ms_sum[$__rate_interval]) / rate(db_query_total[$__rate_interval])", + "instant": false, + "interval": "", + "legendFormat": "Effort", + "range": true, + "refId": "A" + } + ], + "title": "Database Effort", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of individual database calls.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 18, + "y": 10 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prometheus}" + }, + "editorMode": "code", + "expr": "increase(ditto_db_queries_total[$__rate_interval])", + "instant": false, + "legendFormat": "Queries", + "range": true, + "refId": "A" + } + ], + "title": "Database Queries", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Number of Nostr events that are accepted or rejected by the custom policy script.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Accept" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "green", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Reject" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 18 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${prometheus}" + }, + "editorMode": "code", + "expr": "increase(ditto_policy_events_total{ok=\"true\"}[$__rate_interval])", + "instant": false, + "legendFormat": "Accept", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "increase(ditto_policy_events_total{ok=\"false\"}[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "Reject", + "range": true, + "refId": "B" + } + ], + "title": "Policy Events", + "type": "timeseries" + }, + { + "datasource": { + "default": false, + "type": "prometheus", + "uid": "${prometheus}" + }, + "description": "Total number of Nostr clients currently connected to the Nostr relay.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 6, + "y": 18 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "ditto_relay_connections", + "instant": false, + "legendFormat": "Connections", + "range": true, + "refId": "A" + } + ], + "title": "Relay Connections", + "type": "timeseries" + }, + { + "datasource": { + "default": false, + "type": "prometheus", + "uid": "${prometheus}" + }, + "description": "Sum duration of all queries in milliseconds.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 18, + "y": 18 + }, + "id": 7, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "increase(ditto_db_query_duration_ms_sum[$__rate_interval])", + "instant": false, + "legendFormat": "Time", + "range": true, + "refId": "A" + } + ], + "title": "Database Query Time", + "type": "timeseries" + }, + { + "datasource": { + "default": false, + "type": "grafana-postgresql-datasource", + "uid": "${postgres}" + }, + "description": "SQL queries ranked by total time.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "super-light-green", + "value": 100 + }, + { + "color": "light-orange", + "value": 500 + }, + { + "color": "red", + "value": 1000 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "query" + }, + "properties": [ + { + "id": "displayName", + "value": "Query" + }, + { + "id": "custom.inspect", + "value": true + }, + { + "id": "custom.minWidth", + "value": 500 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "total_time" + }, + "properties": [ + { + "id": "displayName", + "value": "Total Time" + }, + { + "id": "unit", + "value": "ms" + }, + { + "id": "decimals", + "value": 1 + }, + { + "id": "custom.hidden", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "average_time" + }, + "properties": [ + { + "id": "displayName", + "value": "Average Time" + }, + { + "id": "unit", + "value": "ms" + }, + { + "id": "custom.cellOptions", + "value": { + "type": "color-text" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "calls" + }, + "properties": [ + { + "id": "displayName", + "value": "Calls" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 0 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "total_percent" + }, + "properties": [ + { + "id": "displayName", + "value": "Total Percent" + }, + { + "id": "unit", + "value": "percentunit" + }, + { + "id": "decimals", + "value": 0 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "max_time" + }, + "properties": [ + { + "id": "displayName", + "value": "Max Time" + }, + { + "id": "unit", + "value": "ms" + }, + { + "id": "custom.cellOptions", + "value": { + "type": "color-text" + } + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 15, + "x": 0, + "y": 26 + }, + "id": 13, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "enablePagination": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": true + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Total Percent" + } + ] + }, + "pluginVersion": "11.2.0", + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "${DS_DITTO-PG}" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "WITH query_stats AS (\n SELECT\n LEFT(query, 10000) AS query,\n (total_plan_time + total_exec_time) AS total_time,\n (mean_plan_time + mean_exec_time) AS average_time,\n (max_plan_time + max_exec_time) AS max_time,\n calls\n FROM\n pg_stat_statements\n WHERE\n calls > 0\n)\nSELECT\n query,\n total_time,\n average_time,\n max_time,\n calls,\n total_time / (SELECT SUM(total_time) FROM query_stats) AS total_percent\nFROM\n query_stats\nORDER BY\n total_time DESC\nLIMIT 100;\n", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + }, + "table": "pg_stat_statements" + } + ], + "title": "Query Performance", + "type": "table" + }, + { + "datasource": { + "name": "${postgres}", + "type": "grafana-postgresql-datasource", + "uid": "${postgres}" + }, + "description": "Index hit rate. Higher is better.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "table" + }, + "properties": [ + { + "id": "displayName", + "value": "Table" + }, + { + "id": "custom.filterable", + "value": true + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "index" + }, + "properties": [ + { + "id": "displayName", + "value": "Index" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "percentage_used" + }, + "properties": [ + { + "id": "displayName", + "value": "Percentage Used" + }, + { + "id": "unit", + "value": "percent" + }, + { + "id": "custom.cellOptions", + "value": { + "mode": "lcd", + "type": "gauge", + "valueDisplayMode": "color" + } + }, + { + "id": "color", + "value": { + "mode": "continuous-RdYlGr" + } + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 9, + "x": 15, + "y": 26 + }, + "id": 14, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "11.2.0", + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "${DS_DITTO-PG}" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT \n relname AS table,\n indexrelname AS index,\n (idx_blks_hit * 100) / (CASE WHEN idx_blks_hit + idx_blks_read = 0 THEN 1 ELSE idx_blks_hit + idx_blks_read END) as percentage_used\nFROM \n pg_statio_user_indexes\nWHERE \n schemaname = 'public'\nORDER BY\n percentage_used DESC;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Index Uses", + "type": "table" + }, + { + "datasource": { + "name": "${postgres}", + "type": "grafana-postgresql-datasource", + "uid": "${postgres}" + }, + "description": "Size of database tables.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [], + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 7, + "x": 0, + "y": 37 + }, + "id": 16, + "options": { + "displayLabels": [ + "name" + ], + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": false, + "values": [ + "value" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": true + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "${DS_DITTO-PG}" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT\n c.relname AS table,\n pg_table_size(c.oid) AS size\nFROM\n pg_class c\n LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace)\nWHERE\n n.nspname NOT IN ('pg_catalog', 'information_schema')\n AND n.nspname !~ '^pg_toast'\n AND c.relkind IN ('r', 'm')\nORDER BY\n pg_table_size(c.oid) DESC;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Table Size", + "transformations": [ + { + "id": "rowsToFields", + "options": {} + } + ], + "type": "piechart" + }, + { + "datasource": { + "name": "${postgres}", + "type": "grafana-postgresql-datasource", + "uid": "${postgres}" + }, + "description": "Size of all indexes in the database.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [], + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 7, + "y": 37 + }, + "id": 17, + "options": { + "displayLabels": [ + "name" + ], + "legend": { + "calcs": [], + "displayMode": "hidden", + "placement": "right", + "showLegend": false, + "values": [] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": true + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.0.0", + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "${DS_DITTO-PG}" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT\n c.relname AS name,\n sum(c.relpages :: bigint * 8192) :: bigint AS size\nFROM\n pg_class c\n LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace)\nWHERE\n n.nspname NOT IN ('pg_catalog', 'information_schema')\n AND n.nspname !~ '^pg_toast'\n AND c.relkind = 'i'\nGROUP BY\n (n.nspname, c.relname)\nORDER BY\n sum(c.relpages) DESC;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Index Size", + "transformations": [ + { + "id": "rowsToFields", + "options": {} + } + ], + "type": "piechart" + }, + { + "datasource": { + "name": "${postgres}", + "type": "grafana-postgresql-datasource", + "uid": "${postgres}" + }, + "description": "Indexes that are not used or very rarely used.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "table" + }, + "properties": [ + { + "id": "displayName", + "value": "Table" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "index" + }, + "properties": [ + { + "id": "displayName", + "value": "Index" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "index_size" + }, + "properties": [ + { + "id": "displayName", + "value": "Size" + }, + { + "id": "unit", + "value": "decbytes" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "index_scans" + }, + "properties": [ + { + "id": "displayName", + "value": "Scans" + }, + { + "id": "unit", + "value": "short" + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 9, + "x": 15, + "y": 37 + }, + "id": 18, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "11.2.0", + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "${DS_DITTO-PG}" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT\n relname AS table,\n indexrelname AS index,\n pg_relation_size(i.indexrelid) AS index_size,\n idx_scan as index_scans\nFROM\n pg_stat_user_indexes ui\n JOIN pg_index i ON ui.indexrelid = i.indexrelid\nWHERE\n NOT indisunique\n AND idx_scan < 50\n AND pg_relation_size(relid) > 5 * 8192\nORDER BY\n pg_relation_size(i.indexrelid) / nullif(idx_scan, 0) DESC NULLS FIRST,\n pg_relation_size(i.indexrelid) DESC;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Unused Indexes", + "type": "table" + }, + { + "datasource": { + "default": false, + "type": "prometheus", + "uid": "${prometheus}" + }, + "description": "Nostr messages sent to the relay over WebSocket.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "{instance=\"localhost:4036\", job=\"ditto\"}" + }, + "properties": [ + { + "id": "displayName", + "value": "Other" + }, + { + "id": "color", + "value": { + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "REQ" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "purple", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "EVENT" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "light-blue", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "CLOSE" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 9, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "increase(ditto_relay_messages_total[$__rate_interval])", + "format": "time_series", + "instant": false, + "legendFormat": "{{verb}}", + "range": true, + "refId": "A" + } + ], + "title": "Relay Messages", + "type": "timeseries" + }, + { + "datasource": { + "default": false, + "type": "prometheus", + "uid": "${prometheus}" + }, + "description": "Nostr events from all sources. Organized by kind.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Kind 0" + }, + "properties": [ + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "NIP-01", + "url": "https://github.com/nostr-protocol/nips/blob/master/01.md" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Kind 1" + }, + "properties": [ + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "NIP-01", + "url": "https://github.com/nostr-protocol/nips/blob/master/01.md" + } + ] + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 24, + "x": 0, + "y": 58 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "increase(ditto_pipeline_events_total[$__rate_interval])", + "instant": false, + "legendFormat": "Kind {{kind}}", + "range": true, + "refId": "A" + } + ], + "title": "Pipeline Events", + "type": "timeseries" + }, + { + "datasource": { + "default": false, + "type": "prometheus", + "uid": "${prometheus}" + }, + "description": "Rate of events being processed by different parts of the application.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 70 + }, + "id": 19, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(increase(ditto_pipeline_events_total[$__rate_interval]))", + "instant": false, + "legendFormat": "Pipeline Events", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${prometheus}" + }, + "editorMode": "code", + "expr": "sum(increase(ditto_relay_events_total[$__rate_interval]))", + "hide": false, + "instant": false, + "legendFormat": "Relay Events", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(increase(ditto_firehose_events_total[$__rate_interval]))", + "hide": false, + "instant": false, + "legendFormat": "Firehose Events", + "range": true, + "refId": "C" + } + ], + "title": "Event Sources", + "type": "timeseries" + } + ], + "refresh": "5s", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "cdtcs576ar7cwb" + }, + "filters": [], + "hide": 0, + "name": "Filters", + "skipUrlSync": false, + "type": "adhoc" + }, + { + "current": {}, + "description": "Prometheus datasource", + "hide": 0, + "includeAll": false, + "label": "Prometheus", + "multi": false, + "name": "prometheus", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "description": "PostgreSQL datasource", + "hide": 0, + "includeAll": false, + "label": "Postgres", + "multi": false, + "name": "postgres", + "options": [], + "query": "grafana-postgresql-datasource", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Ditto", + "uid": "ddps3ap51fv28d", + "version": 59, + "weekStart": "" +} \ No newline at end of file diff --git a/src/controllers/nostr/relay.ts b/src/controllers/nostr/relay.ts index 583fd153..9f47b382 100644 --- a/src/controllers/nostr/relay.ts +++ b/src/controllers/nostr/relay.ts @@ -12,7 +12,7 @@ import { import { AppController } from '@/app.ts'; import { Conf } from '@/config.ts'; import { relayInfoController } from '@/controllers/nostr/relay-info.ts'; -import { relayConnectionsGauge, relayEventCounter, relayMessageCounter } from '@/metrics.ts'; +import { relayConnectionsGauge, relayEventsCounter, relayMessagesCounter } from '@/metrics.ts'; import * as pipeline from '@/pipeline.ts'; import { RelayError } from '@/RelayError.ts'; import { Storages } from '@/storages.ts'; @@ -54,10 +54,10 @@ function connectStream(socket: WebSocket, ip: string | undefined) { const result = n.json().pipe(n.clientMsg()).safeParse(e.data); if (result.success) { - relayMessageCounter.inc({ verb: result.data[0] }); + relayMessagesCounter.inc({ verb: result.data[0] }); handleMsg(result.data); } else { - relayMessageCounter.inc(); + relayMessagesCounter.inc(); send(['NOTICE', 'Invalid message.']); } }; @@ -130,7 +130,7 @@ function connectStream(socket: WebSocket, ip: string | undefined) { /** Handle EVENT. Store the event. */ async function handleEvent([_, event]: NostrClientEVENT): Promise { - relayEventCounter.inc({ kind: event.kind.toString() }); + relayEventsCounter.inc({ kind: event.kind.toString() }); try { // This will store it (if eligible) and run other side-effects. await pipeline.handleEvent(event, AbortSignal.timeout(1000)); diff --git a/src/db/KyselyLogger.ts b/src/db/KyselyLogger.ts index 3b5b4398..72167e21 100644 --- a/src/db/KyselyLogger.ts +++ b/src/db/KyselyLogger.ts @@ -1,6 +1,6 @@ import { Stickynotes } from '@soapbox/stickynotes'; import { Logger } from 'kysely'; -import { dbQueryCounter, dbQueryTimeHistogram } from '@/metrics.ts'; +import { dbQueriesCounter, dbQueryDurationHistogram } from '@/metrics.ts'; /** Log the SQL for queries. */ export const KyselyLogger: Logger = (event) => { @@ -9,8 +9,8 @@ export const KyselyLogger: Logger = (event) => { const { query, queryDurationMillis } = event; const { sql, parameters } = query; - dbQueryCounter.inc(); - dbQueryTimeHistogram.observe(queryDurationMillis); + dbQueriesCounter.inc(); + dbQueryDurationHistogram.observe(queryDurationMillis); console.debug( sql, diff --git a/src/firehose.ts b/src/firehose.ts index 86d19f74..85e3dc89 100644 --- a/src/firehose.ts +++ b/src/firehose.ts @@ -2,7 +2,7 @@ import { Semaphore } from '@lambdalisue/async'; import { Stickynotes } from '@soapbox/stickynotes'; import { Conf } from '@/config.ts'; -import { firehoseEventCounter } from '@/metrics.ts'; +import { firehoseEventsCounter } from '@/metrics.ts'; import { Storages } from '@/storages.ts'; import { nostrNow } from '@/utils.ts'; @@ -23,7 +23,7 @@ export async function startFirehose(): Promise { if (msg[0] === 'EVENT') { const event = msg[2]; console.debug(`NostrEvent<${event.kind}> ${event.id}`); - firehoseEventCounter.inc({ kind: event.kind }); + firehoseEventsCounter.inc({ kind: event.kind }); sem.lock(async () => { try { diff --git a/src/metrics.ts b/src/metrics.ts index c1fb8238..ac1db2ee 100644 --- a/src/metrics.ts +++ b/src/metrics.ts @@ -1,86 +1,86 @@ import { Counter, Gauge, Histogram } from 'prom-client'; -export const httpRequestCounter = new Counter({ - name: 'http_requests_total', +export const httpRequestsCounter = new Counter({ + name: 'ditto_http_requests_total', help: 'Total number of HTTP requests', labelNames: ['method'], }); -export const httpResponseCounter = new Counter({ - name: 'http_responses_total', +export const httpResponsesCounter = new Counter({ + name: 'ditto_http_responses_total', help: 'Total number of HTTP responses', labelNames: ['method', 'path', 'status'], }); export const streamingConnectionsGauge = new Gauge({ - name: 'streaming_connections', + name: 'ditto_streaming_connections', help: 'Number of active connections to the streaming API', }); export const fetchCounter = new Counter({ - name: 'fetch_total', + name: 'ditto_fetch_total', help: 'Total number of fetch requests', labelNames: ['method'], }); -export const firehoseEventCounter = new Counter({ - name: 'firehose_events_total', +export const firehoseEventsCounter = new Counter({ + name: 'ditto_firehose_events_total', help: 'Total number of Nostr events processed by the firehose', labelNames: ['kind'], }); -export const pipelineEventCounter = new Counter({ - name: 'pipeline_events_total', +export const pipelineEventsCounter = new Counter({ + name: 'ditto_pipeline_events_total', help: 'Total number of Nostr events processed by the pipeline', labelNames: ['kind'], }); -export const policyEventCounter = new Counter({ - name: 'policy_events_total', +export const policyEventsCounter = new Counter({ + name: 'ditto_policy_events_total', help: 'Total number of policy OK responses', labelNames: ['ok'], }); -export const relayEventCounter = new Counter({ - name: 'relay_events_total', +export const relayEventsCounter = new Counter({ + name: 'ditto_relay_events_total', help: 'Total number of EVENT messages processed by the relay', labelNames: ['kind'], }); -export const relayMessageCounter = new Counter({ - name: 'relay_messages_total', +export const relayMessagesCounter = new Counter({ + name: 'ditto_relay_messages_total', help: 'Total number of Nostr messages processed by the relay', labelNames: ['verb'], }); export const relayConnectionsGauge = new Gauge({ - name: 'relay_connections', + name: 'ditto_relay_connections', help: 'Number of active connections to the relay', }); -export const dbQueryCounter = new Counter({ - name: 'db_query_total', +export const dbQueriesCounter = new Counter({ + name: 'ditto_db_queries_total', help: 'Total number of database queries', labelNames: ['kind'], }); -export const dbEventCounter = new Counter({ - name: 'db_events_total', +export const dbEventsCounter = new Counter({ + name: 'ditto_db_events_total', help: 'Total number of database inserts', labelNames: ['kind'], }); export const dbPoolSizeGauge = new Gauge({ - name: 'db_pool_size', + name: 'ditto_db_pool_size', help: 'Number of connections in the database pool', }); export const dbAvailableConnectionsGauge = new Gauge({ - name: 'db_available_connections', + name: 'ditto_db_available_connections', help: 'Number of available connections in the database pool', }); -export const dbQueryTimeHistogram = new Histogram({ - name: 'db_query_duration_ms', +export const dbQueryDurationHistogram = new Histogram({ + name: 'ditto_db_query_duration_ms', help: 'Duration of database queries', }); diff --git a/src/middleware/metricsMiddleware.ts b/src/middleware/metricsMiddleware.ts index 6cf0e6de..e8a30972 100644 --- a/src/middleware/metricsMiddleware.ts +++ b/src/middleware/metricsMiddleware.ts @@ -1,12 +1,12 @@ import { MiddlewareHandler } from '@hono/hono'; -import { httpRequestCounter, httpResponseCounter } from '@/metrics.ts'; +import { httpRequestsCounter, httpResponsesCounter } from '@/metrics.ts'; /** Prometheus metrics middleware that tracks HTTP requests by methods and responses by status code. */ export const metricsMiddleware: MiddlewareHandler = async (c, next) => { // HTTP Request. const { method } = c.req; - httpRequestCounter.inc({ method }); + httpRequestsCounter.inc({ method }); // Wait for other handlers to run. await next(); @@ -16,5 +16,5 @@ export const metricsMiddleware: MiddlewareHandler = async (c, next) => { // Get a parameterized path name like `/posts/:id` instead of `/posts/1234`. // Tries to find actual route names first before falling back on potential middleware handlers like `app.use('*')`. const path = c.req.matchedRoutes.find((r) => r.method !== 'ALL')?.path ?? c.req.routePath; - httpResponseCounter.inc({ method, status, path }); + httpResponsesCounter.inc({ method, status, path }); }; diff --git a/src/pipeline.ts b/src/pipeline.ts index 2fb18649..15c1ef34 100644 --- a/src/pipeline.ts +++ b/src/pipeline.ts @@ -8,7 +8,7 @@ import { Conf } from '@/config.ts'; import { DittoDB } from '@/db/DittoDB.ts'; import { deleteAttachedMedia } from '@/db/unattached-media.ts'; import { DittoEvent } from '@/interfaces/DittoEvent.ts'; -import { pipelineEventCounter, policyEventCounter } from '@/metrics.ts'; +import { pipelineEventsCounter, policyEventsCounter } from '@/metrics.ts'; import { RelayError } from '@/RelayError.ts'; import { AdminSigner } from '@/signers/AdminSigner.ts'; import { hydrateEvents } from '@/storages/hydrate.ts'; @@ -40,7 +40,7 @@ async function handleEvent(event: DittoEvent, signal: AbortSignal): Promise ${event.id}`); - pipelineEventCounter.inc({ kind: event.kind }); + pipelineEventsCounter.inc({ kind: event.kind }); if (event.kind !== 24133) { await policyFilter(event); @@ -71,7 +71,7 @@ async function policyFilter(event: NostrEvent): Promise { try { const result = await policyWorker.call(event); - policyEventCounter.inc({ ok: String(result[2]) }); + policyEventsCounter.inc({ ok: String(result[2]) }); debug(JSON.stringify(result)); RelayError.assert(result); } catch (e) { diff --git a/src/storages/EventsDB.ts b/src/storages/EventsDB.ts index 07be8067..7cbd9c22 100644 --- a/src/storages/EventsDB.ts +++ b/src/storages/EventsDB.ts @@ -17,7 +17,7 @@ import { nip27 } from 'nostr-tools'; import { Conf } from '@/config.ts'; import { DittoDatabase } from '@/db/DittoDB.ts'; -import { dbEventCounter } from '@/metrics.ts'; +import { dbEventsCounter } from '@/metrics.ts'; import { RelayError } from '@/RelayError.ts'; import { purifyEvent } from '@/storages/hydrate.ts'; import { isNostrId, isURL } from '@/utils.ts'; @@ -73,7 +73,7 @@ class EventsDB implements NStore { async event(event: NostrEvent, opts: { signal?: AbortSignal; timeout?: number } = {}): Promise { event = purifyEvent(event); this.console.debug('EVENT', JSON.stringify(event)); - dbEventCounter.inc({ kind: event.kind }); + dbEventsCounter.inc({ kind: event.kind }); if (await this.isDeletedAdmin(event)) { throw new RelayError('blocked', 'event deleted by admin');