Conversation
Add V2 support alongside V1 in one package: V1 keeps the named OtelPlugin export; V2 uses a new default export (id devtheops.otel, setup) built on the V2 granular event stream (session.step.*, session.tool.*, session.usage.*, session.execution.*, session.retry.scheduled). Shared changes: - config.ts: additive redactSecrets/redactValues options - headers.ts: use node:child_process instead of the Bun global Refs DEVtheOPS#128
Subagent sessions produced orphan root run spans and dangling parents: the run span was created on the prompt hook (before session.created) and always used the root context. The run span is now created on session.execution.started, nests under the subagent session span, and is marked is_subagent; the subagent session span parents to the parent's opencode.tool.subagent span; session spans end on execution end.
Author
|
Follow-up commit: fix(v2): nest subagent traces under the parent dispatch tool span Testing against a real subagent surfaced two problems in the initial V2 port:
Changes:
Resulting tree (one trace per execution): Verified against OpenCode 2.0.15 with a real subagent dispatch; |
alexhawat
force-pushed
the
feat/opencode-v2-support
branch
from
September 23, 2026 17:34
21b9fe1 to
6808031
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds OpenCode V2 support alongside the existing V1 plugin, in one package.
OtelPluginexport, unchanged.id: devtheops.otel,setup()), built on V2's granularevent stream.
Closes #128.
Why the handlers were re-architected
The V1 handlers consume events that no longer exist in V2 (
session.idle,message.updated,message.part.updated,permission.*,command.executed,session.diff).V2 replaced them with a granular taxonomy, so the handlers were rewritten rather than adapted.
What V2 emits
opencode.sessionrun span (AGENT, turn root)prompthook →session.execution.succeeded/failed/interruptedsession.createdlogsession.created, or lazily on first sightsession.duration,session.token.total,session.cost.totalsession.usage.updated, turn endopencode.llmstep span (LLM) + token/cost/cache/model metricssession.step.started/ended/failedopencode.tool.<name>span (TOOL) +tool.durationsession.tool.input.started,called,success/failedretry.countsession.status(retry)user_promptlog (linked to the run span)session.errorlog + error span statussession.execution.failedmodel.requesthookParity gaps
Not ported (no V2 equivalent): message/part spans, permission telemetry,
command.executed,and
session.diff(lines-of-code/commit) metrics.Shared changes (V1 + V2)
src/config.ts: additiveredactSecrets/redactValuesoptions (V1 ignores them).src/headers.ts: replace theBunglobal withnode:child_processso the headers helper isruntime-agnostic; the "terminated by SIGTERM" error is preserved.
src/redact.ts: new, best-effort secret masking.V2 specifics worth knowing
V2 entry keeps its OTel providers and tracing state on
globalThis(one shared instance,flushed but never shut down) and dedupes events by
event.id.session.idle, andsession.createdis absent for pre-existing sessions,so the turn root span is anchored on
session.execution.*.session.tool.called/success/failedcarry no tool name; it is read fromsession.tool.input.started.data.nameand correlated by call id.Testing
bun run lint,bun run check:jsdoc-coverage(87.96%),bun run typecheck, andbun test(331 pass) are all green locally. Added
tests/redact.test.ts. Verified end-to-end againstOpenCode 2.0.15 with live OTLP export (spans/logs/metrics).
Notes for review
src/v2/util.tsis a copy ofsrc/util.tsretyped against the V2 context. Happy to refactorto a shared generic util if you prefer.
src/v2/is self-contained and does not touch the V1 files (onlysrc/index.tsgains onere-export line), so V1 behaviour is unchanged.