11import json
22import pytest
33
4- from utils import scenarios , missing_feature , features , rfc
4+ from utils import scenarios , features , rfc , irrelevant
55from utils .parametric .spec .trace import find_span , find_trace
66
77
88@rfc ("https://docs.google.com/document/d/1cVod_VI7Yruq8U9dfMRFJd7npDu-uBpste2IB04GyaQ" )
99@scenarios .parametric
1010@features .span_events
11- @missing_feature (reason = "Agent does not advertise native span events serialization support yet" )
1211class Test_Span_Events :
13- def _test_span_with_event (self , _library_env , test_agent , test_library , retrieve_events ):
14- """Test adding a span event, with attributes, to an active span."""
12+ def _test_span_with_native_event (self , _library_env , test_agent , test_library ):
13+ """Test adding a span event, with attributes, to an active span.
14+ Assumes native format where all values are serialized according to their original type.
15+ """
1516 time0 = 123450
1617 name0 = "event_name"
1718 attributes0 = {
@@ -39,12 +40,12 @@ def _test_span_with_event(self, _library_env, test_agent, test_library, retrieve
3940 assert len (trace ) == 1
4041 span = find_span (trace , s .span_id )
4142
42- span_events = retrieve_events ( span )
43+ span_events = span [ "span_events" ]
4344
4445 assert len (span_events ) == 2
4546
4647 event = span_events [0 ]
47- assert event ["time_unix_nano" ] == time0 * 1000
48+ assert event ["time_unix_nano" ] == time0 * 1000000000
4849 assert event ["name" ] == name0
4950 assert event ["attributes" ].get ("string" ) == {"type" : 0 , "string_value" : "bar" }
5051 assert event ["attributes" ].get ("bool" ) == {"type" : 1 , "bool_value" : True }
@@ -53,61 +54,123 @@ def _test_span_with_event(self, _library_env, test_agent, test_library, retrieve
5354
5455 assert event ["attributes" ].get ("str_arr" ) == {
5556 "type" : 4 ,
56- "array_value" : {"type" : 0 , "string_value" : ["a" , "b" , "c" ]},
57+ "array_value" : [
58+ {"type" : 0 , "string_value" : "a" },
59+ {"type" : 0 , "string_value" : "b" },
60+ {"type" : 0 , "string_value" : "c" },
61+ ],
5762 }
5863 assert event ["attributes" ].get ("bool_arr" ) == {
5964 "type" : 4 ,
60- "array_value" : {"type" : 1 , "bool_value" : [ True , False ]} ,
65+ "array_value" : [ {"type" : 1 , "bool_value" : True }, { "type" : 1 , "bool_value" : False }] ,
6166 }
6267 assert event ["attributes" ].get ("int_arr" ) == {
6368 "type" : 4 ,
64- "array_value" : {"type" : 2 , "int_value" : [ 5 , 6 ]} ,
69+ "array_value" : [ {"type" : 2 , "int_value" : 5 }, { "type" : 2 , "int_value" : 6 }] ,
6570 }
6671 assert event ["attributes" ].get ("double_arr" ) == {
6772 "type" : 4 ,
68- "array_value" : {"type" : 3 , "double_value" : [ 1.1 , 2.2 ]} ,
73+ "array_value" : [ {"type" : 3 , "double_value" : 1.1 }, { "type" : 3 , "double_value" : 2.2 }] ,
6974 }
7075
7176 event = span_events [1 ]
72- assert event ["time_unix_nano" ] == time1 * 1000
77+ assert event ["time_unix_nano" ] == time1 * 1000000000
7378 assert event ["name" ] == name1
7479 assert event ["attributes" ].get ("bool" ) == {"type" : 1 , "bool_value" : False }
7580 assert event ["attributes" ].get ("int" ) == {"type" : 2 , "int_value" : 0 }
76- assert isinstance (event ["attributes" ].get ("int" ).get ("int " ), int )
81+ assert isinstance (event ["attributes" ].get ("int" ).get ("int_value " ), int )
7782 assert event ["attributes" ].get ("double" ) == {"type" : 3 , "double_value" : 0.0 }
78- assert isinstance (event ["attributes" ].get ("double" ).get ("double" ), float )
83+ assert isinstance (event ["attributes" ].get ("double" ).get ("double_value" ), float )
84+
85+ def _test_span_with_meta_event (self , _library_env , test_agent , test_library ):
86+ """Test adding a span event, with attributes, to an active span.
87+ Assumes meta format where all values are strings.
88+ """
89+ time0 = 123450
90+ name0 = "event_name"
91+ attributes0 = {
92+ "string" : "bar" ,
93+ "bool" : "true" ,
94+ "int" : "1" ,
95+ "double" : "2.3" ,
96+ "str_arr" : ["a" , "b" , "c" ],
97+ "bool_arr" : ["true" , "false" ],
98+ "int_arr" : ["5" , "6" ],
99+ "double_arr" : ["1.1" , "2.2" ],
100+ }
101+
102+ time1 = 123451
103+ name1 = "other_event"
104+ attributes1 = {"bool" : "false" , "int" : "0" , "double" : "0.0" }
79105
80- @pytest .mark .parametrize ("library_env" , [{"DD_TRACE_API_VERSION" : "v0.7" }])
106+ with test_library , test_library .otel_start_span ("test" ) as s :
107+ s .add_event (name0 , timestamp = time0 , attributes = attributes0 )
108+ s .add_event (name1 , timestamp = time1 , attributes = attributes1 )
109+
110+ traces = test_agent .wait_for_num_traces (1 )
111+
112+ trace = find_trace (traces , s .trace_id )
113+ assert len (trace ) == 1
114+ span = find_span (trace , s .span_id )
115+
116+ span_events = json .loads (span .get ("meta" , {}).get ("events" ))
117+
118+ assert len (span_events ) == 2
119+
120+ event = span_events [0 ]
121+ assert event ["time_unix_nano" ] == time0 * 1000000000
122+ assert event ["name" ] == name0
123+ assert event ["attributes" ].get ("string" ) == "bar"
124+ assert event ["attributes" ].get ("bool" ) == "true"
125+ assert event ["attributes" ].get ("int" ) == "1"
126+ assert event ["attributes" ].get ("double" ) == "2.3"
127+ assert event ["attributes" ].get ("str_arr" ) == ["a" , "b" , "c" ]
128+ assert event ["attributes" ].get ("bool_arr" ) == ["true" , "false" ]
129+ assert event ["attributes" ].get ("int_arr" ) == ["5" , "6" ]
130+ assert event ["attributes" ].get ("double_arr" ) == ["1.1" , "2.2" ]
131+
132+ event = span_events [1 ]
133+ assert event ["time_unix_nano" ] == time1 * 1000000000
134+ assert event ["name" ] == name1
135+ assert event ["attributes" ].get ("bool" ) == "false"
136+ assert event ["attributes" ].get ("int" ) == "0"
137+ assert isinstance (event ["attributes" ].get ("int" ), str )
138+ assert event ["attributes" ].get ("double" ) == "0.0"
139+ assert isinstance (event ["attributes" ].get ("double" ), str )
140+
141+ @irrelevant (library = "ruby" , reason = "Does not support v0.7" )
142+ @pytest .mark .parametrize ("library_env" , [{"DD_TRACE_API_VERSION" : "v0.7" , "DD_TRACE_NATIVE_SPAN_EVENTS" : "1" }])
81143 def test_span_with_event_v07 (self , library_env , test_agent , test_library ):
82144 """Test adding a span event in the v0.7 format, which support the native attribute representation."""
83145
84- self ._test_span_with_event (library_env , test_agent , test_library , lambda span : span [ "span_events" ] )
146+ self ._test_span_with_native_event (library_env , test_agent , test_library )
85147
86- @pytest .mark .parametrize ("library_env" , [{"DD_TRACE_API_VERSION" : "v0.4" }])
148+ @pytest .mark .parametrize ("library_env" , [{"DD_TRACE_API_VERSION" : "v0.4" , "DD_TRACE_NATIVE_SPAN_EVENTS" : "1" }])
87149 def test_span_with_event_v04 (self , library_env , test_agent , test_library ):
88150 """Test adding a span event in the v0.4 format, which support the native attribute representation."""
89151
90- self ._test_span_with_event (library_env , test_agent , test_library , lambda span : span [ "span_events" ] )
152+ self ._test_span_with_native_event (library_env , test_agent , test_library )
91153
92- @pytest .mark .parametrize ("library_env" , [{"DD_TRACE_API_VERSION" : "v0.5" }])
154+ @irrelevant (library = "ruby" , reason = "Does not support v0.5" )
155+ @pytest .mark .parametrize ("library_env" , [{"DD_TRACE_API_VERSION" : "v0.5" , "DD_TRACE_NATIVE_SPAN_EVENTS" : "1" }])
93156 def test_span_with_event_v05 (self , library_env , test_agent , test_library ):
94157 """Test adding a span event in the v0.5 format, which does not support the native attribute representation.
95- Thus span events are serialized as span tags.
158+ Thus span events are serialized as span tags, and attribute values all strings .
96159 """
97160
98- self ._test_span_with_event (
99- library_env , test_agent , test_library , lambda span : json .loads (span .get ("meta" , {}).get ("events" ))
100- )
161+ self ._test_span_with_meta_event (library_env , test_agent , test_library )
101162
163+ @pytest .mark .parametrize ("library_env" , [{"DD_TRACE_API_VERSION" : "v0.4" , "DD_TRACE_NATIVE_SPAN_EVENTS" : "1" }])
102164 def test_span_with_invalid_event_attributes (self , library_env , test_agent , test_library ):
103165 """Test adding a span event, with invalid attributes, to an active span.
104166 Span events with invalid attributes should be discarded.
167+ Valid attributes should be kept.
105168 """
106169
107170 with test_library , test_library .dd_start_span ("test" ) as s :
108171 s .add_event (
109172 "name" ,
110- timestamp = 123 ,
173+ time_unix_nano = 123 ,
111174 attributes = {
112175 "int" : 1 ,
113176 "invalid_arr1" : [1 , "a" ],
0 commit comments