mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-30 01:52:18 +00:00
fix(otel): don't cast None metadata values to empty-string span attributes
user_api_key_budget_reset_at (and any other metadata field that's sometimes None, e.g. a key with no budget configured) was being cast to "" by _cast_as_primitive_value_type and set on the span like any other value. A field that sends two different shapes for the same attribute -- an ISO timestamp string sometimes, an empty string other times -- breaks backends that infer a field's type from the first value they see, such as OpenSearch's dynamic index mapping. Skip None values in the metadata attribute loop instead, matching the same pattern already used for cost_breakdown two loops below. Fixes #29583
This commit is contained in:
parent
be3386f3ce
commit
bf8c35e2d4
1 changed files with 9 additions and 1 deletions
|
|
@ -2361,7 +2361,15 @@ class OpenTelemetry(OTELGenAISemconvMixin, CustomLogger):
|
|||
#############################################
|
||||
metadata: Final = standard_logging_payload["metadata"]
|
||||
for key, value in metadata.items():
|
||||
self.safe_set_attribute(span=span, key=f"metadata.{key}", value=value)
|
||||
# Skip None values instead of letting safe_set_attribute cast them to "".
|
||||
# Fields that are sometimes a real value (e.g. an ISO timestamp string
|
||||
# like user_api_key_budget_reset_at) and sometimes None would otherwise
|
||||
# send two different shapes for the same attribute, and backends that
|
||||
# infer a field's type from the first value they see (e.g. OpenSearch's
|
||||
# dynamic mapping) lock onto whichever shape arrives first -- causing the
|
||||
# other shape to fail once the mapping is set. See issue #29583.
|
||||
if value is not None:
|
||||
self.safe_set_attribute(span=span, key=f"metadata.{key}", value=value)
|
||||
|
||||
# get hidden params
|
||||
hidden_params: Final = getattr(standard_logging_payload, "hidden_params", None) or (
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue