opencode-otel-plugin 0.4.2 → 0.5.1

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 (3) hide show
  1. package/README.md +141 -28
  2. package/dist/index.js +11 -11
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
4
4
 
5
- OpenTelemetry instrumentation plugin for [OpenCode](https://opencode.ai). Automatically traces every AI coding session — LLM calls, tool executions, file edits, and context compactions — and exports them via OTLP/HTTP to any OpenTelemetry-compatible backend.
5
+ OpenTelemetry instrumentation plugin for [OpenCode](https://opencode.ai). Automatically traces every AI coding session — LLM calls, tool executions, file edits, and context compactions — and exports them via OTLP/HTTP (protobuf) to any OpenTelemetry-compatible backend.
6
6
 
7
7
  ## Quick Start
8
8
 
@@ -68,6 +68,7 @@ All configuration uses standard [OpenTelemetry environment variables](https://op
68
68
  |---|---|---|
69
69
  | `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP/HTTP base URL | `http://localhost:4318` |
70
70
  | `OTEL_EXPORTER_OTLP_HEADERS` | Auth headers (`key=value`, comma-separated) | — |
71
+ | `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` | Metric temporality (`cumulative`, `delta`, `lowmemory`) | `cumulative` |
71
72
 
72
73
  ### Backend Examples
73
74
 
@@ -97,11 +98,13 @@ export OTEL_EXPORTER_OTLP_HEADERS="x-honeycomb-team=<your-api-key>"
97
98
  ```bash
98
99
  export OTEL_EXPORTER_OTLP_ENDPOINT="https://{your-environment-id}.live.dynatrace.com/api/v2/otlp"
99
100
  export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Api-Token {your-api-token}"
100
- export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
101
+ export OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE="delta"
101
102
  ```
102
103
 
103
104
  Create an API token in Dynatrace with `openTelemetryTrace.ingest` and `metrics.ingest` scopes.
104
105
 
106
+ > **Note:** Dynatrace requires delta temporality for metrics — cumulative metrics are silently dropped. The `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta` setting is mandatory.
107
+
105
108
  </details>
106
109
 
107
110
  <details>
@@ -127,41 +130,151 @@ Use an [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) to fa
127
130
 
128
131
  ## What Gets Collected
129
132
 
130
- ### Traces
133
+ ### Span Hierarchy
134
+
135
+ Each OpenCode session produces a trace tree with explicit parent-child relationships:
136
+
137
+ ```
138
+ invoke_agent opencode ← root span (one per session)
139
+ ├── chat {model} ← child span (one per LLM request)
140
+ ├── execute_tool {tool_name} ← child span (one per tool call)
141
+ └── session_compaction ← child span (one per compaction)
142
+ ```
143
+
144
+ ### Trace Attributes
145
+
146
+ #### `invoke_agent opencode` — Session Root Span
147
+
148
+ Created when a session starts, ended on `session.idle`. One per coding session.
149
+
150
+ | Attribute | Type | Description |
151
+ |---|---|---|
152
+ | `gen_ai.operation.name` | string | Always `"invoke_agent"` |
153
+ | `gen_ai.agent.name` | string | Always `"opencode"` |
154
+ | `gen_ai.conversation.id` | string | OpenCode session ID |
155
+ | `service.version` | string | OpenCode version (set when `installation.updated` fires) |
156
+ | `vcs.repository.ref.name` | string | Current git branch |
157
+ | `enduser.id` | string | Git author email (`git config user.email`) |
158
+ | `vcs.repository.url.full` | string | Git remote URL |
159
+ | `opencode.session.request_count` | number | Total LLM requests in session (set when span ends) |
160
+
161
+ #### `chat {model}` — LLM Request Span
131
162
 
132
- Each OpenCode session produces a trace tree with parent-child relationships:
163
+ Created on `chat.params` hook, ended when the assistant message arrives with token counts.
133
164
 
134
- | Span | Trigger | Key Attributes |
165
+ | Attribute | Type | Description |
166
+ |---|---|---|
167
+ | `gen_ai.operation.name` | string | Always `"chat"` |
168
+ | `gen_ai.request.model` | string | Model ID sent in the request (e.g., `claude-sonnet-4-20250514`) |
169
+ | `gen_ai.provider.name` | string | Provider identifier (e.g., `anthropic`, `openai`) |
170
+ | `gen_ai.conversation.id` | string | OpenCode session ID |
171
+ | `vcs.repository.ref.name` | string | Current git branch |
172
+ | `enduser.id` | string | Git author email |
173
+ | `vcs.repository.url.full` | string | Git remote URL |
174
+ | `gen_ai.usage.input_tokens` | number | Input tokens consumed (set on completion) |
175
+ | `gen_ai.usage.output_tokens` | number | Output tokens generated (set on completion) |
176
+ | `gen_ai.response.model` | string | Model ID from the response |
177
+ | `gen_ai.response.finish_reasons` | string[] | Finish reasons array (e.g., `["end_turn"]`) |
178
+ | `error.type` | string | Error class name (set only on failure) |
179
+
180
+ #### `execute_tool {name}` — Tool Execution Span
181
+
182
+ Created on `tool.execute.before`, ended on `tool.execute.after`. Includes flattened tool output metadata.
183
+
184
+ | Attribute | Type | Description |
135
185
  |---|---|---|
136
- | `invoke_agent opencode` | Session start | `gen_ai.agent.name`, `gen_ai.conversation.id` |
137
- | `chat {model}` | LLM request | `gen_ai.request.model`, `gen_ai.provider.name`, `gen_ai.usage.input_tokens`, `gen_ai.usage.output_tokens` |
138
- | `execute_tool {name}` | Tool call | `gen_ai.tool.name`, `gen_ai.tool.call.id`, `code.language` (edit/write tools) |
139
- | `session_compaction` | Context compaction | `gen_ai.conversation.id` |
186
+ | `gen_ai.operation.name` | string | Always `"execute_tool"` |
187
+ | `gen_ai.tool.name` | string | Tool name (e.g., `edit`, `write`, `bash`, `glob`) |
188
+ | `gen_ai.tool.call.id` | string | Unique tool call identifier |
189
+ | `gen_ai.conversation.id` | string | OpenCode session ID |
190
+ | `vcs.repository.ref.name` | string | Current git branch |
191
+ | `enduser.id` | string | Git author email |
192
+ | `vcs.repository.url.full` | string | Git remote URL |
193
+ | `gen_ai.tool.output.title` | string | Tool output title (set on completion) |
194
+ | `gen_ai.tool.output.metadata.*` | string | Flattened tool output metadata (max 32 keys, depth 3, strings truncated to 256 chars) |
195
+ | `code.language` | string | Detected programming language (edit, write, and apply_patch tools only; derived from file extension) |
196
+ | `opencode.file.additions` | number | Lines added (edit, write, and apply_patch tools only; omitted when zero) |
197
+ | `opencode.file.deletions` | number | Lines removed (edit, write, and apply_patch tools only; omitted when zero) |
198
+
199
+ #### `session_compaction` — Context Compaction Span
200
+
201
+ Created as an instant span when OpenCode compacts the conversation context.
202
+
203
+ | Attribute | Type | Description |
204
+ |---|---|---|
205
+ | `gen_ai.conversation.id` | string | OpenCode session ID |
206
+ | `vcs.repository.ref.name` | string | Current git branch |
207
+ | `enduser.id` | string | Git author email |
208
+ | `vcs.repository.url.full` | string | Git remote URL |
140
209
 
141
210
  ### Metrics
142
211
 
143
- | Metric | Type | Unit | Description |
144
- |---|---|---|---|
145
- | `gen_ai.client.token.usage` | Histogram | `{token}` | Input/output tokens per LLM call |
146
- | `gen_ai.client.operation.duration` | Histogram | `s` | LLM call duration |
147
- | `opencode.session.request.count` | Counter | `{request}` | LLM requests per session |
148
- | `opencode.session.compaction.count` | Counter | `{compaction}` | Context compactions |
149
- | `opencode.file.changes` | Counter | `{line}` | Lines added/removed |
150
- | `opencode.tool.invocations` | Counter | `{invocation}` | Tool calls |
212
+ #### `gen_ai.client.token.usage` Token Usage
213
+
214
+ Histogram measuring token consumption per LLM call. Unit: `{token}`.
215
+
216
+ | Attribute | Type | Description |
217
+ |---|---|---|
218
+ | `gen_ai.operation.name` | string | Always `"chat"` |
219
+ | `gen_ai.provider.name` | string | Provider identifier |
220
+ | `gen_ai.request.model` | string | Model ID |
221
+ | `gen_ai.token.type` | string | `"input"` or `"output"` — recorded as two separate data points per call |
222
+
223
+ #### `gen_ai.client.operation.duration` — LLM Call Duration
224
+
225
+ Histogram measuring LLM request latency. Unit: `s` (seconds).
226
+
227
+ | Attribute | Type | Description |
228
+ |---|---|---|
229
+ | `gen_ai.operation.name` | string | Always `"chat"` |
230
+ | `gen_ai.provider.name` | string | Provider identifier |
231
+ | `gen_ai.request.model` | string | Model ID |
232
+ | `error.type` | string | Error class name (present only on failed requests) |
233
+
234
+ #### `opencode.session.request.count` — LLM Request Count
235
+
236
+ Counter tracking total LLM requests. Unit: `{request}`.
237
+
238
+ | Attribute | Type | Description |
239
+ |---|---|---|
240
+ | `gen_ai.request.model` | string | Model ID |
241
+ | `gen_ai.provider.name` | string | Provider identifier |
242
+
243
+ #### `opencode.session.compaction.count` — Compaction Count
244
+
245
+ Counter tracking context compaction events. Unit: `{compaction}`. No attributes.
246
+
247
+ #### `opencode.file.changes` — File Change Lines
248
+
249
+ Counter tracking lines of code added or removed by edit, write, and apply_patch tools. Unit: `{line}`.
250
+
251
+ | Attribute | Type | Description |
252
+ |---|---|---|
253
+ | `code.language` | string | Detected programming language (omitted for unknown file extensions) |
254
+ | `opencode.change.type` | string | `"added"` or `"removed"` |
255
+
256
+ #### `opencode.tool.invocations` — Tool Invocation Count
257
+
258
+ Counter tracking tool executions. Unit: `{invocation}`.
259
+
260
+ | Attribute | Type | Description |
261
+ |---|---|---|
262
+ | `gen_ai.tool.name` | string | Tool name (e.g., `edit`, `bash`, `glob`, `read`) |
151
263
 
152
264
  ### Resource Attributes
153
265
 
154
- Attached to all signals, identifying the session:
266
+ Attached to all exported signals (traces and metrics), identifying the session environment. Set once at plugin initialization.
155
267
 
156
- | Attribute | Source |
157
- |---|---|
158
- | `service.name` | Always `"opencode"` |
159
- | `service.version` | OpenCode version (set when available) |
160
- | `enduser.id` | `git config user.email` |
161
- | `host.name` | Machine hostname |
162
- | `opencode.project.name` | Project identifier |
163
- | `vcs.repository.url.full` | Git remote URL |
164
- | `vcs.repository.ref.name` | Current branch |
268
+ | Attribute | Type | Description |
269
+ |---|---|---|
270
+ | `service.name` | string | Always `"opencode"` |
271
+ | `host.name` | string | Machine hostname |
272
+ | `enduser.id` | string | Git author email (`git config user.email`) |
273
+ | `opencode.project.name` | string | Project identifier from OpenCode |
274
+ | `vcs.repository.url.full` | string | Git remote URL |
275
+ | `vcs.repository.ref.name` | string | Current git branch |
276
+ | `opencode.worktree` | string | Git worktree path |
277
+ | `opencode.directory` | string | Current working directory |
165
278
 
166
279
  ## Troubleshooting
167
280
 
@@ -209,7 +322,7 @@ This plugin follows [OpenTelemetry GenAI Semantic Conventions](https://opentelem
209
322
  git clone https://github.com/felixti/opencode-otel-plugin.git
210
323
  cd opencode-otel-plugin
211
324
  bun install
212
- bun test # 55 tests, 96 assertions
325
+ bun test # 67 tests, 113 assertions
213
326
  bun run typecheck # tsc --noEmit
214
327
  bun run build # dist/index.js + dist/index.d.ts
215
328
  ```