mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-13 08:52:02 +00:00
fix(langfuse_otel): keep a caller trace user that the metadata mapping already wrote in its logged form
Some checks failed
LiteLLM Rust / rust-lint (push) Waiting to run
LiteLLM Rust / rust-test (push) Waiting to run
LiteLLM Rust / rust-wheel (push) Waiting to run
Terraform Provider / gofmt, vet, build, test (push) Waiting to run
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Waiting to run
Terraform Modules / fmt, validate, test (aws) (push) Has been cancelled
Terraform Modules / fmt, validate, test (gcp) (push) Has been cancelled
Some checks failed
LiteLLM Rust / rust-lint (push) Waiting to run
LiteLLM Rust / rust-test (push) Waiting to run
LiteLLM Rust / rust-wheel (push) Waiting to run
Terraform Provider / gofmt, vet, build, test (push) Waiting to run
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Waiting to run
Terraform Modules / fmt, validate, test (aws) (push) Has been cancelled
Terraform Modules / fmt, validate, test (gcp) (push) Has been cancelled
This commit is contained in:
parent
66dad9bd09
commit
128dc0414c
3 changed files with 45 additions and 4 deletions
|
|
@ -267,7 +267,8 @@ class LangfuseOtelLogger(OpenTelemetry):
|
|||
def _set_trace_user_attribute(span: Span, kwargs: Mapping[str, object]) -> None:
|
||||
caller: Final = caller_trace_controls(kwargs).user_id
|
||||
if caller is not None:
|
||||
safe_set_attribute(span, LangfuseSpanAttributes.TRACE_USER_ID.value, caller)
|
||||
if caller != LangfuseOtelLogger._mapped_caller_trace_user_id(kwargs):
|
||||
safe_set_attribute(span, LangfuseSpanAttributes.TRACE_USER_ID.value, caller)
|
||||
return
|
||||
slp: Final[Mapping[str, object]] = as_str_mapping(kwargs.get("standard_logging_object")) or MappingProxyType({})
|
||||
slp_metadata: Final[Mapping[str, object]] = as_str_mapping(slp.get("metadata")) or MappingProxyType({})
|
||||
|
|
@ -279,6 +280,13 @@ class LangfuseOtelLogger(OpenTelemetry):
|
|||
if end_user:
|
||||
safe_set_attribute(span, LangfuseSpanAttributes.TRACE_USER_ID.value, str(end_user))
|
||||
|
||||
@staticmethod
|
||||
def _mapped_caller_trace_user_id(kwargs: Mapping[str, object]) -> str | None:
|
||||
"""The caller trace user that `_set_metadata_attributes` already wrote from the header or `metadata`."""
|
||||
request: Final[Mapping[str, object]] = as_str_mapping(kwargs.get("litellm_params")) or MappingProxyType({})
|
||||
mapped_sources: Final = {key: request.get(key) for key in ("metadata", "proxy_server_request")}
|
||||
return caller_trace_controls({"litellm_params": mapped_sources}).user_id
|
||||
|
||||
@staticmethod
|
||||
def _get_langfuse_otel_host() -> str | None:
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ def test_langfuse_otel_list_body_user_does_not_crash(gateway: Gateway, tmp_path:
|
|||
_subsequent_request_still_lands(candidate, collector, batches, model)
|
||||
|
||||
|
||||
def test_langfuse_otel_integer_trace_user_id_does_not_crash(gateway: Gateway, tmp_path: Path) -> None:
|
||||
def test_langfuse_otel_integer_trace_user_id_keeps_its_integer_form(gateway: Gateway, tmp_path: Path) -> None:
|
||||
marker: Final = uuid.uuid4().hex
|
||||
with (
|
||||
wire_server(lambda request: _upstream_reply_for(request, _marker_from_body(request))) as provider,
|
||||
|
|
@ -163,11 +163,26 @@ def test_langfuse_otel_integer_trace_user_id_does_not_crash(gateway: Gateway, tm
|
|||
assert response.status_code == 200, response.text
|
||||
batches: Final[list[bytes]] = []
|
||||
attributes: Final = _await_generation(collector, batches, marker)
|
||||
assert attributes.get("user.id") in ("123", f"end-user-{marker}"), attributes
|
||||
assert attributes.get("session.id") is None, attributes
|
||||
assert _identity(attributes) == {"user.id": 123, "session.id": None}, attributes
|
||||
_subsequent_request_still_lands(candidate, collector, batches, model)
|
||||
|
||||
|
||||
def test_langfuse_otel_list_trace_user_id_keeps_its_json_form(gateway: Gateway, tmp_path: Path) -> None:
|
||||
marker: Final = uuid.uuid4().hex
|
||||
with (
|
||||
wire_server(lambda request: _upstream_reply_for(request, _marker_from_body(request))) as provider,
|
||||
wire_server(_sink) as collector,
|
||||
_langfuse_proxy(gateway, tmp_path, collector.url) as candidate,
|
||||
candidate.scenario() as scenario,
|
||||
):
|
||||
model: Final = scenario.model(model="openai/gpt-4o-mini", api_base=provider.url + "/v1")
|
||||
response: Final = _end_user_request(candidate, model, marker, metadata={"trace_user_id": ["caller-1"]})
|
||||
assert response.status_code == 200, response.text
|
||||
batches: Final[list[bytes]] = []
|
||||
attributes: Final = _await_generation(collector, batches, marker)
|
||||
assert _identity(attributes) == {"user.id": '["caller-1"]', "session.id": None}, attributes
|
||||
|
||||
|
||||
def test_langfuse_otel_null_metadata_still_maps_the_end_user(gateway: Gateway, tmp_path: Path) -> None:
|
||||
marker: Final = uuid.uuid4().hex
|
||||
with (
|
||||
|
|
|
|||
|
|
@ -1137,6 +1137,24 @@ class TestLangfuseOtelTraceIdentity:
|
|||
identity, _ = self._identity(self._kwargs(slp_metadata={"user_api_key_user_id": "internal-1"}))
|
||||
assert identity == {"user.id": None, "session.id": None}
|
||||
|
||||
def test_non_string_caller_trace_user_id_keeps_its_metadata_form(self):
|
||||
listed, _ = self._identity(
|
||||
self._kwargs(
|
||||
slp_metadata={"user_api_key_end_user_id": "end-1"},
|
||||
request_metadata={"trace_user_id": ["caller-1"]},
|
||||
)
|
||||
)
|
||||
numbered, _ = self._identity(
|
||||
self._kwargs(
|
||||
slp_metadata={"user_api_key_end_user_id": "end-1"},
|
||||
request_metadata={"trace_user_id": 123},
|
||||
)
|
||||
)
|
||||
assert (listed, numbered) == (
|
||||
{"user.id": '["caller-1"]', "session.id": None},
|
||||
{"user.id": 123, "session.id": None},
|
||||
)
|
||||
|
||||
def test_logged_end_user_lands_in_user_id_without_a_metadata_copy(self):
|
||||
identity, _ = self._identity(self._kwargs(slp_extra={"end_user": "end-1"}))
|
||||
assert identity == {"user.id": "end-1", "session.id": None}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue