mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-12 23:01:41 +00:00
Merge 819faa01c3 into 49affa7c01
This commit is contained in:
commit
289ca566c3
2 changed files with 33 additions and 2 deletions
|
|
@ -36,11 +36,15 @@ class DDSpanTagger:
|
|||
- ``litellm.key_alias`` — human-readable alias for the API key
|
||||
- ``litellm.key_hash`` — hashed API key (safe to log; never the raw secret)
|
||||
- ``litellm.requested_model``— model name as sent by the client
|
||||
- ``litellm.user_email`` — email of the authenticated user
|
||||
|
||||
Use cases:
|
||||
- Trace all requests from a specific user/key: filter by ``litellm.key_alias`` or
|
||||
``litellm.key_hash``.
|
||||
- Trace all requests for a specific model: filter by ``litellm.requested_model``.
|
||||
- Trace all requests from a specific person under JWT auth, where there is no key_alias:
|
||||
filter by ``@litellm.user_email:"user@example.com"``. The value comes from the JWT claim
|
||||
mapped by ``litellm_jwtauth.user_email_jwt_field``, or from the user row for virtual keys.
|
||||
|
||||
Note: key_alias / key_hash are not available for unauthenticated (e.g. 401) requests.
|
||||
"""
|
||||
|
|
@ -51,8 +55,10 @@ class DDSpanTagger:
|
|||
set_active_span_tag("litellm.key_hash", str(user_api_key_dict.token))
|
||||
if requested_model:
|
||||
set_active_span_tag("litellm.requested_model", str(requested_model))
|
||||
if user_api_key_dict.user_email:
|
||||
set_active_span_tag("litellm.user_email", str(user_api_key_dict.user_email))
|
||||
except Exception:
|
||||
verbose_proxy_logger.debug(
|
||||
"Failed to tag active ddtrace span with key/model tags",
|
||||
"Failed to tag active ddtrace span with key/model/user tags",
|
||||
exc_info=True,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2682,12 +2682,13 @@ class TestStreamingOverheadHeader:
|
|||
class TestDDSpanTaggerTagRequest:
|
||||
"""Tests for DDSpanTagger.tag_request - key/model DD span tagging."""
|
||||
|
||||
def _make_user_api_key_dict(self, key_alias=None, token=None):
|
||||
def _make_user_api_key_dict(self, key_alias=None, token=None, user_email=None):
|
||||
from litellm.proxy._types import UserAPIKeyAuth
|
||||
|
||||
d = UserAPIKeyAuth()
|
||||
d.key_alias = key_alias
|
||||
d.token = token
|
||||
d.user_email = user_email
|
||||
return d
|
||||
|
||||
def test_tags_key_alias_and_model(self):
|
||||
|
|
@ -2728,6 +2729,30 @@ class TestDDSpanTaggerTagRequest:
|
|||
|
||||
mock_set_tag.assert_called_once_with("litellm.requested_model", "claude-3-5-sonnet")
|
||||
|
||||
def test_tags_user_email(self):
|
||||
"""user_email is tagged so JWT-authenticated requests are traceable per person."""
|
||||
user_key = self._make_user_api_key_dict(user_email="user@example.com")
|
||||
|
||||
with patch("litellm.proxy.dd_span_tagger.set_active_span_tag") as mock_set_tag:
|
||||
DDSpanTagger.tag_request(
|
||||
user_api_key_dict=user_key,
|
||||
requested_model=None,
|
||||
)
|
||||
|
||||
mock_set_tag.assert_called_once_with("litellm.user_email", "user@example.com")
|
||||
|
||||
def test_no_user_email_tag_when_absent(self):
|
||||
"""No user email tag when the authenticated identity has no email."""
|
||||
user_key = self._make_user_api_key_dict(key_alias="my-prod-key", user_email=None)
|
||||
|
||||
with patch("litellm.proxy.dd_span_tagger.set_active_span_tag") as mock_set_tag:
|
||||
DDSpanTagger.tag_request(
|
||||
user_api_key_dict=user_key,
|
||||
requested_model="gpt-4o",
|
||||
)
|
||||
|
||||
assert all(call.args[0] != "litellm.user_email" for call in mock_set_tag.call_args_list)
|
||||
|
||||
|
||||
class TestHasAttributeErrorInChain:
|
||||
"""Tests for _has_attribute_error_in_chain helper."""
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue