11
11
class TestBraintrustSpanName (unittest .TestCase ):
12
12
"""Test custom span_name functionality in Braintrust logging."""
13
13
14
- @patch (' litellm.integrations.braintrust_logging.HTTPHandler' )
14
+ @patch (" litellm.integrations.braintrust_logging.HTTPHandler" )
15
15
def test_default_span_name (self , MockHTTPHandler ):
16
16
"""Test that default span name is 'Chat Completion' when not provided."""
17
17
# Mock HTTP response
@@ -22,39 +22,43 @@ def test_default_span_name(self, MockHTTPHandler):
22
22
# Setup
23
23
logger = BraintrustLogger (api_key = "test-key" )
24
24
logger .default_project_id = "test-project-id"
25
-
25
+
26
26
# Create a properly structured mock response
27
27
response_obj = litellm .ModelResponse (
28
28
id = "test-id" ,
29
29
object = "chat.completion" ,
30
30
created = 1234567890 ,
31
31
model = "gpt-3.5-turbo" ,
32
- choices = [{
33
- "index" : 0 ,
34
- "message" : {"role" : "assistant" , "content" : "test response" },
35
- "finish_reason" : "stop"
36
- }],
37
- usage = {"prompt_tokens" : 10 , "completion_tokens" : 20 , "total_tokens" : 30 }
32
+ choices = [
33
+ {
34
+ "index" : 0 ,
35
+ "message" : {"role" : "assistant" , "content" : "test response" },
36
+ "finish_reason" : "stop" ,
37
+ }
38
+ ],
39
+ usage = {"prompt_tokens" : 10 , "completion_tokens" : 20 , "total_tokens" : 30 },
38
40
)
39
-
41
+
40
42
kwargs = {
41
43
"litellm_call_id" : "test-call-id" ,
42
44
"messages" : [{"role" : "user" , "content" : "test" }],
43
45
"litellm_params" : {"metadata" : {}},
44
46
"model" : "gpt-3.5-turbo" ,
45
- "response_cost" : 0.001
47
+ "response_cost" : 0.001 ,
46
48
}
47
-
49
+
48
50
# Execute
49
51
logger .log_success_event (kwargs , response_obj , datetime .now (), datetime .now ())
50
-
52
+
51
53
# Verify
52
54
call_args = mock_http_handler .post .call_args
53
55
self .assertIsNotNone (call_args )
54
- json_data = call_args .kwargs ['json' ]
55
- self .assertEqual (json_data ['events' ][0 ]['span_attributes' ]['name' ], 'Chat Completion' )
56
+ json_data = call_args .kwargs ["json" ]
57
+ self .assertEqual (
58
+ json_data ["events" ][0 ]["span_attributes" ]["name" ], "Chat Completion"
59
+ )
56
60
57
- @patch (' litellm.integrations.braintrust_logging.HTTPHandler' )
61
+ @patch (" litellm.integrations.braintrust_logging.HTTPHandler" )
58
62
def test_custom_span_name (self , MockHTTPHandler ):
59
63
"""Test that custom span name is used when provided in metadata."""
60
64
# Mock HTTP response
@@ -65,39 +69,43 @@ def test_custom_span_name(self, MockHTTPHandler):
65
69
# Setup
66
70
logger = BraintrustLogger (api_key = "test-key" )
67
71
logger .default_project_id = "test-project-id"
68
-
72
+
69
73
# Create a properly structured mock response
70
74
response_obj = litellm .ModelResponse (
71
75
id = "test-id" ,
72
76
object = "chat.completion" ,
73
77
created = 1234567890 ,
74
78
model = "gpt-3.5-turbo" ,
75
- choices = [{
76
- "index" : 0 ,
77
- "message" : {"role" : "assistant" , "content" : "test response" },
78
- "finish_reason" : "stop"
79
- }],
80
- usage = {"prompt_tokens" : 10 , "completion_tokens" : 20 , "total_tokens" : 30 }
79
+ choices = [
80
+ {
81
+ "index" : 0 ,
82
+ "message" : {"role" : "assistant" , "content" : "test response" },
83
+ "finish_reason" : "stop" ,
84
+ }
85
+ ],
86
+ usage = {"prompt_tokens" : 10 , "completion_tokens" : 20 , "total_tokens" : 30 },
81
87
)
82
-
88
+
83
89
kwargs = {
84
90
"litellm_call_id" : "test-call-id" ,
85
91
"messages" : [{"role" : "user" , "content" : "test" }],
86
92
"litellm_params" : {"metadata" : {"span_name" : "Custom Operation" }},
87
93
"model" : "gpt-3.5-turbo" ,
88
- "response_cost" : 0.001
94
+ "response_cost" : 0.001 ,
89
95
}
90
-
96
+
91
97
# Execute
92
98
logger .log_success_event (kwargs , response_obj , datetime .now (), datetime .now ())
93
-
99
+
94
100
# Verify
95
101
call_args = mock_http_handler .post .call_args
96
102
self .assertIsNotNone (call_args )
97
- json_data = call_args .kwargs ['json' ]
98
- self .assertEqual (json_data ['events' ][0 ]['span_attributes' ]['name' ], 'Custom Operation' )
103
+ json_data = call_args .kwargs ["json" ]
104
+ self .assertEqual (
105
+ json_data ["events" ][0 ]["span_attributes" ]["name" ], "Custom Operation"
106
+ )
99
107
100
- @patch (' litellm.integrations.braintrust_logging.HTTPHandler' )
108
+ @patch (" litellm.integrations.braintrust_logging.HTTPHandler" )
101
109
def test_span_name_with_other_metadata (self , MockHTTPHandler ):
102
110
"""Test that span_name works alongside other metadata fields."""
103
111
# Mock HTTP response
@@ -108,21 +116,23 @@ def test_span_name_with_other_metadata(self, MockHTTPHandler):
108
116
# Setup
109
117
logger = BraintrustLogger (api_key = "test-key" )
110
118
logger .default_project_id = "test-project-id"
111
-
119
+
112
120
# Create a properly structured mock response
113
121
response_obj = litellm .ModelResponse (
114
122
id = "test-id" ,
115
123
object = "chat.completion" ,
116
124
created = 1234567890 ,
117
125
model = "gpt-3.5-turbo" ,
118
- choices = [{
119
- "index" : 0 ,
120
- "message" : {"role" : "assistant" , "content" : "test response" },
121
- "finish_reason" : "stop"
122
- }],
123
- usage = {"prompt_tokens" : 10 , "completion_tokens" : 20 , "total_tokens" : 30 }
126
+ choices = [
127
+ {
128
+ "index" : 0 ,
129
+ "message" : {"role" : "assistant" , "content" : "test response" },
130
+ "finish_reason" : "stop" ,
131
+ }
132
+ ],
133
+ usage = {"prompt_tokens" : 10 , "completion_tokens" : 20 , "total_tokens" : 30 },
124
134
)
125
-
135
+
126
136
kwargs = {
127
137
"litellm_call_id" : "test-call-id" ,
128
138
"messages" : [{"role" : "user" , "content" : "test" }],
@@ -132,34 +142,40 @@ def test_span_name_with_other_metadata(self, MockHTTPHandler):
132
142
"project_id" : "custom-project" ,
133
143
"user_id" : "user123" ,
134
144
"session_id" : "session456" ,
135
- "environment" : "production"
145
+ "environment" : "production" ,
136
146
}
137
147
},
138
148
"model" : "gpt-3.5-turbo" ,
139
- "response_cost" : 0.001
149
+ "response_cost" : 0.001 ,
150
+ "standard_logging_object" : {
151
+ "user_id" : "user123" ,
152
+ },
140
153
}
141
-
154
+
142
155
# Execute
143
156
logger .log_success_event (kwargs , response_obj , datetime .now (), datetime .now ())
144
-
157
+
145
158
# Verify
146
159
call_args = mock_http_handler .post .call_args
147
160
self .assertIsNotNone (call_args )
148
- json_data = call_args .kwargs [' json' ]
149
-
161
+ json_data = call_args .kwargs [" json" ]
162
+
150
163
# Check span name
151
- self .assertEqual (json_data ['events' ][0 ]['span_attributes' ]['name' ], 'Multi Metadata Test' )
152
-
164
+ self .assertEqual (
165
+ json_data ["events" ][0 ]["span_attributes" ]["name" ], "Multi Metadata Test"
166
+ )
167
+
153
168
# Check that other metadata is preserved (except for filtered keys)
154
- event_metadata = json_data ['events' ][0 ]['metadata' ]
155
- self .assertEqual (event_metadata ['user_id' ], 'user123' )
156
- self .assertEqual (event_metadata ['session_id' ], 'session456' )
157
- self .assertEqual (event_metadata ['environment' ], 'production' )
158
-
169
+ event_metadata = json_data ["events" ][0 ]["metadata" ]
170
+ print (event_metadata )
171
+ self .assertEqual (event_metadata ["user_id" ], "user123" )
172
+ self .assertEqual (event_metadata ["session_id" ], "session456" )
173
+ self .assertEqual (event_metadata ["environment" ], "production" )
174
+
159
175
# Span name should be in span_attributes, not in metadata
160
- self .assertIn (' span_name' , event_metadata ) # span_name is also kept in metadata
176
+ self .assertIn (" span_name" , event_metadata ) # span_name is also kept in metadata
161
177
162
- @patch (' litellm.integrations.braintrust_logging.get_async_httpx_client' )
178
+ @patch (" litellm.integrations.braintrust_logging.get_async_httpx_client" )
163
179
async def test_async_custom_span_name (self , mock_get_http_handler ):
164
180
"""Test async logging with custom span name."""
165
181
# Mock async HTTP response
@@ -170,38 +186,44 @@ async def test_async_custom_span_name(self, mock_get_http_handler):
170
186
# Setup
171
187
logger = BraintrustLogger (api_key = "test-key" )
172
188
logger .default_project_id = "test-project-id"
173
-
189
+
174
190
# Create a properly structured mock response
175
191
response_obj = litellm .ModelResponse (
176
192
id = "test-id" ,
177
193
object = "chat.completion" ,
178
194
created = 1234567890 ,
179
195
model = "gpt-3.5-turbo" ,
180
- choices = [{
181
- "index" : 0 ,
182
- "message" : {"role" : "assistant" , "content" : "test response" },
183
- "finish_reason" : "stop"
184
- }],
185
- usage = {"prompt_tokens" : 10 , "completion_tokens" : 20 , "total_tokens" : 30 }
196
+ choices = [
197
+ {
198
+ "index" : 0 ,
199
+ "message" : {"role" : "assistant" , "content" : "test response" },
200
+ "finish_reason" : "stop" ,
201
+ }
202
+ ],
203
+ usage = {"prompt_tokens" : 10 , "completion_tokens" : 20 , "total_tokens" : 30 },
186
204
)
187
-
205
+
188
206
kwargs = {
189
207
"litellm_call_id" : "test-call-id" ,
190
208
"messages" : [{"role" : "user" , "content" : "test" }],
191
209
"litellm_params" : {"metadata" : {"span_name" : "Async Custom Operation" }},
192
210
"model" : "gpt-3.5-turbo" ,
193
- "response_cost" : 0.001
211
+ "response_cost" : 0.001 ,
194
212
}
195
-
213
+
196
214
# Execute
197
- await logger .async_log_success_event (kwargs , response_obj , datetime .now (), datetime .now ())
198
-
215
+ await logger .async_log_success_event (
216
+ kwargs , response_obj , datetime .now (), datetime .now ()
217
+ )
218
+
199
219
# Verify
200
220
call_args = mock_http_handler .post .call_args
201
221
self .assertIsNotNone (call_args )
202
- json_data = call_args .kwargs ['json' ]
203
- self .assertEqual (json_data ['events' ][0 ]['span_attributes' ]['name' ], 'Async Custom Operation' )
222
+ json_data = call_args .kwargs ["json" ]
223
+ self .assertEqual (
224
+ json_data ["events" ][0 ]["span_attributes" ]["name" ], "Async Custom Operation"
225
+ )
204
226
205
227
206
228
if __name__ == "__main__" :
207
- unittest .main ()
229
+ unittest .main ()
0 commit comments