@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.
Files changed (111) hide show
  1. package/.env.example +57 -0
  2. package/CHANGELOG.md +52 -0
  3. package/LICENSE +21 -0
  4. package/ObservMe-Production-Docs/00-README.md +79 -0
  5. package/ObservMe-Production-Docs/01-requirements-and-scope.md +207 -0
  6. package/ObservMe-Production-Docs/02-reference-architecture.md +306 -0
  7. package/ObservMe-Production-Docs/03-pi-event-and-session-model.md +266 -0
  8. package/ObservMe-Production-Docs/04-telemetry-semantic-conventions.md +722 -0
  9. package/ObservMe-Production-Docs/05-otel-pipeline-and-collector.md +355 -0
  10. package/ObservMe-Production-Docs/06-security-privacy-redaction.md +294 -0
  11. package/ObservMe-Production-Docs/07-extension-implementation-blueprint.md +447 -0
  12. package/ObservMe-Production-Docs/08-query-grafana-integration.md +276 -0
  13. package/ObservMe-Production-Docs/09-dashboards-alerts-slos.md +640 -0
  14. package/ObservMe-Production-Docs/10-testing-release-operations.md +319 -0
  15. package/ObservMe-Production-Docs/11-deployment-runbooks.md +203 -0
  16. package/ObservMe-Production-Docs/12-configuration-reference.md +337 -0
  17. package/ObservMe-Production-Docs/13-source-notes.md +33 -0
  18. package/ObservMe-Production-Docs/pi-session-format.md +427 -0
  19. package/README.md +356 -0
  20. package/SECURITY.md +45 -0
  21. package/dashboards/observme-agent-node-graphs.json +250 -0
  22. package/dashboards/observme-agents.json +1880 -0
  23. package/dashboards/observme-alerts.yaml +113 -0
  24. package/dashboards/observme-branches-compactions.json +1042 -0
  25. package/dashboards/observme-cost.json +1254 -0
  26. package/dashboards/observme-errors.json +1659 -0
  27. package/dashboards/observme-export-health.json +1802 -0
  28. package/dashboards/observme-latency.json +1494 -0
  29. package/dashboards/observme-llm-conversations.json +730 -0
  30. package/dashboards/observme-logs-llm.json +644 -0
  31. package/dashboards/observme-models.json +933 -0
  32. package/dashboards/observme-overview.json +2129 -0
  33. package/dashboards/observme-slo-health.json +737 -0
  34. package/dashboards/observme-slos.yaml +56 -0
  35. package/dashboards/observme-tools.json +902 -0
  36. package/dashboards/observme-trace-journey.json +1793 -0
  37. package/docs/STRUCTURE.md +49 -0
  38. package/docs/agent-subagent-observability-requirements.md +997 -0
  39. package/docs/compatibility-matrix.md +39 -0
  40. package/docs/configuration-tui-design-standard.md +767 -0
  41. package/docs/configuration.md +38 -0
  42. package/docs/review-validation.md +115 -0
  43. package/docs/validation-flow.md +117 -0
  44. package/examples/collector.yaml +123 -0
  45. package/examples/observme.yaml +131 -0
  46. package/img/demo.gif +0 -0
  47. package/img/icon.svg +47 -0
  48. package/package.json +103 -0
  49. package/src/commands/obs-agents-runtime.ts +150 -0
  50. package/src/commands/obs-agents.ts +491 -0
  51. package/src/commands/obs-args.ts +63 -0
  52. package/src/commands/obs-backfill.ts +1334 -0
  53. package/src/commands/obs-command-support.ts +43 -0
  54. package/src/commands/obs-cost.ts +228 -0
  55. package/src/commands/obs-diagnostics.ts +22 -0
  56. package/src/commands/obs-errors.ts +156 -0
  57. package/src/commands/obs-health.ts +301 -0
  58. package/src/commands/obs-link.ts +90 -0
  59. package/src/commands/obs-logs.ts +194 -0
  60. package/src/commands/obs-loki-summary.ts +184 -0
  61. package/src/commands/obs-session.ts +259 -0
  62. package/src/commands/obs-status.ts +359 -0
  63. package/src/commands/obs-tools.ts +274 -0
  64. package/src/commands/obs-trace.ts +411 -0
  65. package/src/commands/obs.ts +211 -0
  66. package/src/config/bootstrap-project-config.ts +300 -0
  67. package/src/config/defaults.ts +143 -0
  68. package/src/config/load-config.ts +631 -0
  69. package/src/config/project-paths.ts +61 -0
  70. package/src/config/schema.ts +405 -0
  71. package/src/config/validate.ts +456 -0
  72. package/src/constants.ts +4 -0
  73. package/src/diagnostics/sanitize.ts +6 -0
  74. package/src/extension.ts +38 -0
  75. package/src/otel/logs.ts +160 -0
  76. package/src/otel/metrics.ts +165 -0
  77. package/src/otel/otlp-endpoint.ts +10 -0
  78. package/src/otel/sdk.ts +114 -0
  79. package/src/otel/shutdown.ts +102 -0
  80. package/src/otel/traces.ts +166 -0
  81. package/src/pi/agent-lineage.ts +378 -0
  82. package/src/pi/agent-tree-tracker.ts +258 -0
  83. package/src/pi/event-handlers/agent-turn.ts +155 -0
  84. package/src/pi/event-handlers/lifecycle.ts +642 -0
  85. package/src/pi/event-handlers/llm.ts +115 -0
  86. package/src/pi/event-handlers/session-events.ts +159 -0
  87. package/src/pi/event-handlers/tool-bash.ts +275 -0
  88. package/src/pi/handler-internals.ts +2154 -0
  89. package/src/pi/handler-runtime.ts +633 -0
  90. package/src/pi/handler-types.ts +261 -0
  91. package/src/pi/handlers.ts +75 -0
  92. package/src/pi/subagent-spawn.ts +975 -0
  93. package/src/pi/subagent-types.ts +29 -0
  94. package/src/privacy/content-capture.ts +104 -0
  95. package/src/privacy/hash.ts +93 -0
  96. package/src/privacy/redact.ts +619 -0
  97. package/src/privacy/secret-patterns.ts +185 -0
  98. package/src/privacy/truncate.ts +69 -0
  99. package/src/query/grafana-readiness.ts +164 -0
  100. package/src/query/grafana-transport.ts +481 -0
  101. package/src/query/grafana.ts +371 -0
  102. package/src/query/loki.ts +332 -0
  103. package/src/query/prometheus.ts +388 -0
  104. package/src/query/tempo.ts +332 -0
  105. package/src/safety/sensitive-input.ts +208 -0
  106. package/src/semconv/attributes.ts +279 -0
  107. package/src/semconv/metrics.ts +146 -0
  108. package/src/semconv/spans.ts +19 -0
  109. package/src/semconv/values.ts +13 -0
  110. package/src/util/bounded-map.ts +97 -0
  111. package/tsconfig.json +15 -0
@@ -0,0 +1,640 @@
1
+ # ObservMe Dashboards, Alerts, and SLOs
2
+
3
+ ## 1. Dashboard Pack
4
+
5
+ ObservMe ships Grafana dashboards as JSON files:
6
+
7
+ ```text
8
+ dashboards/
9
+ ├── observme-overview.json
10
+ ├── observme-slo-health.json
11
+ ├── observme-export-health.json
12
+ ├── observme-trace-journey.json
13
+ ├── observme-agents.json
14
+ ├── observme-agent-node-graphs.json
15
+ ├── observme-cost.json
16
+ ├── observme-models.json
17
+ ├── observme-latency.json
18
+ ├── observme-tools.json
19
+ ├── observme-errors.json
20
+ ├── observme-logs-llm.json
21
+ ├── observme-llm-conversations.json
22
+ └── observme-branches-compactions.json
23
+ ```
24
+
25
+ ## 1.1 Dashboard Map
26
+
27
+ | Dashboard | Primary question answered | Typical next drill-down |
28
+ |---|---|---|
29
+ | `ObservMe Overview` | Is ObservMe healthy, is workload normal, are agents/subagents healthy, and are cost or latency elevated? | Open the linked SLO Health, Export Health, Trace Journey, Cost, Models, Latency, Tools, Agents, Errors, or LLM Conversations dashboard with the same time range. |
30
+ | `ObservMe SLO Health` | Which SLO is burning budget or near an alert threshold? | Export Health for telemetry-path inputs, Agents/Trace Journey for lineage, Errors for failed workflows, or Latency for handler overhead. |
31
+ | `ObservMe Export Health` | Is the telemetry/export path trustworthy, idle, dropped, redacting, or failing? | Failure-only Loki tables, SLO Health, and `/obs health` for backend reachability. |
32
+ | `ObservMe Trace Journey` | How did one session/agent/workflow move through turns, LLM calls, tools, bash, subagent spawns, waits, joins, logs, and Tempo traces? | Filtered LLM Conversations, Agents, Errors, Tools, or Tempo trace waterfall. |
33
+ | `ObservMe Agents and Subagents` | Are subagents spawning, failing, waiting, joining, becoming orphaned, or losing trace context? | Agent Node Graphs for aggregate topology, Trace Journey for per-run logs/traces, and SLO Health for lineage budget. |
34
+ | `ObservMe Agent Node Graphs` | What aggregate root/role/depth/spawn topology and health shape exists in the selected range? | Agents for ratios/top offenders and Trace Journey for per-execution investigation. |
35
+ | `ObservMe Cost` | Which providers/models/environments and token/cache patterns are driving spend and burn rate? | Models, Logs and LLM I/O, LLM Conversations, and Trace Journey. |
36
+ | `ObservMe Models` | How do provider/model traffic, errors, latency, stop reasons, and cost efficiency compare? | Cost, Latency, Logs and LLM I/O, and trace/log rows for representative requests. |
37
+ | `ObservMe Latency` | Which stage, provider/model, tool, or agent role is slow after accounting for volume? | Trace Journey, Models, Tools, Agents, and Errors. |
38
+ | `ObservMe Tools` | Which tools are busy, slow, failing, or producing large results? | Errors, Trace Journey, and filtered `tool.call.failed` logs. |
39
+ | `ObservMe Errors` | Which error family is pressuring reliability and what logs/traces explain it? | Export Health, Tools, Models, Agents, Trace Journey, and Tempo trace rows. |
40
+ | `ObservMe Logs and LLM I/O` | What LLM lifecycle logs, token trends, and prompt/response size trends exist without duplicating the content timeline? | LLM Conversations for redacted content and Trace Journey/Tempo for execution context. |
41
+ | `ObservMe LLM Conversations` | What redacted opt-in prompts, responses, thinking, and trace links belong to one session/workflow/agent/run? | Trace Journey and Tempo traces. |
42
+ | `ObservMe Branches and Compactions` | Did branch, compaction, model, or thinking-level changes explain cost/latency shifts? | Cost, Models, Latency, and Logs and LLM I/O. |
43
+
44
+ ## 1.2 Shared Dashboard UX Conventions
45
+
46
+ New or changed dashboards must use the same variable names, row names, link patterns, and status colors so users can move from overview panels to domain drill-downs without relearning each dashboard.
47
+
48
+ ### Standard variables
49
+
50
+ Use these exact variable names and display labels when a dashboard supports the dimension. Prometheus variables must stay low-cardinality; high-cardinality identifiers are allowed only in Loki/Tempo drill-downs.
51
+
52
+ | Variable | Display label | Datasource scope | Backing label/attribute | Use |
53
+ |---|---|---|---|---|
54
+ | `environment` | Environment | Prometheus; mixed only if the log/trace backend exposes the same bounded value | `environment` metric label; `deployment.environment.name`/`observme.environment` attribute | Fleet, stage, or local/CI/prod filtering. |
55
+ | `provider` | Provider | Prometheus; Loki for LLM lifecycle/content dashboards when promoted | `provider` metric label; `gen_ai_provider_name` Loki label | LLM traffic, latency, error, token, cost, and content-log filtering. |
56
+ | `model` | Model | Prometheus; Loki for LLM lifecycle/content dashboards when promoted | `model` metric label; `gen_ai_request_model` Loki label | Provider/model comparison; keep values provider-reported and bounded by active use. |
57
+ | `tool_name` | Tool | Prometheus | `tool_name` metric label | Tool workload, latency, and failure panels. |
58
+ | `agent_role` | Agent role | Prometheus; Tempo where attributes are searchable | `agent_role` metric label; `pi.agent.role` attribute if emitted | Root/subagent/orchestrator/worker/reviewer comparison. |
59
+ | `agent_capability` | Agent capability | Prometheus only after verifying the value set is bounded; Tempo otherwise | `agent_capability` metric label; `pi.agent.capability` attribute if emitted | Capability-level aggregate panels without agent IDs. |
60
+ | `subagent_depth` | Subagent depth | Prometheus; Tempo where attributes are searchable | `subagent_depth` metric label; `pi.agent.depth` attribute if emitted | Depth/fan-out/orphan/propagation diagnostics. |
61
+ | `spawn_reason` | Spawn reason | Prometheus | `spawn_reason` metric label | Delegation and fan-out cause analysis. |
62
+ | `session_id` | Session ID | Loki/Tempo only | `pi_session_id` Loki label; `pi.session.id` Tempo/span attribute | Follow one session across logs and traces. Never use in PromQL. |
63
+ | `agent_id` | Agent ID | Loki/Tempo only | `pi_agent_id` Loki label; `pi.agent.id` Tempo/span attribute | Follow one root agent or subagent. Never use in PromQL. |
64
+ | `agent_run_id` | Agent run ID | Loki/Tempo only | `pi_agent_run_id` Loki label; `pi.agent.run.id` Tempo/span attribute | Follow one execution attempt. Never use in PromQL. |
65
+ | `workflow_id` | Workflow ID | Optional Loki/Tempo only where the backend exposes it | `pi_workflow_id` Loki label; `pi.workflow.id` Tempo/span attribute | Follow a multi-agent workflow. Never use in PromQL. |
66
+ | `content_kind` | Content kind | Loki only | `pi_llm_content_kind` Loki label | Filter redacted opt-in prompt, response, thinking, or lifecycle content views. Never use raw content values. |
67
+
68
+ Variable scope rules:
69
+
70
+ - Prometheus-primary: `provider`, `model`, `tool_name`, `spawn_reason`, and any low-cardinality `agent_capability` use; `provider` and `model` may also be Loki variables on LLM lifecycle/content dashboards when the Collector promotes bounded GenAI labels.
71
+ - Loki-only: `content_kind` and any other log-only variable whose backing label is promoted by the local Collector and used only by log panels.
72
+ - Tempo-only: none by default; use trace attributes and row-level links instead of global trace identifiers unless a dashboard is specifically trace-search-only.
73
+ - Mixed: `environment`, `agent_role`, and `subagent_depth` only when every datasource exposes bounded equivalent values.
74
+ - Loki/Tempo-only high-cardinality drill-downs: `session_id`, `agent_id`, `agent_run_id`, and `workflow_id`; these identify individual executions and must never be used in PromQL.
75
+
76
+ ### Standard row names
77
+
78
+ Use these row names consistently and only add domain-specific rows when the dashboard needs additional detail:
79
+
80
+ - `Health`: top-level status, no-data/idle hints, alert state, and failure chips.
81
+ - `Workload`: sessions, turns, requests, tool calls, spawns, and throughput.
82
+ - `Cost`: spend, burn rate, tokens, cache/reasoning usage, and efficiency.
83
+ - `Latency`: p50/p95/p99, stage attribution, and slow-offender tables.
84
+ - `Agent lineage`: root/subagent health, fan-out, depth, orphan, propagation, wait, and join behavior.
85
+ - `Logs`: Loki drill-down tables or log panels with parsed labels and empty-state descriptions.
86
+ - `Traces`: Tempo trace search, trace waterfall entry points, and trace-navigation help.
87
+ - `SLOs`: SLO attainment, burn rates, error budget, and alert-threshold context.
88
+
89
+ ### Drill-down and data-link patterns
90
+
91
+ Preserve the dashboard time range on all drill-down links using Grafana time macros such as `${__url_time_range}` or explicit `from=${__from}&to=${__to}` parameters. Prometheus panels should link to domain dashboards with low-cardinality variables first, then to Loki/Tempo views for per-execution context.
92
+
93
+ Required link patterns for new or changed panels:
94
+
95
+ - Overview health/SLO panels link to Export Health, Errors, SLO Health when present, and Trace Journey.
96
+ - LLM, model, token, and cost panels link to Models, Cost, Logs and LLM I/O, LLM Conversations, and Tempo traces when a trace ID or session/run filter is available.
97
+ - Tool latency/error panels link to Tools, Errors, filtered `tool.call.failed` Loki rows, and Tempo traces.
98
+ - Agent lineage panels link to Agents, Agent Node Graphs, Trace Journey, filtered `event_category="agent-tree"` Loki rows, and Tempo traces.
99
+ - Export/redaction/drop panels link to Export Health, failure logs, and the relevant SLO/alert context.
100
+ - Loki rows should expose a Tempo link from `trace_id`/`span_id` when available; otherwise they should link back to Trace Journey using `session_id`, `agent_id`, and `agent_run_id` filters.
101
+
102
+ Do not place raw prompt, response, command, path, or raw error-message values into dashboard URLs. Prometheus links may pass only low-cardinality labels; high-cardinality values must originate from Loki/Tempo labels or trace/log fields.
103
+
104
+ ### Threshold colors and empty states
105
+
106
+ Use consistent threshold colors:
107
+
108
+ | State | Color | Meaning |
109
+ |---|---|---|
110
+ | Healthy | Green | Within objective or zero failures for the selected range. |
111
+ | Warning | Yellow/Orange | Degraded trend, non-zero recoverable failures, elevated burn, or approaching an alert threshold. |
112
+ | Critical | Red | Active alert condition, redaction failure, export drop/error, lineage break, or SLO violation. |
113
+ | Idle/no data | Gray/Blue | No workload or optional capture disabled; panel description must explain why this can be healthy. |
114
+
115
+ Every failure-only log panel must state that an empty table means no matching failures were observed in the selected range. Every zero-safe Prometheus stat that uses `or vector(0)` must explain whether zero means healthy idle, no events yet, or an actual zero failure rate. Content-capture dashboards must state that prompts, responses, and thinking logs are redacted and opt-in.
116
+
117
+ ### Operator drill-down workflows
118
+
119
+ Use the dashboards as a guided investigation path instead of opening raw metric families randomly:
120
+
121
+ 1. **General health:** start in Overview, inspect the `Health` row, then follow the panel link to SLO Health, Export Health, Errors, or Trace Journey. Keep `${__url_time_range}` on all links.
122
+ 2. **Multi-agent lineage:** start in Overview or Trace Journey, copy/filter by `session_id`, `workflow_id`, `agent_id`, or `agent_run_id` only in Loki/Tempo dashboards, then use Agents and Agent Node Graphs for aggregate ratios and topology.
123
+ 3. **Cost/model changes:** start in Cost or Models, compare burn rate, token mix, cache/reasoning usage, stop reasons, and model/thinking annotations, then use Logs and LLM I/O or LLM Conversations for per-run context.
124
+ 4. **Latency/tool/error:** start in Latency, Tools, or Errors, use top-offender tables that pair percentile/rate with volume, and open linked Loki rows or Tempo traces for representative executions.
125
+ 5. **Export trust:** if panels are blank or suspicious, inspect Export Health before interpreting product dashboards; an idle range can be healthy, but drops, export errors, redaction failures, handler errors, or propagation failures should be visible as non-green chips or failure logs.
126
+
127
+ Zero-state interpretation checklist:
128
+
129
+ - Empty failure-only Loki tables mean no matching failures in the selected range, not that the log pipeline is broken.
130
+ - `or vector(0)` stats must say whether zero means healthy idle/no activity or a true zero failure ratio.
131
+ - Optional redacted content panels can be empty when capture is disabled or when the Collector dropped content attributes by policy.
132
+ - Active-session estimates are approximate across process restarts/counter resets; `observme_active_agents` is the authoritative active agent gauge.
133
+ - High-cardinality execution identifiers are allowed as Loki/Tempo filter variables only and must never be introduced into Prometheus queries or panel links from aggregate panels.
134
+
135
+ ## 2. Overview Dashboard
136
+
137
+ Purpose: act as the operator landing page. Users should be able to answer whether ObservMe is healthy, workload is normal, agents/subagents are healthy, spend or latency is high, and which focused dashboard to open next without scanning every raw metric series.
138
+
139
+ Rows and panels:
140
+
141
+ - `Health`: SLO/health chips for `Export health`, `Agent lineage health`, `Workflow completion health`, `Error pressure`, `Cost burn / hour`, and `Latency health`.
142
+ - `Workload`: compact KPI stats with sparklines for `Active sessions estimate`, `Turns/min`, `LLM requests/min`, `Tool calls/min`, `Subagent spawns/min`, and `Active agents`.
143
+ - `Cost`: selected-range `Total cost`, `Token mix`, and aggregate `Cost trend` without provider/model detail.
144
+ - `Latency`: compact p95 sparkline stats for turn, LLM, and tool latency.
145
+ - `Agent lineage`: selected-range `Lineage failures`, p95 tree depth, p95 fan-out, and current active agents by bounded role/depth labels.
146
+ - `Links`: navigation to Cost, Models, Latency, Tools, Agents, Trace Journey, Errors, Export Health, and LLM Conversations with the current time range preserved.
147
+
148
+ The overview intentionally keeps only landing-page signals. Provider/model, tool, error-family, export, and full trace/log details belong on the domain dashboards linked from the row or panel links.
149
+
150
+ PromQL examples:
151
+
152
+ Export health chip:
153
+
154
+ ```promql
155
+ 1 - ((sum(rate(observme_telemetry_dropped_total[$__range])) or vector(0)) / clamp_min((sum(rate(observme_events_observed_total[$__range])) or vector(0)), 1e-9))
156
+ ```
157
+
158
+ Agent lineage health chip:
159
+
160
+ ```promql
161
+ clamp_min(1 - (((sum(rate(observme_subagent_spawn_failures_total[$__range])) or vector(0)) + (sum(rate(observme_orphan_agents_total[$__range])) or vector(0)) + (sum(rate(observme_trace_context_propagation_failures_total[$__range])) or vector(0))) / clamp_min((sum(rate(observme_subagents_spawned_total[$__range])) or vector(0)), 1e-9)), 0)
162
+ ```
163
+
164
+ Active sessions estimate:
165
+
166
+ ```promql
167
+ clamp_min((sum(observme_sessions_started_total) or vector(0)) - (sum(observme_sessions_shutdown_total) or vector(0)), 0)
168
+ ```
169
+
170
+ Use the `or vector(0)` fallbacks for session lifecycle panels because fresh active sessions can exist before any shutdown counter series has been exported. The overview describes this panel as an estimate because process restarts and counter resets can affect the value.
171
+
172
+ Compact workload stats:
173
+
174
+ ```promql
175
+ 60 * (sum(rate(observme_turns_completed_total[$__rate_interval])) or vector(0))
176
+ ```
177
+
178
+ ```promql
179
+ 60 * (sum(rate(observme_subagents_spawned_total[$__rate_interval])) or vector(0))
180
+ ```
181
+
182
+ Agent fan-out p95:
183
+
184
+ ```promql
185
+ histogram_quantile(0.95, sum(rate(observme_agent_fanout_count_bucket[$__rate_interval])) by (le)) or vector(0)
186
+ ```
187
+
188
+ Dashboard links must preserve the current time range with `${__url_time_range}` and must not include high-cardinality IDs or raw content values. Use Loki/Tempo drill-down dashboards for session, workflow, agent, run, trace, and span identifiers.
189
+
190
+ ## 3. Cost Dashboard
191
+
192
+ Purpose: show selected-range spend, hourly burn, budget pressure, token/cache behavior, and provider/model attribution without misleading denominators.
193
+
194
+ Panels:
195
+
196
+ - Total selected-range cost, cost burn rate per hour, selected-range budget usage, and projected 24h cost.
197
+ - Cost by provider, model, and environment with percent-of-total context.
198
+ - Cost over time as a trend panel suitable for model/thinking/compaction annotations.
199
+ - Token totals by type: input, output, total, reasoning, cache read, cache write, and cache write 1h.
200
+ - Cache read/write token usage, cache read ratio, and estimated cache savings where supported by metrics.
201
+
202
+ PromQL examples:
203
+
204
+ ```promql
205
+ sum(increase(observme_llm_cost_usd_total[$__range])) by (provider, model)
206
+ ```
207
+
208
+ ```promql
209
+ sum(increase(observme_llm_cost_usd_total[$__range])) / clamp_min(sum(increase(observme_llm_requests_total[$__range])), 1e-9) * 1000
210
+ ```
211
+
212
+ ```promql
213
+ sum(increase(observme_llm_input_tokens_total[$__range])) by (provider, model)
214
+ ```
215
+
216
+ ```promql
217
+ sum(increase(observme_llm_cache_read_tokens_total[$__range])) / clamp_min(sum(increase(observme_llm_cache_read_tokens_total[$__range])) + sum(increase(observme_llm_input_tokens_total[$__range])), 1e-9)
218
+ ```
219
+
220
+ ## 4. Tool Dashboard
221
+
222
+ Purpose: identify busy, slow, failing, or oversized tools and connect aggregate symptoms to filtered failure logs/traces.
223
+
224
+ Panels:
225
+
226
+ - Tool calls by name, tool failure rate, and tool p95 latency trend panels.
227
+ - Interactive user-bash (`!`/`!!`) exit codes over the selected range; assistant Bash tool calls remain in the tool-call panels.
228
+ - Tool result size distribution with character/count semantics when the source metric uses `*_chars`.
229
+ - Tool failures by severity with failure count and failure-rate sorting.
230
+ - Tool latency percentiles with volume so sparse p95/p99 series are not overinterpreted.
231
+ - Captured failed-tool output from `tool.error.captured` logs only when `capture.toolResults` is explicitly enabled; the panel must identify content as opt-in and policy-processed, preserve multiline output, and remain empty when capture is disabled or redaction fails closed.
232
+
233
+ PromQL examples:
234
+
235
+ ```promql
236
+ sum(rate(observme_tool_calls_total[$__rate_interval])) by (tool_name)
237
+ ```
238
+
239
+ ```promql
240
+ sum(rate(observme_tool_failures_total[$__rate_interval])) by (tool_name) / clamp_min(sum(rate(observme_tool_calls_total[$__rate_interval])) by (tool_name), 1e-9)
241
+ ```
242
+
243
+ ```promql
244
+ histogram_quantile(0.95, sum(rate(observme_tool_duration_ms_bucket[$__rate_interval])) by (tool_name, le))
245
+ ```
246
+
247
+ Operational Loki failure rows use `event_name="tool.call.failed"` and should expose `tool_name`, bounded error/status fields, and a Tempo link when trace metadata is present. Captured output uses the separate `event_name="tool.error.captured", event_category="tool_content"` stream so aggregate failure logs remain content-free and broad session-log views can exclude captured bodies.
248
+
249
+ ## 5. Agent and Subagent Dashboard
250
+
251
+ Purpose: make root/subagent reliability and orchestration behavior obvious, especially spawn failures, fan-out, depth, orphan lineage, trace-context propagation, wait/join latency, and recovered child failures.
252
+
253
+ Panels:
254
+
255
+ - Agent runs by role, subagent spawns by depth/spawn type/reason, and spawn failures.
256
+ - p95 agent-run and subagent-spawn duration trends.
257
+ - Active agents by depth, agent-tree depth/width, fan-out per parent operation, and alert-aligned threshold references.
258
+ - Orphan agents and trace-context propagation failures.
259
+ - Parent wait/join latency, child-agent failures, and recovered child failures.
260
+ - Ratio panels for spawn failure rate, orphan pressure vs spawns/runs, propagation failure rate, and child recovery ratio.
261
+ - Top tables for slow agent roles, failing spawn reasons, orphan-prone depths, and high fan-out roles.
262
+ - Parent/child handoff table with parsed fields and Trace Journey/Tempo links.
263
+
264
+ PromQL aggregates must avoid high-cardinality workflow IDs and agent IDs:
265
+
266
+ ```promql
267
+ sum(rate(observme_agent_runs_total[5m])) by (agent_role)
268
+ ```
269
+
270
+ ```promql
271
+ sum(rate(observme_subagents_spawned_total[5m])) by (subagent_depth, spawn_type, spawn_reason)
272
+ ```
273
+
274
+ ```promql
275
+ histogram_quantile(0.95, sum(rate(observme_agent_fanout_count_bucket[5m])) by (subagent_depth, le))
276
+ ```
277
+
278
+ ```promql
279
+ sum(rate(observme_orphan_agents_total[5m])) by (agent_role, subagent_depth)
280
+ ```
281
+
282
+ ```promql
283
+ sum(rate(observme_trace_context_propagation_failures_total[5m])) by (agent_role, subagent_depth)
284
+ ```
285
+
286
+ ```promql
287
+ histogram_quantile(0.95, sum(rate(observme_agent_join_duration_ms_bucket[5m])) by (agent_role, le))
288
+ ```
289
+
290
+ ```promql
291
+ histogram_quantile(0.95, sum(rate(observme_agent_run_duration_ms_bucket[5m])) by (agent_role, le))
292
+ ```
293
+
294
+ Use Tempo or Loki for per-agent/per-workflow drill-down with attributes normalized by the backend, for example `pi_workflow_id`, `pi_agent_id`, `pi_agent_parent_id`, `pi_agent_root_id`, and `pi_agent_spawn_id`.
295
+
296
+ ## 5.1 Agent Node Graphs Dashboard
297
+
298
+ Purpose: visualize aggregate topology and health for root agents, roles, spawn reasons, and subagent depths without implying a single trace tree.
299
+
300
+ Panels:
301
+
302
+ - `Pi root → agents → subagents`: aggregate root-to-role-to-depth node graph with selected-range counts and red health nodes/edges for failed spawns, orphan lineage, and propagation failures.
303
+ - `Agent role → spawn reason → subagent depth`: aggregate delegation-path node graph using spawn counts as edge weights.
304
+
305
+ Node graphs use only bounded aggregate labels. Per-workflow/session/agent identifiers belong in Trace Journey, Loki handoff rows, or Tempo spans.
306
+
307
+ ## 5.2 Trace Journey Dashboard
308
+
309
+ Panels:
310
+
311
+ - Trace journey map explaining the `session → agent run → turn → LLM → tool/bash → subagent spawn → wait/join → branch/compaction` flow.
312
+ - Summary stats for active agents, completed workflows, failed workflows, workflow completion ratio, subagent spawns, LLM requests, tool calls, and trace-context propagation failures.
313
+ - Journey flow rate over time for turns, LLM requests, tool calls, bash executions, subagent spawns, and compactions.
314
+ - p95 stage-latency bar gauge for agent-run, turn, LLM, tool, bash, wait, and join spans.
315
+ - Agent-tree shape over time using active agents, p95 depth, p95 width, and p95 fan-out.
316
+ - Subagent handoffs by depth and spawn reason.
317
+ - Loki-backed execution journey events and ordered journey log, filterable by `pi_session_id`, `pi_agent_id`, and `pi_agent_run_id`; these use logs panels because Loki log streams do not provide state-timeline frames without extra transforms.
318
+ - Parent/child handoff table from `event_category="agent-tree"` logs.
319
+ - Tempo TraceQL table for recent `observme-pi-extension` traces so users can open the full waterfall and keep the current session/agent filters beside matching logs.
320
+
321
+ The dashboard uses high-cardinality IDs only for Loki/Tempo drill-down filters. Prometheus panels continue to use low-cardinality aggregate labels only.
322
+
323
+ ## 6. Model Dashboard
324
+
325
+ Purpose: compare provider/model traffic, reliability, latency, stop reasons, and cost efficiency using semantically valid denominators.
326
+
327
+ Panels:
328
+
329
+ - Requests by provider/model with traffic share context.
330
+ - Error rate by provider/model paired with error counts and request volume.
331
+ - p95 latency by provider/model, with adjacent volume context in Latency.
332
+ - Stop reason distribution as selected-range totals or a true time series.
333
+ - Cost per 1k LLM requests by provider/model.
334
+ - Overall cost per completed turn when turn attribution is aggregate-only.
335
+
336
+ PromQL examples:
337
+
338
+ ```promql
339
+ sum(rate(observme_llm_requests_total[$__rate_interval])) by (provider, model)
340
+ ```
341
+
342
+ ```promql
343
+ sum(rate(observme_llm_errors_total[$__rate_interval])) by (provider, model) / clamp_min(sum(rate(observme_llm_requests_total[$__rate_interval])) by (provider, model), 1e-9)
344
+ ```
345
+
346
+ ```promql
347
+ sum(increase(observme_llm_cost_usd_total[$__range])) by (provider, model) / clamp_min(sum(increase(observme_llm_requests_total[$__range])) by (provider, model), 1e-9) * 1000
348
+ ```
349
+
350
+ Do not divide model-level cost by global turn counts and label the result as model cost per turn. Use provider/model LLM-request denominators, or explicitly label aggregate cost per completed turn when the denominator is global turns.
351
+
352
+ ## 7. Branch and Compaction Dashboard
353
+
354
+ Purpose: explain context-branching and compaction pressure, and provide model/thinking change context for cost, latency, and model dashboards.
355
+
356
+ Panels:
357
+
358
+ - Branches per session estimate, using selected-range counts when possible and explaining sparse-session noise.
359
+ - Compactions over time, with per-session/turn context where available.
360
+ - Tokens before compaction histogram with p95 and optional p50/p99 companion views.
361
+ - Branch summaries created and compaction logs as parsed Loki rows.
362
+ - Model changes and thinking level changes, also suitable as dashboard annotations for Cost, Models, and Latency.
363
+
364
+ PromQL examples:
365
+
366
+ ```promql
367
+ sum(rate(observme_compactions_total[$__rate_interval])) by (environment)
368
+ ```
369
+
370
+ ```promql
371
+ histogram_quantile(0.95, sum(rate(observme_compaction_tokens_before_bucket[$__rate_interval])) by (le))
372
+ ```
373
+
374
+ ## 8. Export Health Dashboard
375
+
376
+ Purpose: show whether ObservMe is observing Pi handler activity and whether the local telemetry/export path is dropping, redacting, or failing. This dashboard intentionally combines liveness panels with failure-only panels; failure-only panels can be quiet in a healthy range and should not make the whole dashboard appear blank.
377
+
378
+ Healthy local-session behavior:
379
+
380
+ - A trusted local project where `/obs status` and `/obs health` succeed should show recent ObservMe activity from `observme_events_observed_total` after representative Pi events occur.
381
+ - Failure counters render as `0` when no failure series exists in the selected time range.
382
+ - Collector/export health renders healthy when events are observed and local drops/export errors remain zero.
383
+ - Loki failure tables remain empty unless matching failure logs occur; empty `redaction.failed`, `telemetry.dropped`, `export.failed`, and `trace_context.propagation_failed` tables mean no matching failures were observed in the selected range.
384
+ - The dashboard contract does not require changing project trust, `/obs status`, `/obs health`, local OTLP endpoint selection, Grafana auth/profile, or local debug capture policy.
385
+
386
+ Panels and signals:
387
+
388
+ - Recent observed event rate: `observme_events_observed_total`.
389
+ - Handler latency and pressure: `observme_handler_duration_ms` and `observme_handler_errors_total`.
390
+ - Active SDK spans: `observme_active_spans` by bounded `operation`.
391
+ - Telemetry drops: `observme_telemetry_dropped_total` by bounded `reason`.
392
+ - Redaction failures: `observme_redaction_failures_total` by bounded `operation`/`error_class` where available.
393
+ - Export failures: `observme_export_errors_total` by bounded `reason`/`error_class` where available.
394
+ - Failure logs: Loki `event_name` values `redaction.failed`, `telemetry.dropped`, `export.failed`, and `trace_context.propagation_failed`.
395
+
396
+ Allowed metric labels for Export Health panels are the low-cardinality labels `operation`, `reason`, `error_class`, and `status`. Dashboard PromQL must not group or filter by session IDs, workflow IDs, agent IDs, trace/span IDs, entry IDs, raw prompts, raw commands, raw paths, or raw error messages.
397
+
398
+ Zero-safe PromQL examples for stat panels:
399
+
400
+ ```promql
401
+ sum(rate(observme_events_observed_total[$__rate_interval])) or vector(0)
402
+ ```
403
+
404
+ ```promql
405
+ sum(rate(observme_telemetry_dropped_total[$__rate_interval])) or vector(0)
406
+ ```
407
+
408
+ ```promql
409
+ sum(rate(observme_redaction_failures_total[$__rate_interval])) or vector(0)
410
+ ```
411
+
412
+ ```promql
413
+ sum(rate(observme_export_errors_total[$__rate_interval])) or vector(0)
414
+ ```
415
+
416
+ ```promql
417
+ sum(rate(observme_handler_errors_total[$__rate_interval])) or vector(0)
418
+ ```
419
+
420
+ Breakdowns can keep low-cardinality grouping while still documenting that an unlabeled zero means no series exists yet:
421
+
422
+ ```promql
423
+ sum(rate(observme_telemetry_dropped_total[$__rate_interval])) by (reason) or vector(0)
424
+ ```
425
+
426
+ Observability Export SLO alignment:
427
+
428
+ ```promql
429
+ 1 - (sum(rate(observme_telemetry_dropped_total[$__range])) / clamp_min(sum(rate(observme_events_observed_total[$__range])), 1e-9))
430
+ ```
431
+
432
+ ## 9. Loki Queries
433
+
434
+ Errors:
435
+
436
+ ```logql
437
+ {service_name="observme-pi-extension", event_name=~".*[.]failed|.*[.]dropped|agent[.]orphaned"}
438
+ ```
439
+
440
+ Tool failures:
441
+
442
+ ```logql
443
+ {service_name="observme-pi-extension", event_name="tool.call.failed"}
444
+ ```
445
+
446
+ LLM failures:
447
+
448
+ ```logql
449
+ {service_name="observme-pi-extension", event_name="llm.request.failed"}
450
+ ```
451
+
452
+ The dedicated `observme-llm-conversations.json` dashboard is the canonical opt-in content view. It shows a redacted conversation timeline, prompt/response/thinking panels, and trace links. Its Loki template filters cover `pi_session_id`, `pi_workflow_id` where promoted, `pi_agent_id`, `pi_agent_run_id`, `provider`, `model`, and content kind; the local Collector promotes the required normalized labels for this dashboard when capture and label policy allow them.
453
+
454
+ Captured prompts, responses, and thinking (redacted, opt-in log bodies):
455
+
456
+ ```logql
457
+ {service_name="observme-pi-extension", event_name="llm.prompt.captured"}
458
+ {service_name="observme-pi-extension", event_name="llm.response.captured"}
459
+ {service_name="observme-pi-extension", event_name="llm.thinking.captured"}
460
+ ```
461
+
462
+ Compactions:
463
+
464
+ ```logql
465
+ {service_name="observme-pi-extension", event_name="compaction.created"}
466
+ ```
467
+
468
+ Subagent spawns:
469
+
470
+ ```logql
471
+ {service_name="observme-pi-extension", event_name="agent.spawn.completed"}
472
+ ```
473
+
474
+ Orphan agents:
475
+
476
+ ```logql
477
+ {service_name="observme-pi-extension", event_name="agent.orphaned"}
478
+ ```
479
+
480
+ Trace-context propagation failures:
481
+
482
+ ```logql
483
+ {service_name="observme-pi-extension", event_name="trace_context.propagation_failed"}
484
+ ```
485
+
486
+ These examples assume Loki OTLP ingestion stores ObservMe OTEL attributes as labels or structured metadata. Dotted OTEL attribute names are queried in Loki with underscores, for example `event.name` as `event_name`, `event.category` as `event_category`, and `pi.session.id` as `pi_session_id`. `event.category` is the ObservMe semantic category, so failure dashboards select by `event_name` rather than `event_category="error"`.
487
+
488
+ ## 10. Tempo / TraceQL Concepts
489
+
490
+ Trace search examples depend on Tempo version and configured attributes. Conceptual queries:
491
+
492
+ ```text
493
+ Find traces where pi.tool.name = bash and status = error
494
+ Find traces where pi.llm.cost.total_usd > 0.10
495
+ Find traces where pi.compaction.tokens_before > 50000
496
+ Find traces by pi.session.id
497
+ Find child traces/spans by pi.agent.parent_id or pi.agent.root_id
498
+ Find all traces/spans in an orchestrated workflow by pi.workflow.id
499
+ Find joins where pi.agent.join.status = timeout or error
500
+ ```
501
+
502
+ ## 11. Suggested Alerts
503
+
504
+ ### High LLM Error Rate
505
+
506
+ ```promql
507
+ sum(rate(observme_llm_errors_total[10m])) / clamp_min(sum(rate(observme_llm_requests_total[10m])), 1e-9) > 0.05
508
+ ```
509
+
510
+ Severity: warning
511
+
512
+ ### High Tool Failure Rate
513
+
514
+ ```promql
515
+ sum(rate(observme_tool_failures_total[10m])) by (tool_name) / clamp_min(sum(rate(observme_tool_calls_total[10m])) by (tool_name), 1e-9) > 0.10
516
+ ```
517
+
518
+ Severity: warning
519
+
520
+ ### Subagent Spawn Failures
521
+
522
+ ```promql
523
+ sum(rate(observme_subagent_spawn_failures_total[10m])) > 0
524
+ ```
525
+
526
+ Severity: warning
527
+
528
+ ### Export Drops Detected
529
+
530
+ ```promql
531
+ sum(rate(observme_telemetry_dropped_total[5m])) > 0
532
+ ```
533
+
534
+ Severity: warning
535
+
536
+ ### Cost Spike
537
+
538
+ ```promql
539
+ sum(increase(observme_llm_cost_usd_total[1h])) > 50
540
+ ```
541
+
542
+ Severity depends on organization budget.
543
+
544
+ ### Redaction Failures
545
+
546
+ ```promql
547
+ sum(rate(observme_redaction_failures_total[5m])) > 0
548
+ ```
549
+
550
+ Severity: critical if content capture is enabled.
551
+
552
+ ### Runaway Agent Fan-Out
553
+
554
+ ```promql
555
+ histogram_quantile(0.95, sum(rate(observme_agent_fanout_count_bucket[10m])) by (le)) > 20
556
+ ```
557
+
558
+ Severity: warning; tune the threshold to the organization's normal orchestrator workload.
559
+
560
+ ### Excessive Agent Tree Depth
561
+
562
+ ```promql
563
+ histogram_quantile(0.95, sum(rate(observme_agent_tree_depth_bucket[10m])) by (le)) > 5
564
+ ```
565
+
566
+ Severity: warning; tune the threshold to expected maximum delegation depth.
567
+
568
+ ### Orphan Agents Detected
569
+
570
+ ```promql
571
+ sum(rate(observme_orphan_agents_total[10m])) > 0
572
+ ```
573
+
574
+ Severity: warning.
575
+
576
+ ### Trace Context Propagation Failures
577
+
578
+ ```promql
579
+ sum(rate(observme_trace_context_propagation_failures_total[10m])) > 0
580
+ ```
581
+
582
+ Severity: warning.
583
+
584
+ ### Active Agents Stuck High
585
+
586
+ ```promql
587
+ sum(observme_active_agents) > 100
588
+ ```
589
+
590
+ Severity depends on normal fleet size; tune per deployment.
591
+
592
+ ## 12. SLOs
593
+
594
+ The `ObservMe SLO Health` dashboard (`dashboards/observme-slo-health.json`) surfaces runtime SLO scorecards, 1h/30d burn-rate panels, and alert-threshold references. Export Health also links to the SLO dashboard and shows the liveness, drop, export-error, redaction-failure, and handler-overhead inputs separately so healthy idle ranges are distinguishable from unhealthy export behavior.
595
+
596
+ ### Observability Export SLO
597
+
598
+ 99% of observed telemetry events are not locally dropped over 30 days.
599
+
600
+ Indicator:
601
+
602
+ ```promql
603
+ 1 - (sum(rate(observme_telemetry_dropped_total[30d])) / clamp_min(sum(rate(observme_events_observed_total[30d])), 1e-9))
604
+ ```
605
+
606
+ ### Agent Lineage SLO
607
+
608
+ 99% of known subagent spawns produce either propagated trace context or parent/child lineage attributes.
609
+
610
+ Indicator:
611
+
612
+ ```promql
613
+ 1 - ((sum(rate(observme_subagent_spawn_failures_total{reason="lineage_missing"}[30d])) + sum(rate(observme_orphan_agents_total[30d])) + sum(rate(observme_trace_context_propagation_failures_total[30d]))) / clamp_min(sum(rate(observme_subagents_spawned_total[30d])), 1e-9))
614
+ ```
615
+
616
+ ### Workflow Completion SLO
617
+
618
+ 99% of started workflows complete or explicitly fail with terminal telemetry over 30 days.
619
+
620
+ Indicator:
621
+
622
+ ```promql
623
+ (sum(rate(observme_workflows_completed_total[30d])) + sum(rate(observme_workflow_errors_total[30d]))) / clamp_min(sum(rate(observme_workflows_started_total[30d])), 1e-9)
624
+ ```
625
+
626
+ ### Instrumentation Overhead SLO
627
+
628
+ 99% of event handlers complete in under 10ms.
629
+
630
+ Metric:
631
+
632
+ ```text
633
+ observme_handler_duration_ms
634
+ ```
635
+
636
+ ### Redaction SLO
637
+
638
+ 100% of configured secret test patterns are redacted in CI.
639
+
640
+ This is a test SLO, not runtime-only.