Skip to content

Commit 20966c7

Browse files
committed
Merge branch 'PoC_double_pgwatch' into 'main'
Added an example of two pgwatch agents running with different sinks See merge request postgres-ai/postgres_ai!1
2 parents 2534f82 + 0fe35d7 commit 20966c7

File tree

11 files changed

+492
-0
lines changed

11 files changed

+492
-0
lines changed
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
{
2+
"annotations": {
3+
"list": [
4+
{
5+
"builtIn": 1,
6+
"datasource": {
7+
"type": "grafana",
8+
"uid": "-- Grafana --"
9+
},
10+
"enable": true,
11+
"hide": true,
12+
"iconColor": "rgba(0, 211, 255, 1)",
13+
"name": "Annotations & Alerts",
14+
"type": "dashboard"
15+
}
16+
]
17+
},
18+
"editable": true,
19+
"fiscalYearStartMonth": 0,
20+
"graphTooltip": 0,
21+
"id": 1,
22+
"links": [],
23+
"panels": [
24+
{
25+
"datasource": {
26+
"type": "datasource",
27+
"uid": "-- Mixed --"
28+
},
29+
"fieldConfig": {
30+
"defaults": {
31+
"color": {
32+
"mode": "palette-classic"
33+
},
34+
"custom": {
35+
"axisBorderShow": false,
36+
"axisCenteredZero": false,
37+
"axisColorMode": "text",
38+
"axisLabel": "",
39+
"axisPlacement": "auto",
40+
"barAlignment": -1,
41+
"barWidthFactor": 0.6,
42+
"drawStyle": "line",
43+
"fillOpacity": 20,
44+
"gradientMode": "none",
45+
"hideFrom": {
46+
"legend": false,
47+
"tooltip": false,
48+
"viz": false
49+
},
50+
"insertNulls": false,
51+
"lineInterpolation": "linear",
52+
"lineWidth": 1,
53+
"pointSize": 1,
54+
"scaleDistribution": {
55+
"type": "linear"
56+
},
57+
"showPoints": "auto",
58+
"spanNulls": false,
59+
"stacking": {
60+
"group": "A",
61+
"mode": "normal"
62+
},
63+
"thresholdsStyle": {
64+
"mode": "off"
65+
}
66+
},
67+
"mappings": [],
68+
"thresholds": {
69+
"mode": "absolute",
70+
"steps": [
71+
{
72+
"color": "green"
73+
},
74+
{
75+
"color": "red",
76+
"value": 80
77+
}
78+
]
79+
}
80+
},
81+
"overrides": [
82+
{
83+
"matcher": {
84+
"id": "byRegexp",
85+
"options": ".*"
86+
},
87+
"properties": [
88+
{
89+
"id": "displayName",
90+
"value": "${__field.labels.query_text}"
91+
}
92+
]
93+
}
94+
]
95+
},
96+
"gridPos": {
97+
"h": 8,
98+
"w": 12,
99+
"x": 0,
100+
"y": 0
101+
},
102+
"id": 1,
103+
"options": {
104+
"legend": {
105+
"calcs": [],
106+
"displayMode": "list",
107+
"placement": "bottom",
108+
"showLegend": true
109+
},
110+
"tooltip": {
111+
"hideZeros": false,
112+
"mode": "single",
113+
"sort": "none"
114+
}
115+
},
116+
"pluginVersion": "12.0.2",
117+
"targets": [
118+
{
119+
"datasource": {
120+
"type": "prometheus",
121+
"uid": "P7A0D6631BB10B34F"
122+
},
123+
"disableTextWrap": false,
124+
"editorMode": "code",
125+
"expr": "pgwatch_pg_stat_statements_calls_calls",
126+
"fullMetaSearch": false,
127+
"hide": false,
128+
"includeNullMetadata": true,
129+
"legendFormat": "__auto",
130+
"range": true,
131+
"refId": "B",
132+
"useBackend": false
133+
},
134+
{
135+
"datasource": {
136+
"type": "grafana-postgresql-datasource",
137+
"uid": "P031DD592934B2F1F"
138+
},
139+
"editorMode": "code",
140+
"format": "table",
141+
"hide": false,
142+
"rawQuery": true,
143+
"rawSql": "SELECT\n DISTINCT (data ->> 'queryid') as queryid,\n data ->> 'query' as query_text\nFROM\n pgss_queryid_queries\nWHERE\n $__timeFilter(time)",
144+
"refId": "A",
145+
"sql": {
146+
"columns": [
147+
{
148+
"parameters": [],
149+
"type": "function"
150+
}
151+
],
152+
"groupBy": [
153+
{
154+
"property": {
155+
"type": "string"
156+
},
157+
"type": "groupBy"
158+
}
159+
],
160+
"limit": 50
161+
}
162+
}
163+
],
164+
"title": "pg_stat_statements_calls_to_query",
165+
"transformations": [
166+
{
167+
"filter": {
168+
"id": "byRefId",
169+
"options": "/^(?:B)$/"
170+
},
171+
"id": "seriesToRows",
172+
"options": {}
173+
},
174+
{
175+
"filter": {
176+
"id": "byRefId",
177+
"options": "/^(?:seriesToRows-B-B-B-B-B-B-B-B-B)$/"
178+
},
179+
"id": "extractFields",
180+
"options": {
181+
"delimiter": ",",
182+
"keepTime": false,
183+
"replace": false,
184+
"source": "Metric"
185+
}
186+
},
187+
{
188+
"id": "joinByField",
189+
"options": {
190+
"byField": "queryid",
191+
"mode": "inner"
192+
}
193+
},
194+
{
195+
"id": "filterFieldsByName",
196+
"options": {
197+
"byVariable": false,
198+
"include": {
199+
"names": [
200+
"Time",
201+
"Value",
202+
"query_text"
203+
]
204+
}
205+
}
206+
},
207+
{
208+
"id": "prepareTimeSeries",
209+
"options": {
210+
"format": "multi"
211+
}
212+
}
213+
],
214+
"type": "timeseries"
215+
}
216+
],
217+
"preload": false,
218+
"refresh": "auto",
219+
"schemaVersion": 41,
220+
"tags": [],
221+
"templating": {
222+
"list": []
223+
},
224+
"time": {
225+
"from": "now-5m",
226+
"to": "now"
227+
},
228+
"timepicker": {},
229+
"timezone": "browser",
230+
"title": "PoC",
231+
"uid": "00eb62a7-4b80-43cd-a890-45336979aa18",
232+
"version": 2
233+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: 1
2+
3+
providers:
4+
- name: 'PoC'
5+
orgId: 1
6+
type: file
7+
disableDeletion: false
8+
updateIntervalSeconds: 10
9+
allowUiUpdates: true
10+
options:
11+
path: /var/lib/grafana/dashboards/dash1.json
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
apiVersion: 1
2+
3+
datasources:
4+
- name: PGWatch-PostgreSQL
5+
type: postgres
6+
access: proxy
7+
url: sink-postgres:5432
8+
database: measurements
9+
user: pgwatch
10+
secureJsonData:
11+
password: pgwatchadmin
12+
jsonData:
13+
sslmode: disable
14+
postgresVersion: 1500
15+
isDefault: true
16+
17+
- name: PGWatch-Prometheus
18+
type: prometheus
19+
access: proxy
20+
url: http://sink-prometheus:9090
21+
isDefault: false
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Minimal PGWatch Metrics for PostgreSQL Sink - pg_stat_statements only
2+
metrics:
3+
pgss_queryid_queries:
4+
description: "Query ID calls and query text from pg_stat_statements for PostgreSQL storage"
5+
sqls:
6+
11: |-
7+
select /* pgwatch_generated */
8+
(extract(epoch from now()) * 1e9)::int8 as epoch_ns,
9+
queryid,
10+
query
11+
from pg_stat_statements
12+
where queryid is not null
13+
gauges:
14+
- '*'
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# PGWatch Sources Configuration - PostgreSQL Instance
2+
# This instance stores detailed metrics in PostgreSQL format
3+
4+
- name: target-database
5+
conn_str: postgresql://pgwatch_monitor:monitor_pass@target-db:5432/target_database
6+
kind: postgres
7+
custom_metrics:
8+
pgss_queryid_queries: 30
9+
custom_tags:
10+
env: demo
11+
cluster: local
12+
sink_type: postgresql
13+
is_enabled: true
14+
stmt_timeout: 30
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Simple PGWatch Metrics for Prometheus - just queryid and calls
2+
metrics:
3+
pg_stat_statements_calls:
4+
description: "Simple queryid and calls metric"
5+
sqls:
6+
11: |-
7+
select /* pgwatch_generated */
8+
(extract(epoch from now()) * 1e9)::int8 as epoch_ns,
9+
queryid::text as tag_queryid,
10+
calls
11+
from pg_stat_statements
12+
where queryid is not null
13+
order by calls desc
14+
limit 10
15+
gauges:
16+
- calls
17+
master_only: false
18+
is_instance_level: false
19+
metric_storage_name: pgss_calls
20+
node_status: primary
21+
statement_timeout_seconds: 5
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# PGWatch Sources Configuration - Prometheus Instance
2+
# This instance exposes metrics in Prometheus format
3+
4+
- name: target-database
5+
conn_str: postgresql://pgwatch_monitor:monitor_pass@target-db:5432/target_database
6+
kind: postgres
7+
custom_metrics:
8+
pg_stat_statements_calls: 30
9+
custom_tags:
10+
env: demo
11+
cluster: local
12+
sink_type: prometheus
13+
is_enabled: true
14+
stmt_timeout: 15

config/prometheus/prometheus.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
global:
2+
scrape_interval: 1s
3+
evaluation_interval: 1s
4+
5+
rule_files:
6+
# - "first_rules.yml"
7+
# - "second_rules.yml"
8+
9+
scrape_configs:
10+
- job_name: 'pgwatch-prometheus'
11+
static_configs:
12+
- targets: ['pgwatch-prometheus:9091']
13+
scrape_interval: 30s
14+
metrics_path: /pgwatch

config/sink-postgres/init.sql

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
-- Initialize PostgreSQL sink database for storing pgwatch measurements
2+
-- This database will store all the monitoring metrics collected by PGWatch
3+
-- Based on https://pgwat.ch/latest/howto/metrics_db_bootstrap.html
4+
5+
-- Create the pgwatch role for measurements database
6+
CREATE ROLE pgwatch WITH LOGIN PASSWORD 'pgwatchadmin';
7+
8+
-- Create the measurements database owned by pgwatch
9+
CREATE DATABASE measurements OWNER pgwatch;
10+
11+
-- Switch to the measurements database context
12+
\c measurements;
13+
14+
-- Create extensions that might be useful for metrics storage
15+
CREATE EXTENSION IF NOT EXISTS btree_gist;
16+
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
17+
18+
-- Grant necessary permissions to pgwatch user
19+
GRANT ALL PRIVILEGES ON DATABASE measurements TO pgwatch;
20+
GRANT ALL PRIVILEGES ON SCHEMA public TO pgwatch;
21+
22+
-- pgwatch will automatically create the admin and subpartitions schemas
23+
-- and all necessary tables when it starts up

0 commit comments

Comments
 (0)