Skip to content

Commit fbd58fe

Browse files
committed
fix: styling
1 parent b874425 commit fbd58fe

File tree

7 files changed

+569
-52
lines changed

7 files changed

+569
-52
lines changed

docker-compose.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
version: '3.8'
2+
3+
services:
4+
postgres:
5+
image: postgres:16-alpine
6+
container_name: pev-postgres
7+
environment:
8+
POSTGRES_DB: testdb
9+
POSTGRES_USER: testuser
10+
POSTGRES_PASSWORD: testpass
11+
ports:
12+
- "5432:5432"
13+
volumes:
14+
- postgres-data:/var/lib/postgresql/data
15+
- ./tests/postgres-init:/docker-entrypoint-initdb.d
16+
healthcheck:
17+
test: ["CMD-SHELL", "pg_isready -U testuser -d testdb"]
18+
interval: 5s
19+
timeout: 5s
20+
retries: 5
21+
22+
grafana:
23+
image: grafana/grafana:10.4.0
24+
container_name: pev-grafana
25+
ports:
26+
- "3000:3000"
27+
environment:
28+
- GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=cybertec-pev-panel
29+
- GF_AUTH_ANONYMOUS_ENABLED=true
30+
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
31+
- GF_AUTH_DISABLE_LOGIN_FORM=false
32+
- GF_LOG_LEVEL=debug
33+
volumes:
34+
- ./dist:/var/lib/grafana/plugins/cybertec-pev-panel
35+
- ./provisioning:/etc/grafana/provisioning
36+
- grafana-data:/var/lib/grafana
37+
depends_on:
38+
postgres:
39+
condition: service_healthy
40+
healthcheck:
41+
test: ["CMD-SHELL", "curl -f http://localhost:3000/api/health || exit 1"]
42+
interval: 10s
43+
timeout: 5s
44+
retries: 5
45+
46+
volumes:
47+
postgres-data:
48+
grafana-data:
Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
{
2+
"annotations": {
3+
"list": []
4+
},
5+
"editable": true,
6+
"fiscalYearStartMonth": 0,
7+
"graphTooltip": 0,
8+
"id": null,
9+
"links": [],
10+
"liveNow": false,
11+
"panels": [
12+
{
13+
"datasource": {
14+
"type": "postgres",
15+
"uid": "postgres-testdb"
16+
},
17+
"description": "Simple sequential scan - tests basic JSON EXPLAIN visualization",
18+
"gridPos": {
19+
"h": 12,
20+
"w": 12,
21+
"x": 0,
22+
"y": 0
23+
},
24+
"id": 1,
25+
"options": {
26+
"planFieldName": "QUERY PLAN",
27+
"forceJsonMode": false,
28+
"fontSize": 14,
29+
"darkMode": false
30+
},
31+
"targets": [
32+
{
33+
"datasource": {
34+
"type": "postgres",
35+
"uid": "postgres-testdb"
36+
},
37+
"format": "table",
38+
"rawSql": "EXPLAIN (FORMAT JSON, ANALYZE, BUFFERS)\nSELECT * FROM users WHERE age > 25;",
39+
"refId": "A"
40+
}
41+
],
42+
"title": "Test 1: Simple Sequential Scan",
43+
"type": "cybertec-pev-panel"
44+
},
45+
{
46+
"datasource": {
47+
"type": "postgres",
48+
"uid": "postgres-testdb"
49+
},
50+
"description": "Index scan - tests index usage visualization",
51+
"gridPos": {
52+
"h": 12,
53+
"w": 12,
54+
"x": 12,
55+
"y": 0
56+
},
57+
"id": 2,
58+
"options": {
59+
"planFieldName": "QUERY PLAN",
60+
"forceJsonMode": false,
61+
"fontSize": 14,
62+
"darkMode": false
63+
},
64+
"targets": [
65+
{
66+
"datasource": {
67+
"type": "postgres",
68+
"uid": "postgres-testdb"
69+
},
70+
"format": "table",
71+
"rawSql": "EXPLAIN (FORMAT JSON, ANALYZE)\nSELECT * FROM users WHERE email = 'user500@example.com';",
72+
"refId": "A"
73+
}
74+
],
75+
"title": "Test 2: Index Scan",
76+
"type": "cybertec-pev-panel"
77+
},
78+
{
79+
"datasource": {
80+
"type": "postgres",
81+
"uid": "postgres-testdb"
82+
},
83+
"description": "Join query - tests multi-node visualization",
84+
"gridPos": {
85+
"h": 12,
86+
"w": 12,
87+
"x": 0,
88+
"y": 12
89+
},
90+
"id": 3,
91+
"options": {
92+
"planFieldName": "QUERY PLAN",
93+
"forceJsonMode": false,
94+
"fontSize": 14,
95+
"darkMode": false
96+
},
97+
"targets": [
98+
{
99+
"datasource": {
100+
"type": "postgres",
101+
"uid": "postgres-testdb"
102+
},
103+
"format": "table",
104+
"rawSql": "EXPLAIN (FORMAT JSON, ANALYZE, BUFFERS)\nSELECT u.name, u.email, o.total, o.status\nFROM users u\nJOIN orders o ON u.id = o.user_id\nWHERE u.age > 30 AND o.status = 'completed'\nORDER BY o.total DESC\nLIMIT 20;",
105+
"refId": "A"
106+
}
107+
],
108+
"title": "Test 3: Join Query with Filter",
109+
"type": "cybertec-pev-panel"
110+
},
111+
{
112+
"datasource": {
113+
"type": "postgres",
114+
"uid": "postgres-testdb"
115+
},
116+
"description": "Aggregation query - tests GROUP BY visualization",
117+
"gridPos": {
118+
"h": 12,
119+
"w": 12,
120+
"x": 12,
121+
"y": 12
122+
},
123+
"id": 4,
124+
"options": {
125+
"planFieldName": "QUERY PLAN",
126+
"forceJsonMode": false,
127+
"fontSize": 14,
128+
"darkMode": false
129+
},
130+
"targets": [
131+
{
132+
"datasource": {
133+
"type": "postgres",
134+
"uid": "postgres-testdb"
135+
},
136+
"format": "table",
137+
"rawSql": "EXPLAIN (FORMAT JSON, ANALYZE, BUFFERS)\nSELECT u.country, COUNT(*) as user_count, AVG(o.total) as avg_total\nFROM users u\nLEFT JOIN orders o ON u.id = o.user_id\nGROUP BY u.country\nHAVING COUNT(*) > 50\nORDER BY avg_total DESC;",
138+
"refId": "A"
139+
}
140+
],
141+
"title": "Test 4: Aggregation with GROUP BY",
142+
"type": "cybertec-pev-panel"
143+
},
144+
{
145+
"datasource": {
146+
"type": "postgres",
147+
"uid": "postgres-testdb"
148+
},
149+
"description": "Complex CTE query - tests nested plan visualization",
150+
"gridPos": {
151+
"h": 12,
152+
"w": 12,
153+
"x": 0,
154+
"y": 24
155+
},
156+
"id": 5,
157+
"options": {
158+
"planFieldName": "QUERY PLAN",
159+
"forceJsonMode": false,
160+
"fontSize": 14,
161+
"darkMode": false
162+
},
163+
"targets": [
164+
{
165+
"datasource": {
166+
"type": "postgres",
167+
"uid": "postgres-testdb"
168+
},
169+
"format": "table",
170+
"rawSql": "EXPLAIN (FORMAT JSON, ANALYZE)\nWITH recent_orders AS (\n SELECT user_id, SUM(total) as total_spent, COUNT(*) as order_count\n FROM orders\n WHERE created_at > CURRENT_DATE - INTERVAL '30 days'\n GROUP BY user_id\n)\nSELECT u.name, u.email, u.country, ro.total_spent, ro.order_count\nFROM users u\nJOIN recent_orders ro ON u.id = ro.user_id\nWHERE ro.total_spent > 100\nORDER BY ro.total_spent DESC\nLIMIT 10;",
171+
"refId": "A"
172+
}
173+
],
174+
"title": "Test 5: CTE Query",
175+
"type": "cybertec-pev-panel"
176+
},
177+
{
178+
"datasource": {
179+
"type": "postgres",
180+
"uid": "postgres-testdb"
181+
},
182+
"description": "Multi-table join - tests complex join tree",
183+
"gridPos": {
184+
"h": 12,
185+
"w": 12,
186+
"x": 12,
187+
"y": 24
188+
},
189+
"id": 6,
190+
"options": {
191+
"planFieldName": "QUERY PLAN",
192+
"forceJsonMode": false,
193+
"fontSize": 14,
194+
"darkMode": false
195+
},
196+
"targets": [
197+
{
198+
"datasource": {
199+
"type": "postgres",
200+
"uid": "postgres-testdb"
201+
},
202+
"format": "table",
203+
"rawSql": "EXPLAIN (FORMAT JSON, ANALYZE, BUFFERS)\nSELECT u.name, o.id as order_id, p.name as product_name, oi.quantity, oi.price\nFROM users u\nJOIN orders o ON u.id = o.user_id\nJOIN order_items oi ON o.id = oi.order_id\nJOIN products p ON oi.product_id = p.id\nWHERE u.country = 'USA' AND p.category = 'Electronics'\nLIMIT 50;",
204+
"refId": "A"
205+
}
206+
],
207+
"title": "Test 6: Multi-Table Join",
208+
"type": "cybertec-pev-panel"
209+
},
210+
{
211+
"datasource": {
212+
"type": "testdata",
213+
"uid": "trlxrdZVk"
214+
},
215+
"description": "CSV format - tests TestData data source with simple plan",
216+
"gridPos": {
217+
"h": 12,
218+
"w": 12,
219+
"x": 0,
220+
"y": 36
221+
},
222+
"id": 7,
223+
"options": {
224+
"planFieldName": "plan",
225+
"forceJsonMode": true,
226+
"fontSize": 14,
227+
"darkMode": false
228+
},
229+
"targets": [
230+
{
231+
"datasource": {
232+
"type": "testdata",
233+
"uid": "trlxrdZVk"
234+
},
235+
"refId": "A",
236+
"scenarioId": "csv_content",
237+
"csvContent": "plan\n\"{\"\"Plan\"\":{\"\"Node Type\"\":\"\"Seq Scan\"\",\"\"Relation Name\"\":\"\"users\"\",\"\"Startup Cost\"\":0.00,\"\"Total Cost\"\":35.50,\"\"Plan Rows\"\":1000,\"\"Plan Width\"\":244}}\""
238+
}
239+
],
240+
"title": "Test 7: TestData CSV - Simple Scan",
241+
"type": "cybertec-pev-panel"
242+
},
243+
{
244+
"datasource": {
245+
"type": "testdata",
246+
"uid": "trlxrdZVk"
247+
},
248+
"description": "CSV format - tests join visualization from TestData",
249+
"gridPos": {
250+
"h": 12,
251+
"w": 12,
252+
"x": 12,
253+
"y": 36
254+
},
255+
"id": 8,
256+
"options": {
257+
"planFieldName": "plan",
258+
"forceJsonMode": true,
259+
"fontSize": 14,
260+
"darkMode": false
261+
},
262+
"targets": [
263+
{
264+
"datasource": {
265+
"type": "testdata",
266+
"uid": "trlxrdZVk"
267+
},
268+
"refId": "A",
269+
"scenarioId": "csv_content",
270+
"csvContent": "plan\n\"{\"\"Plan\"\":{\"\"Node Type\"\":\"\"Hash Join\"\",\"\"Join Type\"\":\"\"Inner\"\",\"\"Startup Cost\"\":45.0,\"\"Total Cost\"\":125.5,\"\"Plan Rows\"\":500,\"\"Plan Width\"\":360,\"\"Plans\"\":[{\"\"Node Type\"\":\"\"Seq Scan\"\",\"\"Relation Name\"\":\"\"users\"\",\"\"Startup Cost\"\":0.0,\"\"Total Cost\"\":35.5,\"\"Plan Rows\"\":1000,\"\"Plan Width\"\":244},{\"\"Node Type\"\":\"\"Hash\"\",\"\"Startup Cost\"\":10.0,\"\"Total Cost\"\":10.0,\"\"Plan Rows\"\":250,\"\"Plan Width\"\":116,\"\"Plans\"\":[{\"\"Node Type\"\":\"\"Seq Scan\"\",\"\"Relation Name\"\":\"\"orders\"\",\"\"Startup Cost\"\":0.0,\"\"Total Cost\"\":10.0,\"\"Plan Rows\"\":250,\"\"Plan Width\"\":116}]}]}}\""
271+
}
272+
],
273+
"title": "Test 8: TestData CSV - Join Query",
274+
"type": "cybertec-pev-panel"
275+
}
276+
],
277+
"refresh": "",
278+
"schemaVersion": 39,
279+
"tags": ["pev", "testing", "explain"],
280+
"templating": {
281+
"list": []
282+
},
283+
"time": {
284+
"from": "now-6h",
285+
"to": "now"
286+
},
287+
"timepicker": {},
288+
"timezone": "",
289+
"title": "PEV Panel Test Dashboard",
290+
"uid": "pev-test-dashboard",
291+
"version": 1
292+
}

provisioning/datasources/datasources.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,18 @@ datasources:
44
- name: TestData DB
55
type: testdata
66
uid: trlxrdZVk
7+
isDefault: false
8+
9+
- name: PostgreSQL
10+
type: postgres
11+
uid: postgres-testdb
712
isDefault: true
13+
url: postgres:5432
14+
database: testdb
15+
user: testuser
16+
secureJsonData:
17+
password: testpass
18+
jsonData:
19+
sslmode: disable
20+
postgresVersion: 1600
21+
timescaledb: false

0 commit comments

Comments
 (0)