1616from opentelemetry .trace import INVALID_SPAN , SpanKind
1717from opentelemetry .util .genai .handler import TelemetryHandler
1818from opentelemetry .util .genai .types import (
19+ ContentCapturingMode ,
1920 Error ,
2021 FunctionToolDefinition ,
2122 InputMessage ,
@@ -79,8 +80,12 @@ def test_all_attributes(self):
7980 invocation .output_type = "text"
8081 invocation .temperature = 0.7
8182 invocation .top_p = 0.9
83+ invocation .frequency_penalty = 0.5
84+ invocation .presence_penalty = 0.3
8285 invocation .max_tokens = 1000
86+ invocation .stop_sequences = ["END" , "STOP" ]
8387 invocation .seed = 42
88+ invocation .choice_count = 3
8489 invocation .input_tokens = 100
8590 invocation .output_tokens = 200
8691 invocation .stop ()
@@ -97,8 +102,12 @@ def test_all_attributes(self):
97102 assert attrs [GenAI .GEN_AI_OUTPUT_TYPE ] == "text"
98103 assert attrs [GenAI .GEN_AI_REQUEST_TEMPERATURE ] == 0.7
99104 assert attrs [GenAI .GEN_AI_REQUEST_TOP_P ] == 0.9
105+ assert attrs [GenAI .GEN_AI_REQUEST_FREQUENCY_PENALTY ] == 0.5
106+ assert attrs [GenAI .GEN_AI_REQUEST_PRESENCE_PENALTY ] == 0.3
100107 assert attrs [GenAI .GEN_AI_REQUEST_MAX_TOKENS ] == 1000
108+ assert attrs [GenAI .GEN_AI_REQUEST_STOP_SEQUENCES ] == ("END" , "STOP" )
101109 assert attrs [GenAI .GEN_AI_REQUEST_SEED ] == 42
110+ assert attrs [GenAI .GEN_AI_REQUEST_CHOICE_COUNT ] == 3
102111
103112 def test_no_response_model_or_finish_reasons (self ):
104113 invocation = self .handler .start_invoke_local_agent ("openai" )
@@ -164,8 +173,8 @@ def test_default_values(self):
164173 assert invocation .agent_name is None
165174 assert invocation .provider == "openai"
166175 assert invocation .request_model is None
167- assert invocation .input_messages == []
168- assert invocation .output_messages == []
176+ assert not invocation .input_messages
177+ assert not invocation .output_messages
169178 assert invocation .tool_definitions is None
170179 assert invocation .cache_creation_input_tokens is None
171180 assert invocation .cache_read_input_tokens is None
@@ -208,6 +217,85 @@ def test_tool_definitions_type(self):
208217 assert invocation .tool_definitions [0 ].name == "get_weather"
209218 assert invocation .tool_definitions [0 ].type == "function"
210219
220+ @patch (
221+ "opentelemetry.util.genai._invocation.get_content_capturing_mode" ,
222+ return_value = ContentCapturingMode .SPAN_AND_EVENT ,
223+ )
224+ @patch (
225+ "opentelemetry.util.genai._invocation.is_experimental_mode" ,
226+ return_value = True ,
227+ )
228+ def test_system_instruction_on_span (self , _mock_exp , _mock_cap ):
229+ invocation = self .handler .start_invoke_local_agent ("openai" )
230+ invocation .system_instruction = [
231+ Text (content = "You are a helpful assistant." ),
232+ ]
233+ invocation .stop ()
234+
235+ attrs = self .span_exporter .get_finished_spans ()[0 ].attributes
236+ assert GenAI .GEN_AI_SYSTEM_INSTRUCTIONS in attrs
237+
238+ @patch (
239+ "opentelemetry.util.genai._invocation.get_content_capturing_mode" ,
240+ return_value = ContentCapturingMode .SPAN_AND_EVENT ,
241+ )
242+ @patch (
243+ "opentelemetry.util.genai._invocation.is_experimental_mode" ,
244+ return_value = True ,
245+ )
246+ def test_tool_definitions_on_span (self , _mock_exp , _mock_cap ):
247+ tool = FunctionToolDefinition (
248+ name = "get_weather" ,
249+ description = "Get the weather" ,
250+ parameters = {"type" : "object" , "properties" : {}},
251+ )
252+ invocation = self .handler .start_invoke_local_agent ("openai" )
253+ invocation .tool_definitions = [tool ]
254+ invocation .stop ()
255+
256+ attrs = self .span_exporter .get_finished_spans ()[0 ].attributes
257+ assert GenAI .GEN_AI_TOOL_DEFINITIONS in attrs
258+
259+ @patch (
260+ "opentelemetry.util.genai._invocation.get_content_capturing_mode" ,
261+ return_value = ContentCapturingMode .SPAN_AND_EVENT ,
262+ )
263+ @patch (
264+ "opentelemetry.util.genai._invocation.is_experimental_mode" ,
265+ return_value = True ,
266+ )
267+ def test_messages_on_span (self , _mock_exp , _mock_cap ):
268+ invocation = self .handler .start_invoke_local_agent ("openai" )
269+ invocation .input_messages = [
270+ InputMessage (role = "user" , parts = [Text (content = "Hello" )])
271+ ]
272+ invocation .output_messages = [
273+ OutputMessage (
274+ role = "assistant" ,
275+ parts = [Text (content = "Hi!" )],
276+ finish_reason = "stop" ,
277+ )
278+ ]
279+ invocation .stop ()
280+
281+ attrs = self .span_exporter .get_finished_spans ()[0 ].attributes
282+ assert GenAI .GEN_AI_INPUT_MESSAGES in attrs
283+ assert GenAI .GEN_AI_OUTPUT_MESSAGES in attrs
284+
285+ def test_content_not_on_span_by_default (self ):
286+ invocation = self .handler .start_invoke_local_agent ("openai" )
287+ invocation .system_instruction = [
288+ Text (content = "You are a helpful assistant." ),
289+ ]
290+ invocation .input_messages = [
291+ InputMessage (role = "user" , parts = [Text (content = "Hello" )])
292+ ]
293+ invocation .stop ()
294+
295+ attrs = self .span_exporter .get_finished_spans ()[0 ].attributes
296+ assert GenAI .GEN_AI_SYSTEM_INSTRUCTIONS not in attrs
297+ assert GenAI .GEN_AI_INPUT_MESSAGES not in attrs
298+
211299 def test_default_lists_are_independent (self ):
212300 inv1 = self .handler .start_invoke_local_agent ("openai" )
213301 inv2 = self .handler .start_invoke_local_agent ("openai" )
0 commit comments