open-telemetry / open-telemetry/opentelemetry-python-contrib
Bedrock embedding calls are tagged with `chat` instead of `embeddings`
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.1k
- Forks
- 1.1k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 16
Description
The Bedrock botocore extension tags embedding calls as chat calls, so anything downstream that
sorts spans by gen_ai.operation.name misclassifies them.
What happens
extensions/bedrock.py assigns an LLM-style operation name to every InvokeModel call, with no
detection of embedding models. On main (line 167):
model_id = self._call_context.params.get(_MODEL_ID_KEY)
if model_id:
attributes[GEN_AI_REQUEST_MODEL] = model_id
attributes[GEN_AI_OPERATION_NAME] = GenAiOperationNameValues.CHAT.value
A later substring test at line 199 refines Titan to text_completion, but nothing ever assigns
embeddings. grep -i embed returns zero hits in the file.
Observed with opentelemetry-instrumentation-botocore 0.60b1, SDK 1.39.1, on a Cohere embedding
model:
rpc.method = "InvokeModel"
gen_ai.system = "aws.bedrock"
gen_ai.request.model = "cohere.embed-v4:0"
gen_ai.operation.name = "chat"
Present on main and on the released v0.60b1, so not a recent regression.
Expected
gen_ai.operation.name = "embeddings", which the GenAI semantic conventions define for exactly
this case (open-telemetry/semantic-conventions-genai, model/gen-ai/registry.yaml). This is a
consistency gap, not a new feature: opentelemetry-instrumentation-openai-v2 already sets
GenAiOperationNameValues.EMBEDDINGS.value for its embedding calls (added in #3461).
Why it matters
Downstream tools resolve span kind from gen_ai.operation.name. Datadog's Agent Observability product, for example, bills only llm spans and treats embedding spans (among others) as free. Mislabeling an embedding call as chat moves it into the billed category, so this isn't just a metadata quibble, it misattributes real cost for anyone running Cohere or similar embedding models on Bedrock.
Notes for whoever picks this up
The defect exists in two places independently: extract_attributes and
_extract_metrics_attributes (lines 138-156) each assign the operation name, so a fix touching
only one leaves gen_ai.client.operation.duration and gen_ai.client.token.usage still labeled
chat. The span name (line 393, f"{operation_name} {request_model}") inherits whichever value
wins.
Related: #3210 (bedrock tracking issue), #3461 (openai-v2 embeddings precedent).
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.
Research direction
Start in extensions/bedrock.py, reading extract_attributes and _extract_metrics_attributes where InvokeModel calls receive their operation name. Compare the embedding handling in opentelemetry-instrumentation-openai-v2 and the GenAI registry, then verify that embedding calls produce embeddings for spans and metrics while other Bedrock operation names remain correct.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, python
- Domain
- observability
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100