Uh oh!
There was an error while loading. Please reload this page.
ref(core): Do not emit spans for chats.create in google-genai - #19990
Conversation
Semver Impact of This PR🟢 Patch (bug fixes) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨
Bug Fixes 🐛
Internal Changes 🔧Core
Other
🤖 This preview updates automatically when you update the PR. |
size-limit report 📦
|
node-overhead report 🧳Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.
|
042667f to
cb797a1Compare16c5086 to
15e6af4Compare
andreiborza
left a comment
There was a problem hiding this comment.
LGTM, could you please create an issue for carrying over the data we lose by not creating these spans anymore?
nicohrubec
commented
Apr 2, 2026
@andreiborza issue: #20086 |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Tests lack assertion for absence of removed span
- Added explicit negative span assertions in both Node and Cloudflare Google GenAI tests to ensure a
chat gemini-1.5-pro createspan is not present.
- Added explicit negative span assertions in both Node and Cloudflare Google GenAI tests to ensure a
Or push these changes by commenting:
@cursor push e8acf088c3
Preview (e8acf088c3)
diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/google-genai/test.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/google-genai/test.ts--- a/dev-packages/cloudflare-integration-tests/suites/tracing/google-genai/test.ts+++ b/dev-packages/cloudflare-integration-tests/suites/tracing/google-genai/test.ts@@ -77,6 +77,13 @@
}),
]),
);
+ expect(transactionEvent.spans).not.toEqual(+ expect.arrayContaining([+ expect.objectContaining({+ description: 'chat gemini-1.5-pro create',+ }),+ ]),+ );
})
.start();
await runner.makeRequest('get', '/');
diff --git a/dev-packages/node-integration-tests/suites/tracing/google-genai/test.ts b/dev-packages/node-integration-tests/suites/tracing/google-genai/test.ts--- a/dev-packages/node-integration-tests/suites/tracing/google-genai/test.ts+++ b/dev-packages/node-integration-tests/suites/tracing/google-genai/test.ts@@ -29,6 +29,8 @@
cleanupChildProcesses();
});
+ const CHAT_CREATE_SPAN_DESCRIPTION = 'chat gemini-1.5-pro create';+
const EXPECTED_TRANSACTION_DEFAULT_PII_FALSE = {
transaction: 'main',
spans: expect.arrayContaining([
@@ -166,7 +168,18 @@
test('creates google genai related spans with sendDefaultPii: false', async () => {
await createRunner()
.ignore('event')
- .expect({ transaction: EXPECTED_TRANSACTION_DEFAULT_PII_FALSE })+ .expect({+ transaction: transactionEvent => {+ expect(transactionEvent).toMatchObject(EXPECTED_TRANSACTION_DEFAULT_PII_FALSE);+ expect(transactionEvent.spans).not.toEqual(+ expect.arrayContaining([+ expect.objectContaining({+ description: CHAT_CREATE_SPAN_DESCRIPTION,+ }),+ ]),+ );+ },+ })
.start()
.completed();
});
@@ -176,7 +189,18 @@
test('creates google genai related spans with sendDefaultPii: true', async () => {
await createRunner()
.ignore('event')
- .expect({ transaction: EXPECTED_TRANSACTION_DEFAULT_PII_TRUE })+ .expect({+ transaction: transactionEvent => {+ expect(transactionEvent).toMatchObject(EXPECTED_TRANSACTION_DEFAULT_PII_TRUE);+ expect(transactionEvent.spans).not.toEqual(+ expect.arrayContaining([+ expect.objectContaining({+ description: CHAT_CREATE_SPAN_DESCRIPTION,+ }),+ ]),+ );+ },+ })
.start()
.completed();
});This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
… chat spans (#23316) `chats.create()` takes a `config` (temperature, topP, topK, maxOutputTokens, frequencyPenalty, presencePenalty, tools, systemInstruction) that `@google/genai` reuses for every `chat.sendMessage()` and `chat.sendMessageStream()` call on that chat. #19990 removed the `chats.create()` span, which was the only span reporting those values, and nothing took over. Chat spans have carried model and token counts but no request config since then. Both google-genai instrumentation paths are fixed: - `instrumentGoogleGenAIClient`, the client proxy, used by `@sentry/cloudflare` and `@sentry/vercel-edge` and available for manual wrapping. - `googleGenAIIntegration`, the diagnostics-channel integration, which is the default for Node, Bun, Deno, Astro, AWS Lambda and Google Cloud Functions. Only the first path was in the original report, but both build their attributes from the per-message arguments alone, so both lost the same data. **Decisions** **The config is read from the chat instance, not captured at create time.** `@google/genai` stores `config` as a plain property on the `Chat` object, and both paths already hold that object: the proxy passes it as the instrumented method's `context`, and the channel path receives it as `data.self`. `extractModel()` already recovers the model the same way. Carrying the `chats.create()` arguments forward instead would have meant threading state through `createDeepProxy`, which fixes only the proxy path and moves that function away from its `openai` and `anthropic-ai` counterparts that #19990 deliberately converged. The cost is a dependency on an internal field name, which this file already accepts for `model` / `modelVersion`. **A per-message config replaces the chat config, it does not merge into it.** The SDK resolves the request as `params.config ?? chat.config`, so a message that carries its own config sends only that config. The span mirrors that. Merging key by key would report a create-time `maxOutputTokens` alongside a per-message `temperature` and describe a request that was never sent. **The chat `history` stays off the message spans.** The SDK does send it, folded into `contents`, and the instance carries the whole transcript, but repeating every past turn on every message span duplicates what earlier spans already reported and grows without bound. `gen_ai.request.messages` keeps just the message being sent. **Non-chat calls are unaffected.** `models.generateContent` and `models.embedContent` have no chat instance, so they resolve their config from their own arguments exactly as before. Fixes#20086 AI assistance (Claude, Anthropic) was used in developing this change. The design, review and verification were done by the author. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: isaacs <i@izs.me>


We currently emit spans for the google-genai
chats.create()API. I think this is basically useless becausechats.create()doesn't represent an actual interaction with an LLM model, instead it just constructs a local chat object as a result that then further exposes methods likesendMessage()that represent actual LLM interactions. This PR removes the spans forchats.create().Since this API is a special case where we actually need to proxy the return object instead of the method call itself we had some surrounding logic hardcoded to this method. To make this a bit more future proof and also more explicit we now add a
proxyResultPathfield to the method registry that allows to define this behavior in the method registry without needing any hardcoded logic. Another benefit this has is that the full logic in thecreateDeepProxymethods in all our client-proxy based AI integrations (google-genai, openai, anthropic) is now essentially the same so could potentially in the future be easily merged into a shared abstraction.Limitation: We do"loose" some data by not emitting this create span anymore, because the way this API works is that the user defines certain parameters only on the
chats.create()call and these are then subsequently used for eachchat.sendMessage()call. The correct way would be to send this data as part of eachchat.sendMessage()chat span. We can think about doing this as part of this PR or doing a follow up.