@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,722 @@
|
|
|
1
|
+
# ObservMe Telemetry Semantic Conventions
|
|
2
|
+
|
|
3
|
+
## 1. Naming Strategy
|
|
4
|
+
|
|
5
|
+
ObservMe does not depend on OpenInference. It uses official OpenTelemetry GenAI semantic-convention attributes where they apply and its own namespaces for Pi-specific concepts.
|
|
6
|
+
|
|
7
|
+
Namespaces:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
observme.* Extension/runtime attributes
|
|
11
|
+
pi.* Pi domain attributes, including `pi.workflow.*` and `pi.agent.*` for Pi workflow/agent/subagent lineage
|
|
12
|
+
gen_ai.* Official OpenTelemetry GenAI client/agent attributes and metrics where applicable
|
|
13
|
+
llm.* Legacy ObservMe aliases only; do not use as the sole representation for new telemetry
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Do not introduce a bare `agent.*` namespace for new telemetry. Use `pi.agent.*` for Pi runtime lineage and `gen_ai.agent.*` only where OpenTelemetry's GenAI agent attributes fit.
|
|
17
|
+
|
|
18
|
+
ObservMe-owned metric names use snake_case and are prefixed with `observme_`. Official GenAI metrics such as `gen_ai.client.token.usage` may also be emitted when the selected OpenTelemetry SDK/backend supports them. Because OTEL GenAI conventions are still evolving, ObservMe's `observme_*` metrics remain the stable product contract.
|
|
19
|
+
|
|
20
|
+
Span names use dotted lowercase operation names:
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
pi.session
|
|
24
|
+
pi.agent.run
|
|
25
|
+
pi.agent.spawn
|
|
26
|
+
pi.agent.wait
|
|
27
|
+
pi.agent.join
|
|
28
|
+
pi.turn
|
|
29
|
+
pi.llm.request
|
|
30
|
+
pi.tool.call
|
|
31
|
+
pi.bash.execution
|
|
32
|
+
pi.compaction
|
|
33
|
+
pi.branch
|
|
34
|
+
pi.model.change
|
|
35
|
+
pi.thinking.change
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 2. Resource Attributes
|
|
39
|
+
|
|
40
|
+
Set once at SDK initialization.
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
service.name = observme-pi-extension
|
|
44
|
+
service.namespace = pi
|
|
45
|
+
service.version = <extension version>
|
|
46
|
+
service.instance.id = <uuid per ObservMe telemetry session/process startup>
|
|
47
|
+
telemetry.sdk.name = opentelemetry # normally set by SDK
|
|
48
|
+
observme.version = <extension version>
|
|
49
|
+
observme.instance.id = <uuid per ObservMe telemetry session/process startup>
|
|
50
|
+
pi.agent.id = <uuid or trusted propagated id per logical agent runtime>
|
|
51
|
+
pi.agent.parent_id = <parent agent id>, optional high-cardinality resource attribute
|
|
52
|
+
pi.agent.root_id = <root agent id>, optional high-cardinality resource attribute
|
|
53
|
+
pi.agent.role = root|subagent
|
|
54
|
+
pi.agent.depth = 0 for root, 1+ for subagents
|
|
55
|
+
pi.agent.capability = optional trusted safe capability name
|
|
56
|
+
pi.cwd.hash = sha256(cwd)
|
|
57
|
+
pi.cwd.basename = basename(cwd), optional
|
|
58
|
+
deployment.environment.name = development|test|staging|production|custom
|
|
59
|
+
observme.environment = dev|ci|prod|unknown, optional compatibility alias
|
|
60
|
+
observme.tenant.id = optional tenant/routing id
|
|
61
|
+
pi.workflow.id = generated workflow/root execution id; high-cardinality resource/span/log attribute
|
|
62
|
+
pi.workflow.root_agent_id = root agent id for the workflow tree
|
|
63
|
+
pi.user.hash = optional stable user hash
|
|
64
|
+
pi.project.name = optional safe project name
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Never set raw `cwd` by default because paths often include usernames, project codenames, or customer names.
|
|
68
|
+
|
|
69
|
+
## 3. Common Span Attributes
|
|
70
|
+
|
|
71
|
+
Every ObservMe span should include:
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
pi.session.id
|
|
75
|
+
pi.workflow.id
|
|
76
|
+
pi.workflow.root_agent_id
|
|
77
|
+
pi.agent.id
|
|
78
|
+
pi.agent.parent_id # if this runtime is a subagent
|
|
79
|
+
pi.agent.root_id
|
|
80
|
+
pi.agent.run.id # if inside an agent_start/agent_end lifecycle
|
|
81
|
+
pi.entry.id # if linked to an entry
|
|
82
|
+
pi.entry.parent_id # if linked to an entry
|
|
83
|
+
pi.entry.type # if linked to an entry
|
|
84
|
+
observme.capture.prompts # boolean
|
|
85
|
+
observme.capture.responses # boolean
|
|
86
|
+
observme.capture.tool_arguments # boolean
|
|
87
|
+
observme.redaction.enabled # boolean
|
|
88
|
+
observme.semconv.version # ObservMe convention version
|
|
89
|
+
observme.replayed # true for explicit replay/backfill telemetry
|
|
90
|
+
observme.evicted # true when span was closed by bounded-registry eviction
|
|
91
|
+
observme.truncated # true when content was truncated before export
|
|
92
|
+
observme.original_length # original character length when truncation occurred
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 4. Session Span
|
|
96
|
+
|
|
97
|
+
Span name:
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
pi.session
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Attributes:
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
pi.session.id
|
|
107
|
+
pi.session.name
|
|
108
|
+
pi.session.cwd_hash
|
|
109
|
+
pi.session.parent_session_hash
|
|
110
|
+
pi.session.persisted
|
|
111
|
+
pi.session.file_hash
|
|
112
|
+
pi.session.version
|
|
113
|
+
pi.model.provider.current
|
|
114
|
+
pi.model.id.current
|
|
115
|
+
pi.thinking.level.current
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Events:
|
|
119
|
+
|
|
120
|
+
```text
|
|
121
|
+
session.started
|
|
122
|
+
session.named
|
|
123
|
+
session.shutdown
|
|
124
|
+
session.error
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Shutdown event/log attributes:
|
|
128
|
+
|
|
129
|
+
```text
|
|
130
|
+
pi.workflow.duration_ms
|
|
131
|
+
pi.workflow.status # ok|error
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 5. Workflow, Agent, and Subagent Spans
|
|
135
|
+
|
|
136
|
+
Additional lineage attributes where known:
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
pi.agent.capability # optional trusted safe capability name
|
|
140
|
+
pi.agent.orphaned # true when parent lineage is incomplete
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 5.1 Agent Run Span
|
|
144
|
+
|
|
145
|
+
Pi emits `agent_start` and `agent_end` once per user prompt lifecycle. Represent that lifecycle with a child span under `pi.session`.
|
|
146
|
+
|
|
147
|
+
Span name:
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
pi.agent.run
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Attributes:
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
pi.agent.id
|
|
157
|
+
pi.agent.parent_id # optional
|
|
158
|
+
pi.agent.root_id
|
|
159
|
+
pi.agent.role # root|subagent
|
|
160
|
+
pi.agent.depth
|
|
161
|
+
pi.agent.run.id
|
|
162
|
+
pi.agent.run.index
|
|
163
|
+
pi.agent.run.source # user|rpc|extension|unknown when known
|
|
164
|
+
pi.agent.run.prompt.hash
|
|
165
|
+
pi.agent.run.prompt.length
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Official GenAI attributes may be mirrored when they describe the Pi agent rather than a provider-side assistant:
|
|
169
|
+
|
|
170
|
+
```text
|
|
171
|
+
gen_ai.agent.id # same as pi.agent.id, span/log attribute only
|
|
172
|
+
gen_ai.agent.name # optional configured safe name
|
|
173
|
+
gen_ai.agent.version # ObservMe/Pi agent version if meaningful
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 5.2 Subagent Spawn Span
|
|
177
|
+
|
|
178
|
+
When a tool or extension launches another Pi agent, emit a spawn span around the parent operation.
|
|
179
|
+
|
|
180
|
+
Span name:
|
|
181
|
+
|
|
182
|
+
```text
|
|
183
|
+
pi.agent.spawn
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Attributes:
|
|
187
|
+
|
|
188
|
+
```text
|
|
189
|
+
pi.agent.spawn.id
|
|
190
|
+
pi.agent.spawn.type # tool|command|extension|unknown
|
|
191
|
+
pi.agent.spawn.reason # delegated_task|parallel_search|review|tool_wrapper|unknown
|
|
192
|
+
pi.agent.spawn.outcome # started|failed|cancelled|timeout
|
|
193
|
+
pi.agent.spawn.tool_call_id # if spawned from a tool call
|
|
194
|
+
pi.agent.spawn.command.hash # if spawned by a command; never raw by default
|
|
195
|
+
pi.agent.child.id # if known after spawn
|
|
196
|
+
pi.agent.child.count # current/observed child count for the parent operation
|
|
197
|
+
pi.agent.children.active # active children at observation time
|
|
198
|
+
pi.agent.parent_id # current pi.agent.id
|
|
199
|
+
pi.agent.root_id
|
|
200
|
+
pi.workflow.id
|
|
201
|
+
pi.workflow.root_agent_id
|
|
202
|
+
pi.agent.depth
|
|
203
|
+
pi.session.id
|
|
204
|
+
pi.agent.spawn.trace_context_propagated
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
If W3C trace context is propagated to the child, the child `pi.session` span should continue the trace. If not, link the child trace back using span links/log attributes and the lineage fields above.
|
|
208
|
+
|
|
209
|
+
### 5.3 Agent Wait and Join Spans
|
|
210
|
+
|
|
211
|
+
When a parent agent waits for a child or collects child results, emit wait/join spans or span events so the multi-agent critical path is visible.
|
|
212
|
+
|
|
213
|
+
Span names:
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
pi.agent.wait
|
|
217
|
+
pi.agent.join
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Attributes:
|
|
221
|
+
|
|
222
|
+
```text
|
|
223
|
+
pi.workflow.id
|
|
224
|
+
pi.agent.id
|
|
225
|
+
pi.agent.child.id # high-cardinality span/log attribute only
|
|
226
|
+
pi.agent.spawn.id # high-cardinality span/log attribute only
|
|
227
|
+
pi.agent.wait.reason # dependency|rate_limit|child_running|unknown
|
|
228
|
+
pi.agent.join.status # ok|error|cancelled|timeout|partial|unknown
|
|
229
|
+
pi.agent.child.status # ok|error|cancelled|timeout|unknown
|
|
230
|
+
pi.agent.failure.propagated # true if child failure failed the parent operation
|
|
231
|
+
pi.agent.children.active
|
|
232
|
+
pi.agent.child.count
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## 6. Turn Span
|
|
236
|
+
|
|
237
|
+
Span name:
|
|
238
|
+
|
|
239
|
+
```text
|
|
240
|
+
pi.turn
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Attributes:
|
|
244
|
+
|
|
245
|
+
```text
|
|
246
|
+
pi.turn.id
|
|
247
|
+
pi.turn.index
|
|
248
|
+
pi.turn.branch_path_hash
|
|
249
|
+
pi.turn.user_message.hash
|
|
250
|
+
pi.turn.user_message.length
|
|
251
|
+
pi.turn.user_message.image_count
|
|
252
|
+
pi.model.provider.current
|
|
253
|
+
pi.model.id.current
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Status:
|
|
257
|
+
|
|
258
|
+
- OK if completed without error
|
|
259
|
+
- ERROR if LLM/tool fatal error ends the turn
|
|
260
|
+
- UNSET if interrupted or unknown
|
|
261
|
+
|
|
262
|
+
## 7. LLM / GenAI Request Span
|
|
263
|
+
|
|
264
|
+
Span name:
|
|
265
|
+
|
|
266
|
+
```text
|
|
267
|
+
pi.llm.request
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
For backend interoperability, also follow the OpenTelemetry GenAI client-span guidance where practical: the provider call span may be named `{gen_ai.operation.name} {gen_ai.request.model}` (for example `chat claude-sonnet-4-5`) or kept as `pi.llm.request` with the official `gen_ai.*` attributes below. If both an internal Pi wrapper span and a provider client span are emitted, make the provider span a child of the turn span and avoid double-counting metrics.
|
|
271
|
+
|
|
272
|
+
Required or recommended official GenAI attributes:
|
|
273
|
+
|
|
274
|
+
```text
|
|
275
|
+
gen_ai.operation.name # chat|generate_content|text_completion
|
|
276
|
+
gen_ai.provider.name
|
|
277
|
+
gen_ai.request.model
|
|
278
|
+
gen_ai.response.model # if provider reports a different response model
|
|
279
|
+
gen_ai.response.id # if available; high-cardinality span/log attribute only
|
|
280
|
+
gen_ai.response.finish_reasons # map Pi stopReason to array where possible
|
|
281
|
+
gen_ai.request.temperature
|
|
282
|
+
gen_ai.request.max_tokens
|
|
283
|
+
gen_ai.usage.input_tokens
|
|
284
|
+
gen_ai.usage.output_tokens
|
|
285
|
+
gen_ai.usage.cache_read.input_tokens
|
|
286
|
+
gen_ai.usage.cache_creation.input_tokens
|
|
287
|
+
gen_ai.usage.reasoning.output_tokens # if provider reports reasoning/thinking tokens
|
|
288
|
+
gen_ai.conversation.id # pi.session.id when safe to expose in spans/logs
|
|
289
|
+
error.type # error class when the operation fails
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
ObservMe/Pi-specific LLM attributes:
|
|
293
|
+
|
|
294
|
+
```text
|
|
295
|
+
pi.llm.api
|
|
296
|
+
pi.llm.request.thinking_level
|
|
297
|
+
pi.llm.request.message_count
|
|
298
|
+
pi.llm.request.tool_schema_count
|
|
299
|
+
pi.llm.request.input_chars
|
|
300
|
+
pi.llm.request.id # in-process provider request correlation
|
|
301
|
+
pi.llm.stop_reason
|
|
302
|
+
pi.llm.error_message_hash
|
|
303
|
+
pi.llm.usage.total_tokens
|
|
304
|
+
pi.llm.usage.cache_write_1h_tokens # Anthropic-specific when available
|
|
305
|
+
pi.llm.cost.input_usd
|
|
306
|
+
pi.llm.cost.output_usd
|
|
307
|
+
pi.llm.cost.cache_read_usd
|
|
308
|
+
pi.llm.cost.cache_write_usd
|
|
309
|
+
pi.llm.cost.total_usd
|
|
310
|
+
pi.llm.tool_call_count # replayed assistant-message tool-call count
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Optional content fields when enabled and redacted:
|
|
314
|
+
|
|
315
|
+
```text
|
|
316
|
+
gen_ai.input.messages # only if explicit content capture is enabled
|
|
317
|
+
gen_ai.output.messages # only if explicit content capture is enabled
|
|
318
|
+
pi.llm.prompt.redacted
|
|
319
|
+
pi.llm.response.redacted
|
|
320
|
+
pi.llm.thinking.redacted
|
|
321
|
+
pi.llm.content.kind # log attribute: prompt|response|thinking
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
When prompt, response, or thinking capture is explicitly enabled, ObservMe exports already-redacted content to both the LLM span attributes above and correlated OTEL logs. Keep capture disabled by default; for high-volume production deployments, prefer dashboards and retention policies that treat these opt-in attributes and log bodies as sensitive even after redaction.
|
|
325
|
+
|
|
326
|
+
## 8. Tool Call Span
|
|
327
|
+
|
|
328
|
+
Span name:
|
|
329
|
+
|
|
330
|
+
```text
|
|
331
|
+
pi.tool.call
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
Attributes:
|
|
335
|
+
|
|
336
|
+
```text
|
|
337
|
+
pi.tool.call.id
|
|
338
|
+
pi.tool.name
|
|
339
|
+
pi.tool.category # shell|filesystem|network|custom|unknown
|
|
340
|
+
pi.tool.arguments.hash
|
|
341
|
+
pi.tool.arguments.size
|
|
342
|
+
pi.tool.result.size
|
|
343
|
+
pi.tool.result.hash
|
|
344
|
+
pi.tool.success
|
|
345
|
+
pi.tool.error
|
|
346
|
+
pi.tool.error_class
|
|
347
|
+
gen_ai.tool.call.id # optional official alias for GenAI tool-call correlation
|
|
348
|
+
gen_ai.tool.name # optional official alias
|
|
349
|
+
gen_ai.tool.type # function|extension|datastore when applicable
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Optional:
|
|
353
|
+
|
|
354
|
+
```text
|
|
355
|
+
pi.tool.arguments.redacted
|
|
356
|
+
pi.tool.result.redacted
|
|
357
|
+
gen_ai.tool.call.arguments # only when explicit content capture is enabled and redacted
|
|
358
|
+
gen_ai.tool.call.result # only when explicit content capture is enabled and redacted
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
## 9. Bash Execution Span
|
|
362
|
+
|
|
363
|
+
Span name:
|
|
364
|
+
|
|
365
|
+
```text
|
|
366
|
+
pi.bash.execution
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
Attributes:
|
|
370
|
+
|
|
371
|
+
```text
|
|
372
|
+
pi.bash.command.hash
|
|
373
|
+
pi.bash.command.redacted # optional
|
|
374
|
+
pi.bash.exit_code
|
|
375
|
+
pi.bash.cancelled
|
|
376
|
+
pi.bash.truncated
|
|
377
|
+
pi.bash.output.size
|
|
378
|
+
pi.bash.output.hash
|
|
379
|
+
pi.bash.output.redacted # optional
|
|
380
|
+
pi.bash.full_output_path_present
|
|
381
|
+
pi.bash.exclude_from_context
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
## 10. Branch Span
|
|
385
|
+
|
|
386
|
+
Span name:
|
|
387
|
+
|
|
388
|
+
```text
|
|
389
|
+
pi.branch
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Attributes:
|
|
393
|
+
|
|
394
|
+
```text
|
|
395
|
+
pi.branch.from_id
|
|
396
|
+
pi.branch.to_id
|
|
397
|
+
pi.branch.common_ancestor_id # if available
|
|
398
|
+
pi.branch.path_hash
|
|
399
|
+
pi.leaf.id
|
|
400
|
+
pi.branch.summary.hash
|
|
401
|
+
pi.branch.summary.length
|
|
402
|
+
pi.branch.from_hook
|
|
403
|
+
pi.branch.read_files_count
|
|
404
|
+
pi.branch.modified_files_count
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## 11. Compaction Span
|
|
408
|
+
|
|
409
|
+
Span name:
|
|
410
|
+
|
|
411
|
+
```text
|
|
412
|
+
pi.compaction
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
Attributes:
|
|
416
|
+
|
|
417
|
+
```text
|
|
418
|
+
pi.compaction.first_kept_entry_id
|
|
419
|
+
pi.compaction.tokens_before
|
|
420
|
+
pi.compaction.summary.hash
|
|
421
|
+
pi.compaction.summary.length
|
|
422
|
+
pi.compaction.from_hook
|
|
423
|
+
pi.compaction.reason
|
|
424
|
+
pi.compaction.will_retry
|
|
425
|
+
pi.compaction.read_files_count
|
|
426
|
+
pi.compaction.modified_files_count
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
## 12. Metrics
|
|
430
|
+
|
|
431
|
+
### 12.1 Counters
|
|
432
|
+
|
|
433
|
+
```text
|
|
434
|
+
observme_sessions_started_total
|
|
435
|
+
observme_sessions_shutdown_total
|
|
436
|
+
observme_workflows_started_total
|
|
437
|
+
observme_workflows_completed_total
|
|
438
|
+
observme_workflow_errors_total
|
|
439
|
+
observme_agent_runs_total
|
|
440
|
+
observme_agent_run_errors_total
|
|
441
|
+
observme_subagents_spawned_total
|
|
442
|
+
observme_subagent_spawn_failures_total
|
|
443
|
+
observme_orphan_agents_total
|
|
444
|
+
observme_trace_context_propagation_failures_total
|
|
445
|
+
observme_child_agent_failures_total
|
|
446
|
+
observme_parent_recovered_from_child_failure_total
|
|
447
|
+
observme_turns_started_total
|
|
448
|
+
observme_turns_completed_total
|
|
449
|
+
observme_llm_requests_total
|
|
450
|
+
observme_llm_errors_total
|
|
451
|
+
observme_tool_calls_total
|
|
452
|
+
observme_tool_failures_total
|
|
453
|
+
observme_bash_executions_total
|
|
454
|
+
observme_bash_failures_total
|
|
455
|
+
observme_model_changes_total
|
|
456
|
+
observme_thinking_level_changes_total
|
|
457
|
+
observme_compactions_total
|
|
458
|
+
observme_branches_total
|
|
459
|
+
observme_telemetry_dropped_total
|
|
460
|
+
observme_export_errors_total
|
|
461
|
+
observme_redaction_failures_total
|
|
462
|
+
observme_events_observed_total
|
|
463
|
+
observme_handler_errors_total
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### 12.2 Token and Cost Counters
|
|
467
|
+
|
|
468
|
+
```text
|
|
469
|
+
observme_llm_input_tokens_total
|
|
470
|
+
observme_llm_output_tokens_total
|
|
471
|
+
observme_llm_cache_read_tokens_total
|
|
472
|
+
observme_llm_cache_write_tokens_total
|
|
473
|
+
observme_llm_cache_write_1h_tokens_total
|
|
474
|
+
observme_llm_reasoning_tokens_total
|
|
475
|
+
observme_llm_total_tokens_total
|
|
476
|
+
observme_llm_cost_usd_total
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### 12.3 Histograms
|
|
480
|
+
|
|
481
|
+
```text
|
|
482
|
+
observme_workflow_duration_ms
|
|
483
|
+
observme_agent_run_duration_ms
|
|
484
|
+
observme_agent_lifetime_duration_ms
|
|
485
|
+
observme_subagent_spawn_duration_ms
|
|
486
|
+
observme_agent_wait_duration_ms
|
|
487
|
+
observme_agent_join_duration_ms
|
|
488
|
+
observme_agent_tree_depth
|
|
489
|
+
observme_agent_tree_width
|
|
490
|
+
observme_agent_fanout_count
|
|
491
|
+
observme_turn_duration_ms
|
|
492
|
+
observme_llm_request_duration_ms
|
|
493
|
+
observme_tool_duration_ms
|
|
494
|
+
observme_bash_duration_ms
|
|
495
|
+
observme_compaction_tokens_before
|
|
496
|
+
observme_prompt_size_chars
|
|
497
|
+
observme_response_size_chars
|
|
498
|
+
observme_tool_result_size_chars
|
|
499
|
+
observme_handler_duration_ms
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### 12.4 Gauges
|
|
503
|
+
|
|
504
|
+
```text
|
|
505
|
+
observme_active_spans
|
|
506
|
+
observme_active_agents
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
### 12.5 Lifecycle recording points
|
|
510
|
+
|
|
511
|
+
- Record `observme_tool_result_size_chars` once from the finalized `tool_execution_end` result, using the same bounded tool labels as tool-call metrics.
|
|
512
|
+
- Increment `observme_agent_run_errors_total` only when an ended agent run is classified as failed.
|
|
513
|
+
- Record `observme_workflow_duration_ms` once for a root workflow at shutdown from its stored start time, with bounded `status=ok|error`.
|
|
514
|
+
- Record `observme_subagent_spawn_duration_ms` from spawn start through either launcher completion or launcher failure.
|
|
515
|
+
- Increment `observme_child_agent_failures_total` when an actual child completion/join reports failed status; a launcher failure before child creation is only a spawn failure.
|
|
516
|
+
- Increment `observme_parent_recovered_from_child_failure_total` once when a failed child is joined with `failurePropagated=false` and parent recovery is confirmed.
|
|
517
|
+
- Repeated child completion/join observations use bounded deduplication state and cannot increment the same failure or recovery transition twice.
|
|
518
|
+
|
|
519
|
+
### 12.6 Export Health self-observability contract
|
|
520
|
+
|
|
521
|
+
The `ObservMe Export Health` dashboard is a self-observability contract for the ObservMe runtime, not a replacement for `/obs status` or `/obs health`. A healthy local session should still produce positive liveness signals while failure-only signals remain at zero or no matching log rows.
|
|
522
|
+
|
|
523
|
+
Dashboard-driving signals:
|
|
524
|
+
|
|
525
|
+
```text
|
|
526
|
+
observme_events_observed_total # counter; one handled Pi event observed by a live telemetry session
|
|
527
|
+
observme_handler_duration_ms # histogram; handler lifecycle latency
|
|
528
|
+
observme_handler_errors_total # counter; safe-handler failures
|
|
529
|
+
observme_active_spans # gauge; active SDK spans by bounded operation
|
|
530
|
+
observme_telemetry_dropped_total # counter; local queue/registry drops by bounded reason
|
|
531
|
+
observme_export_errors_total # counter; exporter failures by bounded reason/error class
|
|
532
|
+
observme_redaction_failures_total # counter; dropped fields caused by redaction exceptions
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
Export Health Loki events:
|
|
536
|
+
|
|
537
|
+
```text
|
|
538
|
+
telemetry.dropped # emitted with telemetry-drop counter updates
|
|
539
|
+
redaction.failed # emitted with redaction-failure counter updates
|
|
540
|
+
export.failed # emitted with export-error counter updates
|
|
541
|
+
trace_context.propagation_failed # emitted when subagent trace propagation fails
|
|
542
|
+
handler.failed # emitted when safe handler isolation catches an exception
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
Healthy-state semantics:
|
|
546
|
+
|
|
547
|
+
- `observme_events_observed_total` is the primary liveness denominator for the dashboard and Observability Export SLO.
|
|
548
|
+
- Failure counters should be queryable as zero when no matching failures happened in the selected range.
|
|
549
|
+
- Failure log tables can be empty in a healthy range; empty `telemetry.dropped`, `redaction.failed`, `export.failed`, and `trace_context.propagation_failed` tables mean no matching failures were observed, not that ingestion is broken.
|
|
550
|
+
- Collector/export health is considered healthy when events are observed and local drop/export-error rates remain zero.
|
|
551
|
+
|
|
552
|
+
Metric labels for these signals are restricted to the low-cardinality allowlist below. In practice, Export Health metrics may use only `operation`, `reason`, `error_class`, and `status` as needed. High-cardinality identifiers such as session, workflow, agent, trace, span, entry, prompt, raw path, raw command, and raw error-message values must stay out of Prometheus labels.
|
|
553
|
+
|
|
554
|
+
This telemetry contract must not require changing project trust behavior, `/obs status`, `/obs health`, the configured local OTLP endpoint, Grafana authentication/profile, or intentionally enabled local debug capture settings.
|
|
555
|
+
|
|
556
|
+
### 12.7 Optional official GenAI metrics
|
|
557
|
+
|
|
558
|
+
Emit these in addition to ObservMe metrics only when the SDK/backend path handles dotted OTEL metric names correctly:
|
|
559
|
+
|
|
560
|
+
```text
|
|
561
|
+
gen_ai.client.token.usage # histogram, unit {token}, attribute gen_ai.token.type=input|output
|
|
562
|
+
gen_ai.client.operation.duration # histogram, unit s
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
## 13. Metric Labels
|
|
566
|
+
|
|
567
|
+
Allowed low-cardinality labels:
|
|
568
|
+
|
|
569
|
+
```text
|
|
570
|
+
provider
|
|
571
|
+
model
|
|
572
|
+
tool_name
|
|
573
|
+
tool_category
|
|
574
|
+
environment
|
|
575
|
+
operation
|
|
576
|
+
status
|
|
577
|
+
error_class
|
|
578
|
+
reason # bounded enum only, e.g. span_registry_full|export_timeout
|
|
579
|
+
agent_role # root|subagent|orchestrator|worker|reviewer|unknown
|
|
580
|
+
agent_capability # bounded configured capability enum/string
|
|
581
|
+
subagent_depth # bounded bucket or small integer
|
|
582
|
+
spawn_type # tool|command|extension|unknown
|
|
583
|
+
spawn_reason # delegated_task|parallel_search|review|tool_wrapper|unknown
|
|
584
|
+
pi_version
|
|
585
|
+
observme_version
|
|
586
|
+
token_type # Prometheus-normalized alias for gen_ai.token.type when applicable
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
Forbidden high-cardinality labels:
|
|
590
|
+
|
|
591
|
+
```text
|
|
592
|
+
session_id
|
|
593
|
+
workflow_id
|
|
594
|
+
workflow_root_agent_id
|
|
595
|
+
agent_id
|
|
596
|
+
parent_agent_id
|
|
597
|
+
child_agent_id
|
|
598
|
+
agent_run_id
|
|
599
|
+
spawn_id
|
|
600
|
+
spawn_tool_call_id
|
|
601
|
+
trace_id
|
|
602
|
+
span_id
|
|
603
|
+
entry_id
|
|
604
|
+
tool_call_id
|
|
605
|
+
raw_command
|
|
606
|
+
raw_prompt
|
|
607
|
+
raw_path
|
|
608
|
+
raw_error_message
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
High-cardinality values belong in span attributes or logs, not metrics. If a backend/exporter converts resource attributes into metric labels, drop `pi.workflow.*`, `pi.agent.*`, `pi.session.id`, trace IDs, span IDs, and spawn IDs from the metrics pipeline first. Generated `service.instance.id` / `observme.instance.id` may remain as backend labels when needed to keep concurrent metric streams distinct; dashboard PromQL must aggregate over them instead of grouping by them.
|
|
612
|
+
|
|
613
|
+
## 14. Logs
|
|
614
|
+
|
|
615
|
+
Log body should be a short event summary. Detailed data goes into structured OTEL log attributes.
|
|
616
|
+
|
|
617
|
+
Common log attributes:
|
|
618
|
+
|
|
619
|
+
```text
|
|
620
|
+
event.name
|
|
621
|
+
event.category
|
|
622
|
+
pi.session.id
|
|
623
|
+
pi.workflow.id
|
|
624
|
+
pi.workflow.root_agent_id
|
|
625
|
+
pi.agent.id
|
|
626
|
+
pi.agent.parent_id
|
|
627
|
+
pi.agent.root_id
|
|
628
|
+
pi.agent.run.id
|
|
629
|
+
pi.turn.id
|
|
630
|
+
trace_id
|
|
631
|
+
span_id
|
|
632
|
+
severity
|
|
633
|
+
error.type
|
|
634
|
+
observme.config.source
|
|
635
|
+
observme.config.rejection.issue_codes
|
|
636
|
+
observme.config.rejection.issue_count
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
Configuration rejection diagnostics use only the bounded effective source, normalized issue codes, and aggregate issue count. They never include rejected values, raw validation messages, paths, headers, environment values, or custom regular expressions.
|
|
640
|
+
|
|
641
|
+
Operational `tool.call.completed` and `tool.call.failed` logs include every available common session/workflow/agent/run/turn correlation field plus `pi.tool.call.id`, `pi.tool.name`, `pi.tool.category`, matching `trace_id`/`span_id`, success, and bounded `error.type` for failures. These operational logs never copy raw tool arguments, results, prompts, commands, paths, or error messages. When `capture.toolResults` is explicitly enabled and the capture policy succeeds, failed-tool output is emitted separately as the `tool.error.captured` log body with `event.category="tool_content"`; redaction remains enabled by default and capture failures emit no content.
|
|
642
|
+
|
|
643
|
+
Explicit replay logs may also include:
|
|
644
|
+
|
|
645
|
+
```text
|
|
646
|
+
pi.message.role
|
|
647
|
+
pi.message.content_length
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
Event names:
|
|
651
|
+
|
|
652
|
+
```text
|
|
653
|
+
config.rejected
|
|
654
|
+
session.started
|
|
655
|
+
session.named
|
|
656
|
+
session.shutdown
|
|
657
|
+
session.error
|
|
658
|
+
session.duplicate_start
|
|
659
|
+
workflow.started
|
|
660
|
+
workflow.completed
|
|
661
|
+
workflow.failed
|
|
662
|
+
agent.run.started
|
|
663
|
+
agent.run.completed
|
|
664
|
+
agent.run.failed
|
|
665
|
+
agent.spawn.started
|
|
666
|
+
agent.spawn.completed
|
|
667
|
+
agent.spawn.failed
|
|
668
|
+
agent.wait.started
|
|
669
|
+
agent.wait.completed
|
|
670
|
+
agent.join.started
|
|
671
|
+
agent.join.completed
|
|
672
|
+
agent.orphaned
|
|
673
|
+
trace_context.propagation_failed
|
|
674
|
+
turn.started
|
|
675
|
+
turn.completed
|
|
676
|
+
llm.request.started
|
|
677
|
+
llm.request.completed
|
|
678
|
+
llm.request.failed
|
|
679
|
+
llm.prompt.captured
|
|
680
|
+
llm.response.captured
|
|
681
|
+
llm.thinking.captured
|
|
682
|
+
message.replayed
|
|
683
|
+
tool.call.started
|
|
684
|
+
tool.call.completed
|
|
685
|
+
tool.call.failed
|
|
686
|
+
tool.error.captured
|
|
687
|
+
bash.completed
|
|
688
|
+
model.changed
|
|
689
|
+
thinking.changed
|
|
690
|
+
branch.created
|
|
691
|
+
compaction.created
|
|
692
|
+
redaction.failed
|
|
693
|
+
export.failed
|
|
694
|
+
handler.failed
|
|
695
|
+
telemetry.dropped
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
## 15. Exemplars
|
|
699
|
+
|
|
700
|
+
Metrics that correspond to traces should include exemplars where supported:
|
|
701
|
+
|
|
702
|
+
- `observme_workflow_duration_ms`
|
|
703
|
+
- `observme_agent_run_duration_ms`
|
|
704
|
+
- `observme_agent_wait_duration_ms`
|
|
705
|
+
- `observme_agent_join_duration_ms`
|
|
706
|
+
- `observme_llm_request_duration_ms`
|
|
707
|
+
- `observme_tool_duration_ms`
|
|
708
|
+
- `observme_turn_duration_ms`
|
|
709
|
+
- `observme_llm_cost_usd_total`
|
|
710
|
+
- `gen_ai.client.operation.duration`
|
|
711
|
+
|
|
712
|
+
For Loki OTLP ingestion, remember that attribute names containing dots are normalized with underscores in Loki queries (for example `event.name` becomes `event_name`, and `pi.session.id` becomes `pi_session_id`).
|
|
713
|
+
|
|
714
|
+
## 16. Versioning
|
|
715
|
+
|
|
716
|
+
Semantic conventions are versioned independently:
|
|
717
|
+
|
|
718
|
+
```text
|
|
719
|
+
observme.semconv.version = 1.0.0
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
Breaking changes require major version increments.
|