[bot] OpenAI Images API spans missing input/output capture
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 68/100
- Issue 类型
- 功能
- 描述清晰度
- 描述清楚
- 活跃度
- 冷清
- 技术栈
- java
- 领域
- api, observability
调研方向
从 braintrust-sdk/src/main/java/dev/braintrust/instrumentation/InstrumentationSemConv.java 开始,阅读 tagOpenAIRequest()、tagOpenAIResponse() 和 getSpanName(),然后检查现有的 OpenAI chat_completions 和 responses cassette fixtures。为 generate、edit 和 variation 调用添加 Images API 覆盖;完成的标准是 spans 能捕获文档中所述的图像请求和响应数据、适用时的 usage,以及人类可读的 span 名称,并使用 tests 或 fixtures 覆盖该行为。
由索引模型根据 Issue 内容生成。
描述
Summary
The OpenAI instrumentation intercepts every HTTP call made through the OpenAI Java client's HttpClient (generic, transport-level wrapping), so calls to the Images API (client.images().generate(), .edit(), .createVariation()) do produce a span. However, InstrumentationSemConv's request/response tagging logic only recognizes the Chat Completions (messages/choices) and Responses API (input/output) JSON shapes. Images API requests and responses use neither shape, so the resulting spans have no useful input or output data — the same class of gap already fixed/tracked for embeddings (#66) and audio (#131), but not yet filed for Images.
What is missing
InstrumentationSemConv.tagOpenAIRequest() (lines 127–138 of braintrust-sdk/src/main/java/dev/braintrust/instrumentation/InstrumentationSemConv.java):
if (requestJson.has("messages")) {
span.setAttribute("braintrust.input_json", toJson(requestJson.get("messages")));
} else if (requestJson.has("input") && requestJson.get("input").isArray()) {
span.setAttribute("braintrust.input_json", toJson(requestJson.get("input")));
}
An images.generate request body looks like:
{
"model": "gpt-image-1",
"prompt": "A photorealistic cat sitting on a moon",
"size": "1024x1024",
"quality": "high",
"n": 1
}
prompt is a plain string (not messages, not an input array), so neither branch matches — braintrust.input_json is never set for Images API calls. size, quality, n, and style are also dropped since only model is captured into metadata.
InstrumentationSemConv.tagOpenAIResponse() (lines 144–201) only sets braintrust.output_json when the response has choices or output:
if (responseJson.has("choices")) {
span.setAttribute("braintrust.output_json", toJson(responseJson.get("choices")));
} else if (responseJson.has("output")) {
span.setAttribute("braintrust.output_json", toJson(responseJson.get("output")));
}
An images.generate response returns {"data": [{"url": "...", "revised_prompt": "..."}], ...} (or b64_json instead of url). Neither choices nor output is present, so braintrust.output_json is never set — the generated image URL/base64 data and revised_prompt are silently dropped. No usage extraction exists for the Images API's token-based billing on gpt-image-1 either.
The span name mapping in getSpanName() (lines 511–522) also has no case for the images/generations / images/edits / images/variations path segments, so the span name falls back to the raw last path segment instead of a human-readable name like the existing "Chat Completion"/"Embeddings" cases.
Braintrust docs status
- not_found — the Braintrust OpenAI integration docs at https://www.braintrust.dev/docs/integrations/ai-providers/openai document streaming audio transcription tracing ("Braintrust traces streaming audio transcription calls for sync and async OpenAI clients") but make no mention of the Images API or image generation tracing for any language.
Upstream sources
- OpenAI Images API reference: https://platform.openai.com/docs/api-reference/images/create — documents
prompt(string, required),size,quality,n,style,response_format, and the responsedata[]array withurl/b64_json/revised_prompt - OpenAI Java SDK:
client.images().generate(ImageGenerateParams),.edit(ImageEditParams),.createVariation(ImageCreateVariationParams)— stable, documented methods oncom.openai:openai-java(this repo pins2.15.0,)) - gpt-image-1 token-based usage: https://platform.openai.com/docs/guides/image-generation —
gpt-image-1responses include ausageobject withinput_tokens/output_tokens, distinct from the legacy DALL·E per-image pricing
Local files inspected
braintrust-sdk/src/main/java/dev/braintrust/instrumentation/InstrumentationSemConv.java— lines 110–141 (tagOpenAIRequest: onlymessages/array-inputhandled), lines 143–201 (tagOpenAIResponse: onlychoices/outputhandled), lines 511–522 (getSpanName: no case forimages/*paths)braintrust-sdk/instrumentation/openai_2_15_0/src/main/java/dev/braintrust/instrumentation/openai/v2_15_0/TracingHttpClient.java— generic HTTP-level wrapping; delegates all tagging toInstrumentationSemConvtest-harness/src/testFixtures/resources/cassettes/openai/mappings/— onlychat_completions-*andresponses-*cassette files exist; noimages-*cassette or test exists anywhere in the repo (confirmed via repo-wide search)
- 主要语言
- Java
- 星标
- 21
- 派生
- 5
- 平均合并
- 1 天 20 小时
- 30 天内合并 PR
- 8
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
braintrustdata/braintrust-sdk-java 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 82/100
-
难度 2/5 1-3 小时 新手友好度 82/100
-
难度 2/5 1-3 小时 新手友好度 82/100
-
难度 2/5 1-3 小时 新手友好度 78/100
-
难度 2/5 1-3 小时 新手友好度 68/100
查看 braintrustdata/braintrust-sdk-java 的全部 Issue
相似的 Issue
-
[BUG] 订单:会员凭订单号即可取消其他会员的待付款订单(取消接口不校验订单归属)可能已有人在做 @dadiyang 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 70/100
macrozheng/mall#1016 ·
-
[Bug] The producer summary counts an unreported client version as a second version and warns about a version mix可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭
难度 2/5 1-3 小时 新手友好度 74/100
apache/rocketmq-dashboard#6110 ·
维护者通常 4 天内回复
-
Python 3.15 support可能已有人在做 @amnesiaof 今天认领。 未关闭L: python L: python:uv
难度 2/5 1-3 小时 新手友好度 72/100
dependabot/dependabot-core#16524 · 1 条评论 ·
维护者通常 1 天内回复
-
`Processing lsp` never exits and leaves orphaned processes可能已有人在做 @overcast302 今天认领。 未关闭bug
难度 2/5 1-3 小时 新手友好度 72/100
processing/processing4#1578 · 1 条评论 ·
-
bug needs triage
难度 2/5 1-3 小时 新手友好度 72/100
PlayersCommittee/gemp-swccg-public#1174 ·
维护者通常 2 天内回复