11#![ cfg( unix) ]
22
3+ use std:: { fs:: File , os:: unix:: fs:: MetadataExt } ;
4+
35use integration_test_runner:: trace_asserter:: { read_spans_from_json, TraceAsserter } ;
4- use opentelemetry:: global;
56use opentelemetry:: trace:: TraceError ;
6- use opentelemetry:: {
7- trace:: { TraceContextExt , Tracer } ,
8- Key , KeyValue ,
9- } ;
107use opentelemetry_otlp:: SpanExporter ;
118
129use anyhow:: Result ;
1310use ctor:: dtor;
1411use integration_test_runner:: test_utils;
15- use opentelemetry_proto:: tonic:: trace:: v1:: TracesData ;
1612use opentelemetry_sdk:: { trace as sdktrace, Resource } ;
17- use std:: fs:: File ;
18- use std:: io:: Write ;
19- use std:: os:: unix:: fs:: MetadataExt ;
20- use std:: time:: Duration ;
21- use tokio:: time:: sleep;
2213
2314fn init_tracer_provider ( ) -> Result < sdktrace:: SdkTracerProvider , TraceError > {
2415 let exporter_builder = SpanExporter :: builder ( ) ;
@@ -44,46 +35,6 @@ fn init_tracer_provider() -> Result<sdktrace::SdkTracerProvider, TraceError> {
4435 . build ( ) )
4536}
4637
47- const LEMONS_KEY : Key = Key :: from_static_str ( "lemons" ) ;
48- const ANOTHER_KEY : Key = Key :: from_static_str ( "ex.com/another" ) ;
49-
50- #[ tokio:: test( flavor = "multi_thread" , worker_threads = 4 ) ]
51- #[ cfg( any( feature = "tonic-client" , feature = "reqwest-blocking-client" ) ) ]
52- pub async fn traces ( ) -> Result < ( ) > {
53- test_utils:: start_collector_container ( ) . await ?;
54-
55- let tracer_provider = init_tracer_provider ( ) . expect ( "Failed to initialize tracer provider." ) ;
56- global:: set_tracer_provider ( tracer_provider. clone ( ) ) ;
57-
58- let tracer = global:: tracer ( "ex.com/basic" ) ;
59-
60- tracer. in_span ( "operation" , |cx| {
61- let span = cx. span ( ) ;
62- span. add_event (
63- "Nice operation!" . to_string ( ) ,
64- vec ! [ KeyValue :: new( "bogons" , 100 ) ] ,
65- ) ;
66- span. set_attribute ( KeyValue :: new ( ANOTHER_KEY , "yes" ) ) ;
67-
68- tracer. in_span ( "Sub operation..." , |cx| {
69- let span = cx. span ( ) ;
70- span. set_attribute ( KeyValue :: new ( LEMONS_KEY , "five" ) ) ;
71-
72- span. add_event ( "Sub span event" , vec ! [ ] ) ;
73- } ) ;
74- } ) ;
75-
76- tracer_provider. shutdown ( ) ?;
77-
78- // Give it a second to flush
79- sleep ( Duration :: from_secs ( 2 ) ) . await ;
80-
81- // Validate results
82- assert_traces_results ( test_utils:: TRACES_FILE , "./expected/traces.json" ) ?;
83-
84- Ok ( ( ) )
85- }
86-
8738pub fn assert_traces_results ( result : & str , expected : & str ) -> Result < ( ) > {
8839 let left = read_spans_from_json ( File :: open ( expected) ?) ?;
8940 let right = read_spans_from_json ( File :: open ( result) ?) ?;
@@ -97,94 +48,164 @@ pub fn assert_traces_results(result: &str, expected: &str) -> Result<()> {
9748 Ok ( ( ) )
9849}
9950
100- #[ test]
101- #[ should_panic( expected = "left: \" Sub operation...\" " ) ] // we swap the parent spans with child spans in failed_traces.json
102- pub fn test_assert_span_eq_failure ( ) {
103- let left = read_spans_from_json ( File :: open ( "./expected/traces.json" ) . unwrap ( ) ) . unwrap ( ) ;
104- let right = read_spans_from_json ( File :: open ( "./expected/failed_traces.json" ) . unwrap ( ) ) . unwrap ( ) ;
105-
106- TraceAsserter :: new ( right, left) . assert ( ) ;
107- }
108-
109- #[ test]
110- pub fn test_assert_span_eq ( ) -> Result < ( ) > {
111- let spans = read_spans_from_json ( File :: open ( "./expected/traces.json" ) ?) ?;
112-
113- TraceAsserter :: new ( spans. clone ( ) , spans) . assert ( ) ;
114-
115- Ok ( ( ) )
116- }
117-
118- #[ test]
119- pub fn test_serde ( ) -> Result < ( ) > {
120- let spans = read_spans_from_json (
121- File :: open ( "./expected/traces.json" ) . expect ( "Failed to read traces.json" ) ,
122- ) ?;
123- let json = serde_json:: to_string_pretty ( & TracesData {
124- resource_spans : spans,
125- } )
126- . expect ( "Failed to serialize spans to json" ) ;
127-
128- // Write to file.
129- let mut file = File :: create ( "./expected/serialized_traces.json" ) . unwrap ( ) ;
130- file. write_all ( json. as_bytes ( ) ) . unwrap ( ) ;
131-
132- let left = read_spans_from_json (
133- File :: open ( "./expected/traces.json" ) . expect ( "Failed to read traces.json" ) ,
134- ) ?;
135- let right = read_spans_from_json (
136- File :: open ( "./expected/serialized_traces.json" )
137- . expect ( "Failed to read serialized_traces.json" ) ,
138- ) ?;
139-
140- TraceAsserter :: new ( left, right) . assert ( ) ;
141-
142- Ok ( ( ) )
143- }
144-
145- #[ ignore = "TODO: [Fix Me] Failing on CI. Needs to be investigated and resolved." ]
146- #[ test]
147- #[ cfg( any( feature = "tonic-client" , feature = "reqwest-blocking-client" ) ) ]
148- pub fn span_batch_non_tokio_main ( ) -> Result < ( ) > {
149- // Initialize the tracer provider inside a tokio runtime
150- // as this allows tonic client to capture the runtime,
151- // but actual export occurs from the dedicated std::thread
152- // created by BatchSpanProcessor.
153-
51+ #[ cfg( test) ]
52+ mod tracetests {
15453 use anyhow:: Ok ;
155- let rt = tokio:: runtime:: Runtime :: new ( ) ?;
156- let tracer_provider = rt. block_on ( async {
157- // While we're here setup our collector container too, as this needs tokio to run
158- let _ = test_utils:: start_collector_container ( ) . await ;
159- init_tracer_provider ( )
160- } ) ?;
161-
162- let tracer = global:: tracer ( "ex.com/basic" ) ;
163-
164- tracer. in_span ( "operation" , |cx| {
165- let span = cx. span ( ) ;
166- span. add_event (
167- "Nice operation!" . to_string ( ) ,
168- vec ! [ KeyValue :: new( "bogons" , 100 ) ] ,
169- ) ;
170- span. set_attribute ( KeyValue :: new ( ANOTHER_KEY , "yes" ) ) ;
171-
172- tracer. in_span ( "Sub operation..." , |cx| {
54+ use anyhow:: Result ;
55+ use integration_test_runner:: test_utils;
56+ use integration_test_runner:: trace_asserter:: { read_spans_from_json, TraceAsserter } ;
57+ use opentelemetry:: Key ;
58+ use opentelemetry:: {
59+ global,
60+ trace:: { TraceContextExt , Tracer } ,
61+ KeyValue ,
62+ } ;
63+ use opentelemetry_proto:: tonic:: trace:: v1:: TracesData ;
64+ use std:: fs:: File ;
65+ use std:: io:: Write ;
66+ use std:: time:: Duration ;
67+ use tokio:: time:: sleep;
68+
69+ use crate :: { assert_traces_results, init_tracer_provider} ;
70+
71+ const LEMONS_KEY : Key = Key :: from_static_str ( "lemons" ) ;
72+ const ANOTHER_KEY : Key = Key :: from_static_str ( "ex.com/another" ) ;
73+
74+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 4 ) ]
75+ #[ cfg( any( feature = "tonic-client" , feature = "reqwest-blocking-client" ) ) ]
76+ pub async fn traces ( ) -> Result < ( ) > {
77+ use opentelemetry:: {
78+ global,
79+ trace:: { TraceContextExt , Tracer } ,
80+ KeyValue ,
81+ } ;
82+
83+ use crate :: { assert_traces_results, init_tracer_provider} ;
84+
85+ test_utils:: start_collector_container ( ) . await ?;
86+
87+ let tracer_provider =
88+ init_tracer_provider ( ) . expect ( "Failed to initialize tracer provider." ) ;
89+ global:: set_tracer_provider ( tracer_provider. clone ( ) ) ;
90+
91+ let tracer = global:: tracer ( "ex.com/basic" ) ;
92+
93+ tracer. in_span ( "operation" , |cx| {
17394 let span = cx. span ( ) ;
174- span. set_attribute ( KeyValue :: new ( LEMONS_KEY , "five" ) ) ;
95+ span. add_event (
96+ "Nice operation!" . to_string ( ) ,
97+ vec ! [ KeyValue :: new( "bogons" , 100 ) ] ,
98+ ) ;
99+ span. set_attribute ( KeyValue :: new ( ANOTHER_KEY , "yes" ) ) ;
100+
101+ tracer. in_span ( "Sub operation..." , |cx| {
102+ let span = cx. span ( ) ;
103+ span. set_attribute ( KeyValue :: new ( LEMONS_KEY , "five" ) ) ;
104+
105+ span. add_event ( "Sub span event" , vec ! [ ] ) ;
106+ } ) ;
107+ } ) ;
175108
176- span. add_event ( "Sub span event" , vec ! [ ] ) ;
109+ tracer_provider. shutdown ( ) ?;
110+
111+ // Give it a second to flush
112+ sleep ( Duration :: from_secs ( 5 ) ) . await ;
113+
114+ // Validate results
115+ assert_traces_results ( test_utils:: TRACES_FILE , "./expected/traces.json" ) ?;
116+
117+ Ok ( ( ) )
118+ }
119+
120+ #[ test]
121+ #[ should_panic( expected = "left: \" Sub operation...\" " ) ] // we swap the parent spans with child spans in failed_traces.json
122+ pub fn test_assert_span_eq_failure ( ) {
123+ let left = read_spans_from_json ( File :: open ( "./expected/traces.json" ) . unwrap ( ) ) . unwrap ( ) ;
124+ let right =
125+ read_spans_from_json ( File :: open ( "./expected/failed_traces.json" ) . unwrap ( ) ) . unwrap ( ) ;
126+
127+ TraceAsserter :: new ( right, left) . assert ( ) ;
128+ }
129+
130+ #[ test]
131+ pub fn test_assert_span_eq ( ) -> Result < ( ) > {
132+ let spans = read_spans_from_json ( File :: open ( "./expected/traces.json" ) ?) ?;
133+
134+ TraceAsserter :: new ( spans. clone ( ) , spans) . assert ( ) ;
135+
136+ Ok ( ( ) )
137+ }
138+
139+ #[ test]
140+ pub fn test_serde ( ) -> Result < ( ) > {
141+ let spans = read_spans_from_json (
142+ File :: open ( "./expected/traces.json" ) . expect ( "Failed to read traces.json" ) ,
143+ ) ?;
144+ let json = serde_json:: to_string_pretty ( & TracesData {
145+ resource_spans : spans,
146+ } )
147+ . expect ( "Failed to serialize spans to json" ) ;
148+
149+ // Write to file.
150+ let mut file = File :: create ( "./expected/serialized_traces.json" ) . unwrap ( ) ;
151+ file. write_all ( json. as_bytes ( ) ) . unwrap ( ) ;
152+
153+ let left = read_spans_from_json (
154+ File :: open ( "./expected/traces.json" ) . expect ( "Failed to read traces.json" ) ,
155+ ) ?;
156+ let right = read_spans_from_json (
157+ File :: open ( "./expected/serialized_traces.json" )
158+ . expect ( "Failed to read serialized_traces.json" ) ,
159+ ) ?;
160+
161+ TraceAsserter :: new ( left, right) . assert ( ) ;
162+
163+ Ok ( ( ) )
164+ }
165+
166+ #[ ignore = "TODO: [Fix Me] Failing on CI. Needs to be investigated and resolved." ]
167+ #[ test]
168+ #[ cfg( any( feature = "tonic-client" , feature = "reqwest-blocking-client" ) ) ]
169+ pub fn span_batch_non_tokio_main ( ) -> Result < ( ) > {
170+ // Initialize the tracer provider inside a tokio runtime
171+ // as this allows tonic client to capture the runtime,
172+ // but actual export occurs from the dedicated std::thread
173+ // created by BatchSpanProcessor.
174+
175+ let rt = tokio:: runtime:: Runtime :: new ( ) ?;
176+ let tracer_provider = rt. block_on ( async {
177+ // While we're here setup our collector container too, as this needs tokio to run
178+ let _ = test_utils:: start_collector_container ( ) . await ;
179+ init_tracer_provider ( )
180+ } ) ?;
181+
182+ let tracer = global:: tracer ( "ex.com/basic" ) ;
183+
184+ tracer. in_span ( "operation" , |cx| {
185+ let span = cx. span ( ) ;
186+ span. add_event (
187+ "Nice operation!" . to_string ( ) ,
188+ vec ! [ KeyValue :: new( "bogons" , 100 ) ] ,
189+ ) ;
190+ span. set_attribute ( KeyValue :: new ( ANOTHER_KEY , "yes" ) ) ;
191+
192+ tracer. in_span ( "Sub operation..." , |cx| {
193+ let span = cx. span ( ) ;
194+ span. set_attribute ( KeyValue :: new ( LEMONS_KEY , "five" ) ) ;
195+
196+ span. add_event ( "Sub span event" , vec ! [ ] ) ;
197+ } ) ;
177198 } ) ;
178- } ) ;
179199
180- tracer_provider. shutdown ( ) ?;
200+ tracer_provider. shutdown ( ) ?;
181201
182- // Give it a second to flush
183- std:: thread:: sleep ( Duration :: from_secs ( 2 ) ) ;
202+ // Give it a second to flush
203+ std:: thread:: sleep ( Duration :: from_secs ( 5 ) ) ;
184204
185- // Validate results
186- assert_traces_results ( test_utils:: TRACES_FILE , "./expected/traces.json" ) ?;
187- Ok ( ( ) )
205+ // Validate results
206+ assert_traces_results ( test_utils:: TRACES_FILE , "./expected/traces.json" ) ?;
207+ Ok ( ( ) )
208+ }
188209}
189210
190211///
0 commit comments