@senad-d/observme 0.1.0
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/.env.example +57 -0
- package/CHANGELOG.md +52 -0
- package/LICENSE +21 -0
- package/ObservMe-Production-Docs/00-README.md +79 -0
- package/ObservMe-Production-Docs/01-requirements-and-scope.md +207 -0
- package/ObservMe-Production-Docs/02-reference-architecture.md +306 -0
- package/ObservMe-Production-Docs/03-pi-event-and-session-model.md +266 -0
- package/ObservMe-Production-Docs/04-telemetry-semantic-conventions.md +722 -0
- package/ObservMe-Production-Docs/05-otel-pipeline-and-collector.md +355 -0
- package/ObservMe-Production-Docs/06-security-privacy-redaction.md +294 -0
- package/ObservMe-Production-Docs/07-extension-implementation-blueprint.md +447 -0
- package/ObservMe-Production-Docs/08-query-grafana-integration.md +276 -0
- package/ObservMe-Production-Docs/09-dashboards-alerts-slos.md +640 -0
- package/ObservMe-Production-Docs/10-testing-release-operations.md +319 -0
- package/ObservMe-Production-Docs/11-deployment-runbooks.md +203 -0
- package/ObservMe-Production-Docs/12-configuration-reference.md +337 -0
- package/ObservMe-Production-Docs/13-source-notes.md +33 -0
- package/ObservMe-Production-Docs/pi-session-format.md +427 -0
- package/README.md +356 -0
- package/SECURITY.md +45 -0
- package/dashboards/observme-agent-node-graphs.json +250 -0
- package/dashboards/observme-agents.json +1880 -0
- package/dashboards/observme-alerts.yaml +113 -0
- package/dashboards/observme-branches-compactions.json +1042 -0
- package/dashboards/observme-cost.json +1254 -0
- package/dashboards/observme-errors.json +1659 -0
- package/dashboards/observme-export-health.json +1802 -0
- package/dashboards/observme-latency.json +1494 -0
- package/dashboards/observme-llm-conversations.json +730 -0
- package/dashboards/observme-logs-llm.json +644 -0
- package/dashboards/observme-models.json +933 -0
- package/dashboards/observme-overview.json +2129 -0
- package/dashboards/observme-slo-health.json +737 -0
- package/dashboards/observme-slos.yaml +56 -0
- package/dashboards/observme-tools.json +902 -0
- package/dashboards/observme-trace-journey.json +1793 -0
- package/docs/STRUCTURE.md +49 -0
- package/docs/agent-subagent-observability-requirements.md +997 -0
- package/docs/compatibility-matrix.md +39 -0
- package/docs/configuration-tui-design-standard.md +767 -0
- package/docs/configuration.md +38 -0
- package/docs/review-validation.md +115 -0
- package/docs/validation-flow.md +117 -0
- package/examples/collector.yaml +123 -0
- package/examples/observme.yaml +131 -0
- package/img/demo.gif +0 -0
- package/img/icon.svg +47 -0
- package/package.json +103 -0
- package/src/commands/obs-agents-runtime.ts +150 -0
- package/src/commands/obs-agents.ts +491 -0
- package/src/commands/obs-args.ts +63 -0
- package/src/commands/obs-backfill.ts +1334 -0
- package/src/commands/obs-command-support.ts +43 -0
- package/src/commands/obs-cost.ts +228 -0
- package/src/commands/obs-diagnostics.ts +22 -0
- package/src/commands/obs-errors.ts +156 -0
- package/src/commands/obs-health.ts +301 -0
- package/src/commands/obs-link.ts +90 -0
- package/src/commands/obs-logs.ts +194 -0
- package/src/commands/obs-loki-summary.ts +184 -0
- package/src/commands/obs-session.ts +259 -0
- package/src/commands/obs-status.ts +359 -0
- package/src/commands/obs-tools.ts +274 -0
- package/src/commands/obs-trace.ts +411 -0
- package/src/commands/obs.ts +211 -0
- package/src/config/bootstrap-project-config.ts +300 -0
- package/src/config/defaults.ts +143 -0
- package/src/config/load-config.ts +631 -0
- package/src/config/project-paths.ts +61 -0
- package/src/config/schema.ts +405 -0
- package/src/config/validate.ts +456 -0
- package/src/constants.ts +4 -0
- package/src/diagnostics/sanitize.ts +6 -0
- package/src/extension.ts +38 -0
- package/src/otel/logs.ts +160 -0
- package/src/otel/metrics.ts +165 -0
- package/src/otel/otlp-endpoint.ts +10 -0
- package/src/otel/sdk.ts +114 -0
- package/src/otel/shutdown.ts +102 -0
- package/src/otel/traces.ts +166 -0
- package/src/pi/agent-lineage.ts +378 -0
- package/src/pi/agent-tree-tracker.ts +258 -0
- package/src/pi/event-handlers/agent-turn.ts +155 -0
- package/src/pi/event-handlers/lifecycle.ts +642 -0
- package/src/pi/event-handlers/llm.ts +115 -0
- package/src/pi/event-handlers/session-events.ts +159 -0
- package/src/pi/event-handlers/tool-bash.ts +275 -0
- package/src/pi/handler-internals.ts +2154 -0
- package/src/pi/handler-runtime.ts +633 -0
- package/src/pi/handler-types.ts +261 -0
- package/src/pi/handlers.ts +75 -0
- package/src/pi/subagent-spawn.ts +975 -0
- package/src/pi/subagent-types.ts +29 -0
- package/src/privacy/content-capture.ts +104 -0
- package/src/privacy/hash.ts +93 -0
- package/src/privacy/redact.ts +619 -0
- package/src/privacy/secret-patterns.ts +185 -0
- package/src/privacy/truncate.ts +69 -0
- package/src/query/grafana-readiness.ts +164 -0
- package/src/query/grafana-transport.ts +481 -0
- package/src/query/grafana.ts +371 -0
- package/src/query/loki.ts +332 -0
- package/src/query/prometheus.ts +388 -0
- package/src/query/tempo.ts +332 -0
- package/src/safety/sensitive-input.ts +208 -0
- package/src/semconv/attributes.ts +279 -0
- package/src/semconv/metrics.ts +146 -0
- package/src/semconv/spans.ts +19 -0
- package/src/semconv/values.ts +13 -0
- package/src/util/bounded-map.ts +97 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# ObservMe Query and Grafana Integration
|
|
2
|
+
|
|
3
|
+
## 1. Purpose
|
|
4
|
+
|
|
5
|
+
ObservMe is primarily an emitter, but it should also help users query the observability stack from inside Pi. Query commands must be lightweight and optional.
|
|
6
|
+
|
|
7
|
+
## 2. Query Architecture
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
Pi /obs command
|
|
11
|
+
-> ObservMe query client
|
|
12
|
+
-> Grafana API
|
|
13
|
+
-> Tempo API
|
|
14
|
+
-> Loki API
|
|
15
|
+
-> Prometheus/Mimir API
|
|
16
|
+
-> Agent lineage queries (Tempo/Loki)
|
|
17
|
+
-> Render concise result in Pi TUI
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Preferred integration is Grafana API because Grafana already knows all datasources and provides stable links.
|
|
21
|
+
|
|
22
|
+
## 3. Configuration
|
|
23
|
+
|
|
24
|
+
```yaml
|
|
25
|
+
query:
|
|
26
|
+
enabled: true
|
|
27
|
+
grafana:
|
|
28
|
+
url: https://grafana.example.com
|
|
29
|
+
token: ${OBSERVME_GRAFANA_TOKEN}
|
|
30
|
+
username: ""
|
|
31
|
+
password: ""
|
|
32
|
+
datasourceUids:
|
|
33
|
+
tempo: tempo
|
|
34
|
+
loki: loki
|
|
35
|
+
prometheus: mimir
|
|
36
|
+
tls:
|
|
37
|
+
insecureSkipVerify: false
|
|
38
|
+
transport:
|
|
39
|
+
preferIPv4: false
|
|
40
|
+
links:
|
|
41
|
+
traceUrlTemplate: "https://grafana.example.com/explore?left=..."
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Authentication and local transport behavior:
|
|
45
|
+
|
|
46
|
+
- Prefer `query.grafana.token` for Grafana service-account or bearer tokens.
|
|
47
|
+
- If the token is blank or an unresolved environment placeholder, ObservMe may use `query.grafana.username` plus `query.grafana.password` as a local-development Basic auth fallback.
|
|
48
|
+
- Query-backed commands fail fast before backend calls when Grafana auth is unresolved/missing/incomplete, `query.grafana.url` is invalid, or a required datasource UID is blank.
|
|
49
|
+
- `401` and `403` responses are surfaced as Grafana authentication failures without printing token or password values.
|
|
50
|
+
- Browser login cookies are irrelevant because `/obs` commands call the Grafana API directly from the Pi process.
|
|
51
|
+
|
|
52
|
+
Bundled local-stack profile:
|
|
53
|
+
|
|
54
|
+
```yaml
|
|
55
|
+
query:
|
|
56
|
+
enabled: true
|
|
57
|
+
links:
|
|
58
|
+
traceUrlTemplate: https://observability.local/explore?left=...
|
|
59
|
+
grafana:
|
|
60
|
+
url: https://observability.local
|
|
61
|
+
token: ${OBSERVME_GRAFANA_TOKEN}
|
|
62
|
+
username: admin
|
|
63
|
+
password: ${OBSERVME_GRAFANA_PASSWORD}
|
|
64
|
+
datasourceUids:
|
|
65
|
+
tempo: tempo
|
|
66
|
+
loki: loki
|
|
67
|
+
prometheus: prometheus
|
|
68
|
+
tls:
|
|
69
|
+
insecureSkipVerify: true
|
|
70
|
+
transport:
|
|
71
|
+
preferIPv4: true
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
For the bundled `observability-stack/`, the supported command path is nginx HTTPS at `https://observability.local`; the default stack does not publish Grafana on `localhost:3000`. Create a Grafana service-account token with Viewer access for read-only datasource queries and export it as `OBSERVME_GRAFANA_TOKEN`, or export/set `OBSERVME_GRAFANA_PASSWORD` from `observability-stack/secrets/grafana_admin_password` for local Basic auth. Extension environment values can come from system environment variables before Pi starts, or from a trusted project `.env` copied from `.env.example`; system variables override `.env`. The local self-signed certificate requires `query.grafana.tls.insecureSkipVerify=true`, and `query.grafana.transport.preferIPv4=true` avoids DNS stalls when `observability.local` resolves to IPv6 first. Provisioned datasource UIDs are `tempo`, `loki`, and `prometheus`; Loki selectors use normalized labels such as `service_name`, `pi_session_id`, `event_name`, and `event_category`.
|
|
75
|
+
|
|
76
|
+
## 4. Commands
|
|
77
|
+
|
|
78
|
+
### `/obs status`
|
|
79
|
+
|
|
80
|
+
Shows local ObservMe state.
|
|
81
|
+
|
|
82
|
+
Output:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
ObservMe: enabled
|
|
86
|
+
OTLP endpoint: https://otel.example.com:4318
|
|
87
|
+
Traces: enabled
|
|
88
|
+
Metrics: enabled
|
|
89
|
+
Logs: enabled
|
|
90
|
+
Prompt capture: disabled
|
|
91
|
+
Queue drops: 0
|
|
92
|
+
Last export error: none
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### `/obs health`
|
|
96
|
+
|
|
97
|
+
Checks Collector and Grafana reachability, and reports Grafana query auth/config readiness before datasource calls.
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
Collector: reachable
|
|
101
|
+
Grafana: reachable
|
|
102
|
+
Tempo datasource: ok
|
|
103
|
+
Loki datasource: ok
|
|
104
|
+
Metrics datasource: ok
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### `/obs session`
|
|
108
|
+
|
|
109
|
+
Shows current session telemetry summary.
|
|
110
|
+
|
|
111
|
+
```text
|
|
112
|
+
Session: 8ddf...
|
|
113
|
+
Trace: 4bf92f...
|
|
114
|
+
Turns: 12
|
|
115
|
+
LLM calls: 18
|
|
116
|
+
Tool calls: 35
|
|
117
|
+
Cost: $1.42
|
|
118
|
+
Open trace: https://grafana.example.com/...
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### `/obs trace`
|
|
122
|
+
|
|
123
|
+
Returns a Grafana Tempo trace link. For the current active session, the link is available from runtime state before shutdown. Tempo may show ended child spans before the long-lived root `pi.session` span appears; the root is exported after `session_shutdown`.
|
|
124
|
+
|
|
125
|
+
Options:
|
|
126
|
+
|
|
127
|
+
```text
|
|
128
|
+
/obs trace
|
|
129
|
+
/obs trace --last-turn
|
|
130
|
+
/obs trace --session <session-id>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### `/obs cost`
|
|
134
|
+
|
|
135
|
+
Queries Prometheus/Mimir.
|
|
136
|
+
|
|
137
|
+
PromQL example for aggregate cost:
|
|
138
|
+
|
|
139
|
+
```promql
|
|
140
|
+
sum(increase(observme_llm_cost_usd_total[24h])) by (model, provider)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Session-scoped metric query, only for deployments that explicitly promote session IDs to metric labels:
|
|
144
|
+
|
|
145
|
+
```promql
|
|
146
|
+
sum(increase(observme_llm_cost_usd_total{pi_session_id="$session"}[24h])) by (model, provider)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Because `session_id` is high cardinality, session-scoped metric queries should be disabled by default. The safer default is querying trace/log attributes for the current session.
|
|
150
|
+
|
|
151
|
+
### `/obs agents`
|
|
152
|
+
|
|
153
|
+
Shows the current workflow/agent identity and, when query integration is enabled, recent parent/child relationships, depth, fan-out, orphan, and critical-path hints.
|
|
154
|
+
|
|
155
|
+
Output:
|
|
156
|
+
|
|
157
|
+
```text
|
|
158
|
+
Workflow: 91ce... root=2f4c...
|
|
159
|
+
Agent: 2f4c... (orchestrator depth=0)
|
|
160
|
+
Session: 8ddf...
|
|
161
|
+
Subagents spawned in current trace: 3
|
|
162
|
+
Current tree: depth=2 width=4 active=1 orphaned=0
|
|
163
|
+
Latest child: 7a91... status=ok cost=$0.18 join=1.2s
|
|
164
|
+
Open lineage trace: https://grafana.example.com/...
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
PromQL aggregate examples must use only low-cardinality labels:
|
|
168
|
+
|
|
169
|
+
```promql
|
|
170
|
+
sum(rate(observme_subagents_spawned_total[1h])) by (agent_role, subagent_depth, spawn_type, spawn_reason)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
```promql
|
|
174
|
+
histogram_quantile(0.95, sum(rate(observme_agent_fanout_count_bucket[1h])) by (subagent_depth, le))
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
```promql
|
|
178
|
+
sum(rate(observme_orphan_agents_total[1h])) by (agent_role, subagent_depth)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Per-agent and per-workflow drill-down should use Tempo/Loki attributes such as `pi_workflow_id`, `pi_agent_id`, `pi_agent_parent_id`, and trace/span IDs, not Prometheus labels.
|
|
182
|
+
|
|
183
|
+
### `/obs tools`
|
|
184
|
+
|
|
185
|
+
PromQL:
|
|
186
|
+
|
|
187
|
+
```promql
|
|
188
|
+
topk(10, sum(rate(observme_tool_calls_total[1h])) by (tool_name))
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Failures:
|
|
192
|
+
|
|
193
|
+
```promql
|
|
194
|
+
sum(rate(observme_tool_failures_total[1h])) by (tool_name, error_class)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### `/obs errors`
|
|
198
|
+
|
|
199
|
+
Loki LogQL:
|
|
200
|
+
|
|
201
|
+
```logql
|
|
202
|
+
{service_name="observme-pi-extension", event_name=~".*[.]failed|.*[.]dropped|agent[.]orphaned"}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
With Loki OTLP ingestion, OTel attribute dots are normalized to underscores (`event.name` -> `event_name`, `pi.session.id` -> `pi_session_id`). `event.category` remains a semantic category such as `lifecycle`, `agent-tree`, or `compaction`; use `event_name` for failure/error selectors. Use `| json` only when the log body itself is JSON; default ObservMe event fields should be OTEL log attributes/structured metadata.
|
|
206
|
+
|
|
207
|
+
### `/obs logs`
|
|
208
|
+
|
|
209
|
+
Loki LogQL for current session:
|
|
210
|
+
|
|
211
|
+
```logql
|
|
212
|
+
{service_name="observme-pi-extension", pi_session_id="$session"}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Only available if Loki receives `pi.session.id` as structured metadata or label.
|
|
216
|
+
|
|
217
|
+
## 5. Trace Links
|
|
218
|
+
|
|
219
|
+
If trace id is available:
|
|
220
|
+
|
|
221
|
+
```text
|
|
222
|
+
https://grafana.example.com/explore?schemaVersion=1&panes=...
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
ObservMe should support configurable URL templates because Grafana URL encoding changes across versions and organizations.
|
|
226
|
+
|
|
227
|
+
## 6. Grafana Query Abstraction
|
|
228
|
+
|
|
229
|
+
Interface:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
interface ObservabilityQueryClient {
|
|
233
|
+
health(): Promise<HealthResult>;
|
|
234
|
+
getTraceLink(traceId: string): string;
|
|
235
|
+
queryPrometheus(query: string, time?: Date): Promise<QueryResult>;
|
|
236
|
+
queryLoki(query: string, range: TimeRange): Promise<LogResult[]>;
|
|
237
|
+
searchTempo(attrs: Record<string, string>, range: TimeRange): Promise<TraceSummary[]>;
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## 7. Safe Query Rules
|
|
242
|
+
|
|
243
|
+
- Never send raw prompts as query strings.
|
|
244
|
+
- Prefer session id, trace id, generated workflow id, generated agent id, and hashed fields.
|
|
245
|
+
- Do not query raw prompts, raw commands, raw paths, or inherited subagent environment values.
|
|
246
|
+
- Apply max result limits.
|
|
247
|
+
- Apply query timeouts.
|
|
248
|
+
- Render summaries, not huge raw logs.
|
|
249
|
+
|
|
250
|
+
Defaults:
|
|
251
|
+
|
|
252
|
+
```yaml
|
|
253
|
+
query:
|
|
254
|
+
timeoutMs: 5000
|
|
255
|
+
maxLogs: 50
|
|
256
|
+
maxTraces: 20
|
|
257
|
+
maxMetricSeries: 20
|
|
258
|
+
maxAgents: 20
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## 8. Dependency Direction
|
|
262
|
+
|
|
263
|
+
ObservMe telemetry emission must not depend on Grafana query availability.
|
|
264
|
+
|
|
265
|
+
Bad:
|
|
266
|
+
|
|
267
|
+
```text
|
|
268
|
+
Pi event -> Grafana query -> emit telemetry
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Good:
|
|
272
|
+
|
|
273
|
+
```text
|
|
274
|
+
Pi event -> emit telemetry
|
|
275
|
+
/obs command -> optional query
|
|
276
|
+
```
|