@emeryld/obs-stack 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -111,6 +111,16 @@ Adjust the `backend` service inside `examples/docker-compose.override.yml` to ma
111
111
  ## Grafana provisioning
112
112
 
113
113
  Grafana relies on the datasources defined in `grafana/provisioning/datasources/datasources.yaml` to wire up Loki and Tempo automatically. You never need to configure the data sources manually—just open Grafana at the URL reported by `obs-stack urls`.
114
+ Each datasource now exposes a stable `uid` (`loki` and `tempo`) so the shipping dashboards can reference them reliably.
115
+
116
+ We also preload three starter dashboards via `grafana/provisioning/dashboards/`. Each JSON file targets the Loki datasource (uid `loki`) so they work out of the box:
117
+
118
+ - **Logs overview**: table-based log stream plus a severity breakout to spot noisy services that are emitting within the selected time range; the bottom table also shows the modules that currently produce the most log volume.
119
+ - **Error spotlight**: graph of error rate per service, a recent error table, and a quick stat showing how many error events arrived over the past five minutes.
120
+ - **Service telemetry**: log rate by logger namespace, the top namespaces by volume, and a traced-log ratio that highlights how many records still carry `trace_id`.
121
+ The dashboard also now surfaces request throughput per route and a cache hit ratio stat so you can compare HTTP behavior and cache effectiveness without building ad-hoc panels.
122
+
123
+ Edit the JSON in `grafana/provisioning/dashboards/files/` (or export updates from Grafana) and restart the stack or reload dashboards to see your changes automatically.
114
124
 
115
125
  ## Troubleshooting
116
126
 
@@ -0,0 +1,9 @@
1
+ apiVersion: 1
2
+ providers:
3
+ - name: "obs-stack dashboards"
4
+ orgId: 1
5
+ folder: ""
6
+ type: file
7
+ disableDeletion: false
8
+ options:
9
+ path: /etc/grafana/provisioning/dashboards/files
@@ -0,0 +1,209 @@
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
+ "gnetId": null,
20
+ "graphTooltip": 0,
21
+ "id": null,
22
+ "links": [],
23
+ "liveNow": false,
24
+ "panels": [
25
+ {
26
+ "datasource": {
27
+ "type": "loki",
28
+ "uid": "loki"
29
+ },
30
+ "fieldConfig": {
31
+ "defaults": {
32
+ "custom": {},
33
+ "mappings": [],
34
+ "thresholds": {
35
+ "mode": "absolute",
36
+ "steps": [
37
+ {
38
+ "color": "green",
39
+ "value": null
40
+ }
41
+ ]
42
+ },
43
+ "unit": "short"
44
+ },
45
+ "overrides": []
46
+ },
47
+ "gridPos": {
48
+ "h": 8,
49
+ "w": 12,
50
+ "x": 0,
51
+ "y": 0
52
+ },
53
+ "id": 1,
54
+ "options": {
55
+ "legend": {
56
+ "displayMode": "list",
57
+ "placement": "bottom"
58
+ }
59
+ },
60
+ "targets": [
61
+ {
62
+ "datasource": {
63
+ "type": "loki",
64
+ "uid": "loki"
65
+ },
66
+ "expr": "sum(rate({severityText=\"ERROR\", service_name=~\"$service_name\"}[1m])) by (service_name)",
67
+ "queryType": "range",
68
+ "refId": "A"
69
+ }
70
+ ],
71
+ "title": "Error rate per service",
72
+ "type": "timeseries"
73
+ },
74
+ {
75
+ "datasource": {
76
+ "type": "loki",
77
+ "uid": "loki"
78
+ },
79
+ "fieldConfig": {
80
+ "defaults": {
81
+ "custom": {},
82
+ "mappings": [],
83
+ "thresholds": {
84
+ "mode": "absolute",
85
+ "steps": [
86
+ {
87
+ "color": "green",
88
+ "value": null
89
+ }
90
+ ]
91
+ }
92
+ },
93
+ "overrides": []
94
+ },
95
+ "gridPos": {
96
+ "h": 8,
97
+ "w": 12,
98
+ "x": 0,
99
+ "y": 8
100
+ },
101
+ "id": 2,
102
+ "options": {
103
+ "showHeader": true
104
+ },
105
+ "targets": [
106
+ {
107
+ "datasource": {
108
+ "type": "loki",
109
+ "uid": "loki"
110
+ },
111
+ "expr": "{severityText=\"ERROR\", service_name=~\"$service_name\"}",
112
+ "queryType": "range",
113
+ "refId": "A"
114
+ }
115
+ ],
116
+ "title": "Recent errors",
117
+ "type": "table"
118
+ },
119
+ {
120
+ "datasource": {
121
+ "type": "loki",
122
+ "uid": "loki"
123
+ },
124
+ "fieldConfig": {
125
+ "defaults": {
126
+ "custom": {},
127
+ "mappings": [],
128
+ "unit": "short"
129
+ },
130
+ "overrides": []
131
+ },
132
+ "gridPos": {
133
+ "h": 4,
134
+ "w": 12,
135
+ "x": 0,
136
+ "y": 16
137
+ },
138
+ "id": 3,
139
+ "options": {
140
+ "orientation": "horizontal",
141
+ "reduceOptions": {
142
+ "calcs": [
143
+ "sum"
144
+ ],
145
+ "fields": "",
146
+ "values": false
147
+ },
148
+ "textMode": "auto"
149
+ },
150
+ "targets": [
151
+ {
152
+ "datasource": {
153
+ "type": "loki",
154
+ "uid": "loki"
155
+ },
156
+ "expr": "sum(count_over_time({severityText=\"ERROR\", service_name=~\"$service_name\"}[5m]))",
157
+ "queryType": "range",
158
+ "refId": "A"
159
+ }
160
+ ],
161
+ "title": "Errors in last 5 minutes",
162
+ "type": "stat"
163
+ }
164
+ ],
165
+ "refresh": "5s",
166
+ "schemaVersion": 38,
167
+ "style": "dark",
168
+ "tags": [
169
+ "errors",
170
+ "alerts",
171
+ "logs"
172
+ ],
173
+ "templating": {
174
+ "list": [
175
+ {
176
+ "allValue": ".*",
177
+ "datasource": {
178
+ "type": "loki",
179
+ "uid": "loki"
180
+ },
181
+ "definition": "label_values({service_name!=\"\"}, service_name)",
182
+ "includeAll": true,
183
+ "label": "Service",
184
+ "multi": false,
185
+ "name": "service_name",
186
+ "options": [],
187
+ "query": "label_values({service_name!=\"\"}, service_name)",
188
+ "refresh": 2,
189
+ "skipUrlSync": false,
190
+ "type": "query",
191
+ "useTags": false,
192
+ "current": {
193
+ "text": "All services",
194
+ "value": ".*"
195
+ }
196
+ }
197
+ ]
198
+ },
199
+ "time": {
200
+ "from": "now-1h",
201
+ "to": "now"
202
+ },
203
+ "timepicker": {},
204
+ "timezone": "browser",
205
+ "title": "Error spotlight",
206
+ "uid": "error-spotlight",
207
+ "version": 1,
208
+ "weekStart": ""
209
+ }
@@ -0,0 +1,221 @@
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
+ "gnetId": null,
20
+ "graphTooltip": 0,
21
+ "id": null,
22
+ "links": [],
23
+ "liveNow": false,
24
+ "panels": [
25
+ {
26
+ "datasource": {
27
+ "type": "loki",
28
+ "uid": "loki"
29
+ },
30
+ "fieldConfig": {
31
+ "defaults": {
32
+ "custom": {},
33
+ "mappings": [],
34
+ "thresholds": {
35
+ "mode": "absolute",
36
+ "steps": [
37
+ {
38
+ "color": "green",
39
+ "value": null
40
+ }
41
+ ]
42
+ }
43
+ },
44
+ "overrides": []
45
+ },
46
+ "gridPos": {
47
+ "h": 12,
48
+ "w": 12,
49
+ "x": 0,
50
+ "y": 0
51
+ },
52
+ "id": 1,
53
+ "options": {
54
+ "showLabels": true,
55
+ "showTime": true,
56
+ "wrapLogMessage": true
57
+ },
58
+ "targets": [
59
+ {
60
+ "datasource": {
61
+ "type": "loki",
62
+ "uid": "loki"
63
+ },
64
+ "editorMode": "builder",
65
+ "expr": "{service_name=~\"$service_name\"}",
66
+ "queryType": "range",
67
+ "refId": "A"
68
+ }
69
+ ],
70
+ "title": "Log stream",
71
+ "type": "logs"
72
+ },
73
+ {
74
+ "datasource": {
75
+ "type": "loki",
76
+ "uid": "loki"
77
+ },
78
+ "fieldConfig": {
79
+ "defaults": {
80
+ "custom": {},
81
+ "mappings": [],
82
+ "thresholds": {
83
+ "mode": "absolute",
84
+ "steps": [
85
+ {
86
+ "color": "green",
87
+ "value": null
88
+ }
89
+ ]
90
+ },
91
+ "unit": "short"
92
+ },
93
+ "overrides": []
94
+ },
95
+ "gridPos": {
96
+ "h": 8,
97
+ "w": 12,
98
+ "x": 0,
99
+ "y": 12
100
+ },
101
+ "id": 2,
102
+ "options": {
103
+ "legend": {
104
+ "displayMode": "list",
105
+ "placement": "bottom"
106
+ },
107
+ "tooltip": {
108
+ "mode": "single"
109
+ }
110
+ },
111
+ "targets": [
112
+ {
113
+ "datasource": {
114
+ "type": "loki",
115
+ "uid": "loki"
116
+ },
117
+ "expr": "sum(rate({service_name=~\"$service_name\"}[5m])) by (severityText)",
118
+ "queryType": "range",
119
+ "refId": "A"
120
+ }
121
+ ],
122
+ "title": "Log rate by severity",
123
+ "type": "timeseries"
124
+ }
125
+ ,
126
+ {
127
+ "datasource": {
128
+ "type": "loki",
129
+ "uid": "loki"
130
+ },
131
+ "fieldConfig": {
132
+ "defaults": {
133
+ "custom": {},
134
+ "mappings": [],
135
+ "thresholds": {
136
+ "mode": "absolute",
137
+ "steps": [
138
+ {
139
+ "color": "green",
140
+ "value": null
141
+ }
142
+ ]
143
+ }
144
+ },
145
+ "overrides": []
146
+ },
147
+ "gridPos": {
148
+ "h": 8,
149
+ "w": 12,
150
+ "x": 0,
151
+ "y": 20
152
+ },
153
+ "id": 3,
154
+ "options": {
155
+ "showHeader": true,
156
+ "sortBy": [
157
+ {
158
+ "desc": true,
159
+ "displayName": "Value"
160
+ }
161
+ ]
162
+ },
163
+ "targets": [
164
+ {
165
+ "datasource": {
166
+ "type": "loki",
167
+ "uid": "loki"
168
+ },
169
+ "expr": "topk(5, sum by (module) (count_over_time({module!=\"\"}[5m])))",
170
+ "queryType": "range",
171
+ "refId": "A"
172
+ }
173
+ ],
174
+ "title": "Top modules by log volume",
175
+ "type": "table"
176
+ }
177
+ ],
178
+ "refresh": "15s",
179
+ "schemaVersion": 38,
180
+ "style": "dark",
181
+ "tags": [
182
+ "logs",
183
+ "observability"
184
+ ],
185
+ "templating": {
186
+ "list": [
187
+ {
188
+ "allValue": ".*",
189
+ "datasource": {
190
+ "type": "loki",
191
+ "uid": "loki"
192
+ },
193
+ "definition": "label_values({service_name!=\"\"}, service_name)",
194
+ "includeAll": true,
195
+ "label": "Service",
196
+ "multi": false,
197
+ "name": "service_name",
198
+ "options": [],
199
+ "query": "label_values({service_name!=\"\"}, service_name)",
200
+ "refresh": 2,
201
+ "skipUrlSync": false,
202
+ "type": "query",
203
+ "useTags": false,
204
+ "current": {
205
+ "text": "All services",
206
+ "value": ".*"
207
+ }
208
+ }
209
+ ]
210
+ },
211
+ "time": {
212
+ "from": "now-6h",
213
+ "to": "now"
214
+ },
215
+ "timepicker": {},
216
+ "timezone": "browser",
217
+ "title": "Logs overview",
218
+ "uid": "logs-overview",
219
+ "version": 1,
220
+ "weekStart": ""
221
+ }
@@ -0,0 +1,301 @@
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
+ "gnetId": null,
20
+ "graphTooltip": 0,
21
+ "id": null,
22
+ "links": [],
23
+ "liveNow": false,
24
+ "panels": [
25
+ {
26
+ "datasource": {
27
+ "type": "loki",
28
+ "uid": "loki"
29
+ },
30
+ "fieldConfig": {
31
+ "defaults": {
32
+ "custom": {},
33
+ "mappings": [],
34
+ "thresholds": {
35
+ "mode": "absolute",
36
+ "steps": [
37
+ {
38
+ "color": "green",
39
+ "value": null
40
+ }
41
+ ]
42
+ },
43
+ "unit": "short"
44
+ },
45
+ "overrides": []
46
+ },
47
+ "gridPos": {
48
+ "h": 8,
49
+ "w": 12,
50
+ "x": 0,
51
+ "y": 0
52
+ },
53
+ "id": 1,
54
+ "options": {
55
+ "legend": {
56
+ "displayMode": "list",
57
+ "placement": "bottom"
58
+ },
59
+ "tooltip": {
60
+ "mode": "single"
61
+ }
62
+ },
63
+ "targets": [
64
+ {
65
+ "datasource": {
66
+ "type": "loki",
67
+ "uid": "loki"
68
+ },
69
+ "expr": "sum(rate({service_name=~\"$service_name\"}[5m])) by (logger_name)",
70
+ "queryType": "range",
71
+ "refId": "A"
72
+ }
73
+ ],
74
+ "title": "Log rate by logger",
75
+ "type": "timeseries"
76
+ },
77
+ {
78
+ "datasource": {
79
+ "type": "loki",
80
+ "uid": "loki"
81
+ },
82
+ "fieldConfig": {
83
+ "defaults": {
84
+ "custom": {},
85
+ "mappings": [],
86
+ "thresholds": {
87
+ "mode": "absolute",
88
+ "steps": [
89
+ {
90
+ "color": "green",
91
+ "value": null
92
+ }
93
+ ]
94
+ }
95
+ },
96
+ "overrides": []
97
+ },
98
+ "gridPos": {
99
+ "h": 8,
100
+ "w": 12,
101
+ "x": 0,
102
+ "y": 8
103
+ },
104
+ "id": 2,
105
+ "options": {
106
+ "showHeader": true
107
+ },
108
+ "targets": [
109
+ {
110
+ "datasource": {
111
+ "type": "loki",
112
+ "uid": "loki"
113
+ },
114
+ "expr": "topk(10, sum by (logger_name) (count_over_time({service_name=~\"$service_name\"}[5m])))",
115
+ "queryType": "range",
116
+ "refId": "A"
117
+ }
118
+ ],
119
+ "title": "Top log namespaces",
120
+ "type": "table"
121
+ },
122
+ {
123
+ "datasource": {
124
+ "type": "loki",
125
+ "uid": "loki"
126
+ },
127
+ "fieldConfig": {
128
+ "defaults": {
129
+ "custom": {},
130
+ "mappings": [],
131
+ "unit": "percent"
132
+ },
133
+ "overrides": []
134
+ },
135
+ "gridPos": {
136
+ "h": 4,
137
+ "w": 12,
138
+ "x": 0,
139
+ "y": 16
140
+ },
141
+ "id": 3,
142
+ "options": {
143
+ "orientation": "horizontal",
144
+ "reduceOptions": {
145
+ "calcs": [
146
+ "mean"
147
+ ],
148
+ "fields": "",
149
+ "values": false
150
+ },
151
+ "textMode": "auto"
152
+ },
153
+ "targets": [
154
+ {
155
+ "datasource": {
156
+ "type": "loki",
157
+ "uid": "loki"
158
+ },
159
+ "expr": "sum(count_over_time({trace_id!=\"\", service_name=~\"$service_name\"}[5m])) / sum(count_over_time({service_name=~\"$service_name\"}[5m])) * 100",
160
+ "queryType": "range",
161
+ "refId": "A"
162
+ }
163
+ ],
164
+ "title": "Traced logs",
165
+ "type": "stat"
166
+ }
167
+ ,
168
+ {
169
+ "datasource": {
170
+ "type": "loki",
171
+ "uid": "loki"
172
+ },
173
+ "fieldConfig": {
174
+ "defaults": {
175
+ "custom": {},
176
+ "mappings": [],
177
+ "unit": "reqps"
178
+ },
179
+ "overrides": []
180
+ },
181
+ "gridPos": {
182
+ "h": 8,
183
+ "w": 12,
184
+ "x": 0,
185
+ "y": 20
186
+ },
187
+ "id": 4,
188
+ "options": {
189
+ "legend": {
190
+ "displayMode": "list",
191
+ "placement": "bottom"
192
+ },
193
+ "tooltip": {
194
+ "mode": "single"
195
+ }
196
+ },
197
+ "targets": [
198
+ {
199
+ "datasource": {
200
+ "type": "loki",
201
+ "uid": "loki"
202
+ },
203
+ "expr": "sum(rate({http.route!=\"\", service_name=~\"$service_name\"}[1m])) by (http.route)",
204
+ "queryType": "range",
205
+ "refId": "A"
206
+ }
207
+ ],
208
+ "title": "Request rate by route",
209
+ "type": "timeseries"
210
+ }
211
+ ,
212
+ {
213
+ "datasource": {
214
+ "type": "loki",
215
+ "uid": "loki"
216
+ },
217
+ "fieldConfig": {
218
+ "defaults": {
219
+ "custom": {},
220
+ "mappings": [],
221
+ "unit": "percent"
222
+ },
223
+ "overrides": []
224
+ },
225
+ "gridPos": {
226
+ "h": 4,
227
+ "w": 12,
228
+ "x": 0,
229
+ "y": 28
230
+ },
231
+ "id": 5,
232
+ "options": {
233
+ "orientation": "horizontal",
234
+ "reduceOptions": {
235
+ "calcs": [
236
+ "mean"
237
+ ],
238
+ "fields": "",
239
+ "values": false
240
+ },
241
+ "textMode": "auto"
242
+ },
243
+ "targets": [
244
+ {
245
+ "datasource": {
246
+ "type": "loki",
247
+ "uid": "loki"
248
+ },
249
+ "expr": "sum(count_over_time({cache.system!=\"\", cache.hit=\"true\", service_name=~\"$service_name\"}[5m])) / sum(count_over_time({cache.system!=\"\", service_name=~\"$service_name\"}[5m])) * 100",
250
+ "queryType": "range",
251
+ "refId": "A"
252
+ }
253
+ ],
254
+ "title": "Cache hit ratio",
255
+ "type": "stat"
256
+ }
257
+ ],
258
+ "refresh": "10s",
259
+ "schemaVersion": 38,
260
+ "style": "dark",
261
+ "tags": [
262
+ "service",
263
+ "telemetry"
264
+ ],
265
+ "templating": {
266
+ "list": [
267
+ {
268
+ "allValue": ".*",
269
+ "datasource": {
270
+ "type": "loki",
271
+ "uid": "loki"
272
+ },
273
+ "definition": "label_values({service_name!=\"\"}, service_name)",
274
+ "includeAll": true,
275
+ "label": "Service",
276
+ "multi": false,
277
+ "name": "service_name",
278
+ "options": [],
279
+ "query": "label_values({service_name!=\"\"}, service_name)",
280
+ "refresh": 2,
281
+ "skipUrlSync": false,
282
+ "type": "query",
283
+ "useTags": false,
284
+ "current": {
285
+ "text": "All services",
286
+ "value": ".*"
287
+ }
288
+ }
289
+ ]
290
+ },
291
+ "time": {
292
+ "from": "now-1h",
293
+ "to": "now"
294
+ },
295
+ "timepicker": {},
296
+ "timezone": "browser",
297
+ "title": "Service telemetry",
298
+ "uid": "service-telemetry",
299
+ "version": 1,
300
+ "weekStart": ""
301
+ }
@@ -1,6 +1,7 @@
1
1
  apiVersion: 1
2
2
  datasources:
3
3
  - name: Loki
4
+ uid: loki
4
5
  type: loki
5
6
  access: proxy
6
7
  orgId: 1
@@ -9,6 +10,7 @@ datasources:
9
10
  jsonData:
10
11
  min_refresh_interval: "5s"
11
12
  - name: Tempo
13
+ uid: tempo
12
14
  type: tempo
13
15
  access: proxy
14
16
  orgId: 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emeryld/obs-stack",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Docker Compose-based Grafana + Tempo + Loki + OpenTelemetry Collector stack",
5
5
  "type": "commonjs",
6
6
  "bin": {