diff --git a/packages/core/src/filesystem.ts b/packages/core/src/filesystem.ts index 8a1cc3a08fc3..9d68f3ff5b65 100644 --- a/packages/core/src/filesystem.ts +++ b/packages/core/src/filesystem.ts @@ -80,6 +80,7 @@ export namespace AppFileSystem { }) const readJson = Effect.fn("FileSystem.readJson")(function* (path: string) { + yield* Effect.annotateCurrentSpan({ "file.path": path }) const text = yield* fs.readFileString(path) return JSON.parse(text) }) @@ -99,6 +100,7 @@ export namespace AppFileSystem { content: string | Uint8Array, mode?: number, ) { + yield* Effect.annotateCurrentSpan({ "file.path": path }) const write = typeof content === "string" ? fs.writeFileString(path, content) : fs.writeFile(path, content) yield* write.pipe( @@ -122,6 +124,7 @@ export namespace AppFileSystem { }) const findUp = Effect.fn("FileSystem.findUp")(function* (target: string, start: string, stop?: string) { + yield* Effect.annotateCurrentSpan({ "file.target": target, "file.start": start }) const result: string[] = [] let current = start while (true) { diff --git a/packages/opencode/src/auth/index.ts b/packages/opencode/src/auth/index.ts index f7c6319357a3..c5dee878f1c1 100644 --- a/packages/opencode/src/auth/index.ts +++ b/packages/opencode/src/auth/index.ts @@ -57,6 +57,7 @@ export const layer = Layer.effect( const decode = Schema.decodeUnknownOption(Info) const all = Effect.fn("Auth.all")(function* () { + yield* Effect.annotateCurrentSpan({ "auth.file": file }) if (process.env.OPENCODE_AUTH_CONTENT) { try { return JSON.parse(process.env.OPENCODE_AUTH_CONTENT) @@ -68,6 +69,7 @@ export const layer = Layer.effect( }) const get = Effect.fn("Auth.get")(function* (providerID: string) { + yield* Effect.annotateCurrentSpan({ "provider.id": providerID }) return (yield* all())[providerID] }) diff --git a/packages/opencode/src/plugin/index.ts b/packages/opencode/src/plugin/index.ts index 7a7f260df897..127de3595f9b 100644 --- a/packages/opencode/src/plugin/index.ts +++ b/packages/opencode/src/plugin/index.ts @@ -260,6 +260,7 @@ export const layer = Layer.effect( Input = Parameters[Name]>[0], Output = Parameters[Name]>[1], >(name: Name, input: Input, output: Output) { + yield* Effect.annotateCurrentSpan({ "plugin.hook": name }) if (!name) return output const s = yield* InstanceState.get(state) for (const hook of s.hooks) { diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index c27b69b6a208..319eb6a58328 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -1564,9 +1564,10 @@ const layer: Layer.Layer< } } - const getProvider = Effect.fn("Provider.getProvider")((providerID: ProviderID) => - InstanceState.use(state, (s) => s.providers[providerID]), - ) + const getProvider = Effect.fn("Provider.getProvider")(function* (providerID: ProviderID) { + yield* Effect.annotateCurrentSpan({ "provider.id": providerID }) + return yield* InstanceState.use(state, (s) => s.providers[providerID]) + }) const getModel = Effect.fn("Provider.getModel")(function* (providerID: ProviderID, modelID: ModelID) { const s = yield* InstanceState.get(state) @@ -1587,6 +1588,7 @@ const layer: Layer.Layer< }) const getLanguage = Effect.fn("Provider.getLanguage")(function* (model: Model) { + yield* Effect.annotateCurrentSpan({ "provider.id": model.providerID, "model.id": model.id }) const s = yield* InstanceState.get(state) const envs = yield* env.all() const key = `${model.providerID}/${model.id}` diff --git a/packages/opencode/src/session/compaction.ts b/packages/opencode/src/session/compaction.ts index 3ca4f074f9e4..7c6ae50c8feb 100644 --- a/packages/opencode/src/session/compaction.ts +++ b/packages/opencode/src/session/compaction.ts @@ -319,6 +319,7 @@ export const layer: Layer.Layer< // goes backwards through parts until there are PRUNE_PROTECT tokens worth of tool // calls, then erases output of older tool calls to free context space const prune = Effect.fn("SessionCompaction.prune")(function* (input: { sessionID: SessionID }) { + yield* Effect.annotateCurrentSpan({ "session.id": input.sessionID }) const cfg = yield* config.get() if (!cfg.compaction?.prune) return log.info("pruning") diff --git a/packages/opencode/src/session/instruction.ts b/packages/opencode/src/session/instruction.ts index 6629ce67bc9f..dd706ba9eac0 100644 --- a/packages/opencode/src/session/instruction.ts +++ b/packages/opencode/src/session/instruction.ts @@ -99,6 +99,7 @@ export const layer: Layer.Layer< }) const clear = Effect.fn("Instruction.clear")(function* (messageID: MessageID) { + yield* Effect.annotateCurrentSpan({ "message.id": messageID }) const s = yield* InstanceState.get(state) s.claims.delete(messageID) }) diff --git a/packages/opencode/src/session/processor.ts b/packages/opencode/src/session/processor.ts index 579c4cc42c54..7d2f1593846d 100644 --- a/packages/opencode/src/session/processor.ts +++ b/packages/opencode/src/session/processor.ts @@ -636,6 +636,10 @@ export const layer: Layer.Layer< }) const cleanup = Effect.fn("SessionProcessor.cleanup")(function* () { + yield* Effect.annotateCurrentSpan({ + "session.id": ctx.sessionID, + "message.id": ctx.assistantMessage.id, + }) if (ctx.snapshot) { const patch = yield* snapshot.patch(ctx.snapshot) if (patch.files.length) { @@ -725,6 +729,10 @@ export const layer: Layer.Layer< }) const process = Effect.fn("SessionProcessor.process")(function* (streamInput: LLM.StreamInput) { + yield* Effect.annotateCurrentSpan({ + "session.id": ctx.sessionID, + "message.id": ctx.assistantMessage.id, + }) slog.info("process") ctx.needsCompaction = false ctx.shouldBreak = (yield* config.get()).experimental?.continue_loop_on_deny !== true diff --git a/packages/opencode/src/session/session.ts b/packages/opencode/src/session/session.ts index f50f8750b32b..62c072fefc07 100644 --- a/packages/opencode/src/session/session.ts +++ b/packages/opencode/src/session/session.ts @@ -583,7 +583,11 @@ export const layer: Layer.Layer(part: T): Effect.Effect => Effect.gen(function* () { @@ -593,7 +597,15 @@ export const layer: Layer.Layer @@ -719,6 +731,7 @@ export const layer: Layer.Layer boolean, ) { + yield* Effect.annotateCurrentSpan({ "session.id": sessionID }) for (const item of MessageV2.stream(sessionID)) { if (predicate(item)) return Option.some(item) } diff --git a/packages/opencode/src/session/summary.ts b/packages/opencode/src/session/summary.ts index e39bd85e9ac9..09308b386bf2 100644 --- a/packages/opencode/src/session/summary.ts +++ b/packages/opencode/src/session/summary.ts @@ -81,6 +81,7 @@ export const layer = Layer.effect( const bus = yield* Bus.Service const computeDiff = Effect.fn("SessionSummary.computeDiff")(function* (input: { messages: MessageV2.WithParts[] }) { + yield* Effect.annotateCurrentSpan({ "messages.count": input.messages.length }) let from: string | undefined let to: string | undefined for (const item of input.messages) { @@ -104,6 +105,7 @@ export const layer = Layer.effect( sessionID: SessionID messageID: MessageID }) { + yield* Effect.annotateCurrentSpan({ "session.id": input.sessionID, "message.id": input.messageID }) const all = yield* sessions.messages({ sessionID: input.sessionID }) if (!all.length) return diff --git a/packages/opencode/src/snapshot/index.ts b/packages/opencode/src/snapshot/index.ts index 848a067c3d11..4e01c051695b 100644 --- a/packages/opencode/src/snapshot/index.ts +++ b/packages/opencode/src/snapshot/index.ts @@ -750,7 +750,9 @@ export const layer: Layer.Layer< return yield* InstanceState.useEffect(state, (s) => s.cleanup()) }), track: Effect.fn("Snapshot.track")(function* () { - return yield* InstanceState.useEffect(state, (s) => s.track()) + const hash = yield* InstanceState.useEffect(state, (s) => s.track()) + if (hash) yield* Effect.annotateCurrentSpan({ "snapshot.hash": hash }) + return hash }), patch: Effect.fn("Snapshot.patch")(function* (hash: string) { return yield* InstanceState.useEffect(state, (s) => s.patch(hash)) diff --git a/packages/opencode/src/tool/truncate.ts b/packages/opencode/src/tool/truncate.ts index ffc16c0b9f99..2b1d5a207cd7 100644 --- a/packages/opencode/src/tool/truncate.ts +++ b/packages/opencode/src/tool/truncate.ts @@ -53,6 +53,7 @@ export const layer = Layer.effect( const fs = yield* AppFileSystem.Service const cleanup = Effect.fn("Truncate.cleanup")(function* () { + yield* Effect.annotateCurrentSpan({ "truncate.dir": TRUNCATION_DIR }) const cutoff = Identifier.timestamp( Identifier.create("tool", "ascending", Date.now() - Duration.toMillis(RETENTION)), ) @@ -60,10 +61,13 @@ export const layer = Layer.effect( Effect.map((all) => all.filter((name) => name.startsWith("tool_"))), Effect.catch(() => Effect.succeed([])), ) + let removed = 0 for (const entry of entries) { if (Identifier.timestamp(entry) >= cutoff) continue yield* fs.remove(path.join(TRUNCATION_DIR, entry)).pipe(Effect.catch(() => Effect.void)) + removed++ } + yield* Effect.annotateCurrentSpan({ "truncate.scanned": entries.length, "truncate.removed": removed }) }) const write = Effect.fn("Truncate.write")(function* (text: string) {