[bot] Google GenAI Batches API is not instrumented (mis-tagged as a generic LLM span)
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 38/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- java
- Domain
- observability-sre
Research direction
Start with braintrust-sdk/instrumentation/genai_1_18_0/src/main/java/com/google/genai/BraintrustApiClient.java, especially tagSpan(), then inspect BraintrustInstrumentation.java to confirm the client and async batch entry points. Compare the google-genai Batches API shapes with the existing instrumentation and identify tests to add for create, get, list, cancel, and completed results. Done means batch operations have appropriate span data and regression coverage without treating BatchJob metadata as generation output.
Written by the indexing model from the issue text.
Description
Summary
The genai_1_18_0 module instruments Google's google-genai Java SDK by subclassing its package-private ApiClient (com.google.genai.BraintrustApiClient) and swapping it into every service object on the Client, including client.batches and client.async.batches (BraintrustInstrumentation.wrapClient, lines 36–52). This means a call to client.batches.create(...)/.get(...)/.list(...)/.cancel(...)/.createEmbeddings(...) does produce a span — but BraintrustApiClient.tagSpan() has no awareness of the Batches API's request/response shape, so the span is mis-tagged: it's marked span_attributes.type = "llm" as if it were a real generation call, but the request/response field extraction (built for generateContent-shaped bodies) finds essentially nothing meaningful to populate.
What is missing
In braintrust-sdk/instrumentation/genai_1_18_0/src/main/java/com/google/genai/BraintrustApiClient.java, tagSpan() (lines 50–161):
- Request metadata extraction (lines 65–76) looks for top-level
model,systemInstruction,tools,toolConfig,safetySettings,cachedContent. AbatchGenerateContentrequest body wraps everything under abatchobject ({"batch": {"displayName": ..., "inputConfig": {...}}}), and acreateEmbeddingsbatch job body is shaped aroundEmbeddingsBatchJobSource/CreateEmbeddingsBatchJobConfig— none of the expected top-level fields exist, so metadata stays essentially empty. input_jsonconstruction (lines 97–113) only populatesmodel/contents/config(fromgenerationConfig) — a batch-create body has none of these at top level (the model is only present in the URL path, e.g.{model}:batchGenerateContent, andgetModel(genAIEndpoint)(used as a fallback at line 102) is the only path by whichmodelwould end up ininput_jsonat all); the batch's actual per-itemcontents/generation requests (whether inline or file/GCS-referenced) are never captured.- Response handling (lines 116–150) dumps the whole response body as
output_json(line 125) — for a batch create/get call, that whole body is justBatchJobresource metadata (name,state,createTime, etc.), not generative output — and readsusageMetadatafor metrics (line 128), which aBatchJobresponse never has. There is no instrumentation at all of retrieving a completed batch's actual per-request results (where real generation outputs andusageMetadatabecome available), so even a fully successful batch job produces a span withtype: "llm"but no meaningful input, output, or token metrics. - No test or example anywhere in the repo exercises
client.batchesin any form (confirmed via grep forbatchunderbraintrust-sdk/instrumentation/genai_1_18_0/— the only match isBraintrustInstrumentation.java's own field-swap wiring, not a test).
Braintrust docs status: not_found
Checked https://www.braintrust.dev/docs/integrations/ai-providers/gemini in full: no mention of batchGenerateContent, Batches, or batch/async generation jobs anywhere, in any language. The only "batch"-adjacent mention is batchEmbedContents, and only in the unrelated context of AI proxy/gateway passthrough support for embeddings ("The gateway also supports Gemini's native embedContent and batchEmbedContents endpoints") — not span/tracing coverage, and not the Batches job API this issue is about.
Note: this repo's own gap-audit history already treats "Batch API not instrumented, mis-tagged as a generic LLM span" as a valid, in-scope finding — see the already-filed and still-open #155 for Anthropic's Message Batches API, which this issue mirrors for the Google GenAI provider (a distinct upstream API/SDK/module, not a duplicate).
Upstream sources
- Gemini API "Batch Mode" (
batchGenerateContent) — official docs: https://ai.google.dev/gemini-api/docs/batch-api and https://ai.google.dev/gemini-api/docs/batch-mode. Async, 50%-discounted, ~24h turnaround; supports inline requests or file/JSONL upload. - Vertex AI batch predictions for Gemini (and partner models) via GCS/BigQuery: https://docs.cloud.google.com/vertex-ai/generative-ai/docs/maas/capabilities/batch-prediction, with a Java-specific sample using the same
com.google.genai.Batchesclass: https://docs.cloud.google.com/vertex-ai/generative-ai/docs/samples/googlegenaisdk-batchpredict-with-gcs. - Official
google-genaiJava SDK exposes this directly:com.google.genai.Batches(googleapis/java-genai,src/main/java/com/google/genai/Batches.java), javadoc at https://googleapis.github.io/java-genai/javadoc/com/google/genai/Batches.html —create(String model, BatchJobSource, CreateBatchJobConfig),createEmbeddings(...)(experimental),get(...),cancel(...),delete(...),list(...), all returning/operating onBatchJob.
Local repo files inspected
braintrust-sdk/instrumentation/genai_1_18_0/src/main/java/com/google/genai/BraintrustApiClient.java— lines 50–161 (tagSpan)braintrust-sdk/instrumentation/genai_1_18_0/src/main/java/com/google/genai/BraintrustInstrumentation.java— lines 22–57 (wrapClient), confirmingclient.batches/client.async.batchesare explicitly wired to the same instrumentedApiClient(lines 37, 47) and therefore do produce (mis-tagged) spans rather than bypassing instrumentation entirely- Repo-wide grep for
batch/Batch/batchGenerateContent/BatchJobunderbraintrust-sdk/instrumentation/genai_1_18_0/— only match is the field-swap wiring above; no test or example exercises the Batches API
- Dominant language
- Java
- Stars
- 21
- Forks
- 5
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 8
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from braintrustdata/braintrust-sdk-java
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
All issues in braintrustdata/braintrust-sdk-java
Similar issues
-
certification
Difficulty 1/5 Under an hour Newbie friendliness 80/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
[BUG] ECR GetAuthorizationToken returns a proxyEndpoint for the default region, not the request's Openbug ecr
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
Needs: Triage Type: Feature request
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
AntennaPod/AntennaPod#8794 ·
-
agentic-workflows
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
github/copilot-sdk#2760 ·