1
1
#![ cfg( unix) ]
2
2
3
+ use std:: { fs:: File , os:: unix:: fs:: MetadataExt } ;
4
+
3
5
use integration_test_runner:: trace_asserter:: { read_spans_from_json, TraceAsserter } ;
4
- use opentelemetry:: global;
5
6
use opentelemetry:: trace:: TraceError ;
6
- use opentelemetry:: {
7
- trace:: { TraceContextExt , Tracer } ,
8
- Key , KeyValue ,
9
- } ;
10
7
use opentelemetry_otlp:: SpanExporter ;
11
8
12
9
use anyhow:: Result ;
13
10
use ctor:: dtor;
14
11
use integration_test_runner:: test_utils;
15
- use opentelemetry_proto:: tonic:: trace:: v1:: TracesData ;
16
12
use 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;
22
13
23
14
fn init_tracer_provider ( ) -> Result < sdktrace:: SdkTracerProvider , TraceError > {
24
15
let exporter_builder = SpanExporter :: builder ( ) ;
@@ -44,46 +35,6 @@ fn init_tracer_provider() -> Result<sdktrace::SdkTracerProvider, TraceError> {
44
35
. build ( ) )
45
36
}
46
37
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
-
87
38
pub fn assert_traces_results ( result : & str , expected : & str ) -> Result < ( ) > {
88
39
let left = read_spans_from_json ( File :: open ( expected) ?) ?;
89
40
let right = read_spans_from_json ( File :: open ( result) ?) ?;
@@ -97,94 +48,164 @@ pub fn assert_traces_results(result: &str, expected: &str) -> Result<()> {
97
48
Ok ( ( ) )
98
49
}
99
50
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 {
154
53
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| {
173
94
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
+ } ) ;
175
108
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
+ } ) ;
177
198
} ) ;
178
- } ) ;
179
199
180
- tracer_provider. shutdown ( ) ?;
200
+ tracer_provider. shutdown ( ) ?;
181
201
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 ) ) ;
184
204
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
+ }
188
209
}
189
210
190
211
///
0 commit comments