Skip to content

Commit 65b1f61

Browse files
committed
feat: do not create a separate trace for sub-agent
1 parent 8faf2da commit 65b1f61

2 files changed

Lines changed: 26 additions & 38 deletions

File tree

src/index.ts

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ import type { Plugin } from "@opencode-ai/plugin"
22
import { SeverityNumber } from "@opentelemetry/api-logs"
33
import { logs } from "@opentelemetry/api-logs"
44
import { trace } from "@opentelemetry/api"
5+
import {
6+
AGENT_NAME,
7+
INPUT_MIME_TYPE,
8+
INPUT_VALUE,
9+
LLM_INPUT_MESSAGES,
10+
MimeType,
11+
} from "@arizeai/openinference-semantic-conventions"
512
import pkg from "../package.json" with { type: "json" }
613
import type {
714
EventSessionCreated,
@@ -218,14 +225,23 @@ export const OtelPlugin: Plugin = async ({ project, client, directory, worktree
218225
.filter(Boolean)
219226
.join("\n")
220227
sessionInputs.set(input.sessionID, promptText)
221-
handleRunStarted(
222-
input.sessionID,
223-
agent,
224-
promptText,
225-
input.model ? `${input.model.providerID}/${input.model.modelID}` : "unknown",
226-
Date.now(),
227-
ctx,
228-
)
228+
const model = input.model ? `${input.model.providerID}/${input.model.modelID}` : "unknown"
229+
const sessionSpan = sessionSpans.get(input.sessionID)
230+
if (sessionSpan) {
231+
sessionSpan.setAttributes({
232+
[AGENT_NAME]: agent,
233+
...(promptText
234+
? {
235+
[INPUT_VALUE]: promptText,
236+
[INPUT_MIME_TYPE]: MimeType.TEXT,
237+
[LLM_INPUT_MESSAGES]: JSON.stringify([{ role: "user", content: promptText }]),
238+
}
239+
: {}),
240+
model,
241+
})
242+
} else {
243+
handleRunStarted(input.sessionID, agent, promptText, model, Date.now(), ctx)
244+
}
229245
const promptLength = promptText.length
230246
logger.emit({
231247
severityNumber: SeverityNumber.INFO,
@@ -238,7 +254,7 @@ export const OtelPlugin: Plugin = async ({ project, client, directory, worktree
238254
"session.id": input.sessionID,
239255
agent,
240256
prompt_length: promptLength,
241-
model: input.model ? `${input.model.providerID}/${input.model.modelID}` : "unknown",
257+
model,
242258
...commonAttrs,
243259
},
244260
})

tests/handlers/spans.test.ts

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { describe, test, expect } from "bun:test"
22
import { SpanStatusCode } from "@opentelemetry/api"
33
import {
4-
AGENT_NAME,
54
LLM_MODEL_NAME,
65
LLM_PROVIDER,
76
LLM_SYSTEM,
@@ -12,7 +11,6 @@ import {
1211
LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE,
1312
OpenInferenceSpanKind,
1413
SemanticConventions,
15-
SESSION_ID,
1614
TOOL_NAME,
1715
} from "@arizeai/openinference-semantic-conventions"
1816
import type { Span } from "@opentelemetry/api"
@@ -27,7 +25,7 @@ import {
2725
handleMessagePartUpdated,
2826
startMessageSpan,
2927
} from "../../src/handlers/message.ts"
30-
import { makeCtx, makeTracer, type SpySpan } from "../helpers.ts"
28+
import { makeCtx, makeTracer } from "../helpers.ts"
3129
import type {
3230
EventSessionCreated,
3331
EventSessionIdle,
@@ -156,32 +154,6 @@ describe("session spans", () => {
156154
expect(ctx.sessionSpans.has("ses_1")).toBe(false)
157155
})
158156

159-
test("run span carries session.id attribute", () => {
160-
const { ctx, tracer } = makeCtx()
161-
handleRunStarted("ses_1", "agent", "prompt", "anthropic/claude", 1000, ctx)
162-
expect(tracer.spans[0]!.attributes["session.id"]).toBe("ses_1")
163-
expect(tracer.spans[0]!.attributes[SESSION_ID]).toBe("ses_1")
164-
})
165-
166-
test("run span is tagged as an OpenInference agent span", () => {
167-
const { ctx, tracer } = makeCtx()
168-
handleRunStarted("ses_1", "agent", "prompt", "anthropic/claude", 1000, ctx)
169-
expect(tracer.spans[0]!.attributes[OPENINFERENCE_SPAN_KIND]).toBe(OpenInferenceSpanKind.AGENT)
170-
expect(tracer.spans[0]!.attributes[AGENT_NAME]).toBe("agent")
171-
})
172-
173-
test("run span carries is_subagent=false for root session", () => {
174-
const { ctx, tracer } = makeCtx()
175-
handleRunStarted("ses_root", "agent", "prompt", "anthropic/claude", 1000, ctx)
176-
expect(tracer.spans[0]!.attributes["session.is_subagent"]).toBe(false)
177-
})
178-
179-
test("session span carries is_subagent=true for subagent session", () => {
180-
const { ctx, tracer } = makeCtx()
181-
handleSessionCreated(makeSessionCreated("ses_child", 1000, "ses_parent"), ctx)
182-
expect(tracer.spans[0]!.attributes["session.is_subagent"]).toBe(true)
183-
})
184-
185157
test("ends session span with OK status on session.idle", () => {
186158
const { ctx, tracer } = makeCtx()
187159
handleSessionCreated(makeSessionCreated("ses_1"), ctx)

0 commit comments

Comments
 (0)