22
33use anyhow:: Result ;
44use ctor:: dtor;
5- use integration_test_runner:: logs_asserter:: { read_logs_from_json, LogsAsserter } ;
65use integration_test_runner:: test_utils;
6+ use opentelemetry_appender_tracing:: layer:: OpenTelemetryTracingBridge ;
77use opentelemetry_otlp:: LogExporter ;
88use opentelemetry_sdk:: logs:: LoggerProvider ;
99use opentelemetry_sdk:: { logs as sdklogs, Resource } ;
1010use std:: fs:: File ;
1111use std:: io:: Read ;
12- use std:: os:: unix:: fs:: MetadataExt ;
12+ use std:: time:: Duration ;
13+ use tracing:: info;
14+ use tracing_subscriber:: layer:: SubscriberExt ;
15+ use uuid:: Uuid ;
1316
1417fn init_logs ( is_simple : bool ) -> Result < sdklogs:: LoggerProvider > {
1518 let exporter_builder = LogExporter :: builder ( ) ;
@@ -43,25 +46,85 @@ fn init_logs(is_simple: bool) -> Result<sdklogs::LoggerProvider> {
4346 Ok ( logger_provider)
4447}
4548
49+ async fn logs_tokio_helper ( is_simple : bool ) -> Result < ( ) > {
50+ use crate :: { assert_logs_results_contains, init_logs} ;
51+ test_utils:: start_collector_container ( ) . await ?;
52+
53+ let logger_provider = init_logs ( is_simple) . unwrap ( ) ;
54+ let layer = OpenTelemetryTracingBridge :: new ( & logger_provider) ;
55+ let subscriber = tracing_subscriber:: registry ( ) . with ( layer) ;
56+ // generate a random uuid and store it to expected guid
57+ let expected_uuid = Uuid :: new_v4 ( ) . to_string ( ) ;
58+ {
59+ let _guard = tracing:: subscriber:: set_default ( subscriber) ;
60+ info ! ( target: "my-target" , uuid = expected_uuid, "hello from {}. My price is {}." , "banana" , 2.99 ) ;
61+ }
62+
63+ let _ = logger_provider. shutdown ( ) ;
64+ tokio:: time:: sleep ( Duration :: from_secs ( 5 ) ) . await ;
65+ assert_logs_results_contains ( test_utils:: LOGS_FILE , expected_uuid. as_str ( ) ) ?;
66+ Ok ( ( ) )
67+ }
68+
69+ fn logs_non_tokio_helper ( is_simple : bool , init_logs_inside_rt : bool ) -> Result < ( ) > {
70+ let rt = tokio:: runtime:: Runtime :: new ( ) ?;
71+ let logger_provider = if init_logs_inside_rt {
72+ // Initialize the logger provider inside the Tokio runtime
73+ rt. block_on ( async {
74+ // Setup the collector container inside Tokio runtime
75+ test_utils:: start_collector_container ( ) . await ?;
76+ init_logs ( is_simple)
77+ } ) ?
78+ } else {
79+ // Initialize the logger provider outside the Tokio runtime
80+ rt. block_on ( async {
81+ let _ = test_utils:: start_collector_container ( ) . await ;
82+ } ) ;
83+ init_logs ( is_simple) ?
84+ } ;
85+
86+ let layer = OpenTelemetryTracingBridge :: new ( & logger_provider) ;
87+ let subscriber = tracing_subscriber:: registry ( ) . with ( layer) ;
88+
89+ // Generate a random UUID and store it to expected guid
90+ let expected_uuid = Uuid :: new_v4 ( ) . to_string ( ) ;
91+ {
92+ let _guard = tracing:: subscriber:: set_default ( subscriber) ;
93+ info ! (
94+ target: "my-target" ,
95+ uuid = expected_uuid,
96+ "hello from {}. My price is {}." ,
97+ "banana" ,
98+ 2.99
99+ ) ;
100+ }
101+
102+ let _ = logger_provider. shutdown ( ) ;
103+ std:: thread:: sleep ( Duration :: from_secs ( 5 ) ) ;
104+ assert_logs_results_contains ( test_utils:: LOGS_FILE , expected_uuid. as_str ( ) ) ?;
105+ Ok ( ( ) )
106+ }
107+
108+ fn assert_logs_results_contains ( result : & str , expected_content : & str ) -> Result < ( ) > {
109+ let file = File :: open ( result) ?;
110+ let mut contents = String :: new ( ) ;
111+ let mut reader = std:: io:: BufReader :: new ( & file) ;
112+ reader. read_to_string ( & mut contents) ?;
113+ assert ! ( contents. contains( expected_content) ) ;
114+ Ok ( ( ) )
115+ }
116+
46117#[ cfg( test) ]
47118mod logtests {
48- // TODO: The tests in this mod works like below: Emit a log with a UUID,
119+ // The tests in this mod works like below: Emit a log with a UUID,
49120 // then read the logs from the file and check if the UUID is present in the
50121 // logs. This makes it easy to validate with a single collector and its
51122 // output. This is a very simple test but good enough to validate that OTLP
52- // Exporter did work! A more comprehensive test would be to validate the
53- // entire Payload. The infra for it already exists (logs_asserter.rs), the
54- // TODO here is to write a test that validates the entire payload.
123+ // Exporter did work!
55124
56125 use super :: * ;
57126 use integration_test_runner:: logs_asserter:: { read_logs_from_json, LogsAsserter } ;
58- use integration_test_runner:: test_utils;
59- use opentelemetry_appender_tracing:: layer;
60- use opentelemetry_appender_tracing:: layer:: OpenTelemetryTracingBridge ;
61- use std:: { fs:: File , time:: Duration } ;
62- use tracing:: info;
63- use tracing_subscriber:: layer:: SubscriberExt ;
64- use uuid:: Uuid ;
127+ use std:: fs:: File ;
65128
66129 #[ test]
67130 #[ should_panic( expected = "assertion `left == right` failed: body does not match" ) ]
@@ -87,6 +150,8 @@ mod logtests {
87150 Ok ( ( ) )
88151 }
89152
153+ // Batch Processor
154+
90155 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 4 ) ]
91156 #[ cfg( any( feature = "tonic-client" , feature = "reqwest-blocking-client" ) ) ]
92157 pub async fn logs_batch_tokio_multi_thread ( ) -> Result < ( ) > {
@@ -105,104 +170,63 @@ mod logtests {
105170 logs_tokio_helper ( false ) . await
106171 }
107172
108- async fn logs_tokio_helper ( is_simple : bool ) -> Result < ( ) > {
109- use crate :: { assert_logs_results_contains, init_logs} ;
110- test_utils:: start_collector_container ( ) . await ?;
111-
112- let logger_provider = init_logs ( is_simple) . unwrap ( ) ;
113- let layer = OpenTelemetryTracingBridge :: new ( & logger_provider) ;
114- let subscriber = tracing_subscriber:: registry ( ) . with ( layer) ;
115- // generate a random uuid and store it to expected guid
116- let expected_uuid = Uuid :: new_v4 ( ) . to_string ( ) ;
117- {
118- let _guard = tracing:: subscriber:: set_default ( subscriber) ;
119- info ! ( target: "my-target" , uuid = expected_uuid, "hello from {}. My price is {}." , "banana" , 2.99 ) ;
120- }
121-
122- let _ = logger_provider. shutdown ( ) ;
123- tokio:: time:: sleep ( Duration :: from_secs ( 5 ) ) . await ;
124- assert_logs_results_contains ( test_utils:: LOGS_FILE , expected_uuid. as_str ( ) ) ?;
125- Ok ( ( ) )
173+ #[ test]
174+ #[ cfg( any( feature = "tonic-client" , feature = "reqwest-blocking-client" ) ) ]
175+ pub fn logs_batch_non_tokio_main_init_logs_inside_rt ( ) -> Result < ( ) > {
176+ logs_non_tokio_helper ( false , true )
177+ }
178+
179+ #[ test]
180+ #[ cfg( feature = "reqwest-blocking-client" ) ]
181+ pub fn logs_batch_non_tokio_main_with_init_logs_outside_rt ( ) -> Result < ( ) > {
182+ logs_non_tokio_helper ( false , false )
183+ }
184+
185+ // Simple Processor
186+
187+ #[ test]
188+ #[ cfg( any( feature = "tonic-client" , feature = "reqwest-blocking-client" ) ) ]
189+ pub fn logs_simple_non_tokio_main_with_init_logs_inside_rt ( ) -> Result < ( ) > {
190+ logs_non_tokio_helper ( true , true )
191+ }
192+
193+ #[ test]
194+ #[ cfg( any( feature = "reqwest-blocking-client" ) ) ]
195+ pub fn logs_simple_non_tokio_main_with_init_logs_outsie_rt ( ) -> Result < ( ) > {
196+ logs_non_tokio_helper ( true , false )
126197 }
127198
128199 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 4 ) ]
129- #[ cfg( any( feature = "tonic-client" , feature = "reqwest-client" ) ) ]
200+ #[ cfg( any(
201+ feature = "tonic-client" ,
202+ feature = "reqwest-client" ,
203+ feature = "hyper-client"
204+ ) ) ]
130205 pub async fn logs_simple_tokio_multi_thread ( ) -> Result < ( ) > {
131206 logs_tokio_helper ( true ) . await
132207 }
133208
134209 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
135- #[ cfg( any( feature = "tonic-client" , feature = "reqwest-client" ) ) ]
210+ #[ cfg( any(
211+ feature = "tonic-client" ,
212+ feature = "reqwest-client" ,
213+ feature = "hyper-client"
214+ ) ) ]
136215 pub async fn logs_simple_tokio_multi_with_one_worker ( ) -> Result < ( ) > {
137216 logs_tokio_helper ( true ) . await
138217 }
139218
140- // Ignored, to be investigated
141- #[ ignore]
219+ #[ ignore] // https://github.com/open-telemetry/opentelemetry-rust/issues/2539
142220 #[ tokio:: test( flavor = "current_thread" ) ]
143- #[ cfg( any( feature = "tonic-client" , feature = "reqwest-client" ) ) ]
221+ #[ cfg( any(
222+ feature = "tonic-client" ,
223+ feature = "reqwest-client" ,
224+ feature = "hyper-client"
225+ ) ) ]
144226 pub async fn logs_simple_tokio_current ( ) -> Result < ( ) > {
145227 logs_tokio_helper ( true ) . await
146228 }
147-
148- #[ test]
149- #[ cfg( any( feature = "tonic-client" , feature = "reqwest-blocking-client" ) ) ]
150- pub fn logs_batch_non_tokio_main ( ) -> Result < ( ) > {
151- logs_non_tokio_helper ( false )
152- }
153-
154- fn logs_non_tokio_helper ( is_simple : bool ) -> Result < ( ) > {
155- // Initialize the logger provider inside a tokio runtime
156- // as this allows tonic client to capture the runtime,
157- // but actual export occurs from the dedicated std::thread
158- // created by BatchLogProcessor.
159- let rt = tokio:: runtime:: Runtime :: new ( ) ?;
160- let logger_provider = rt. block_on ( async {
161- // While we're here setup our collector container too, as this needs tokio to run
162- test_utils:: start_collector_container ( ) . await ?;
163- init_logs ( is_simple)
164- } ) ?;
165- let layer = layer:: OpenTelemetryTracingBridge :: new ( & logger_provider) ;
166- let subscriber = tracing_subscriber:: registry ( ) . with ( layer) ;
167- // generate a random uuid and store it to expected guid
168- let expected_uuid = Uuid :: new_v4 ( ) . to_string ( ) ;
169- {
170- let _guard = tracing:: subscriber:: set_default ( subscriber) ;
171- info ! ( target: "my-target" , uuid = expected_uuid, "hello from {}. My price is {}." , "banana" , 2.99 ) ;
172- }
173-
174- let _ = logger_provider. shutdown ( ) ;
175- std:: thread:: sleep ( Duration :: from_secs ( 5 ) ) ;
176- assert_logs_results_contains ( test_utils:: LOGS_FILE , expected_uuid. as_str ( ) ) ?;
177- Ok ( ( ) )
178- }
179-
180- #[ test]
181- #[ cfg( any( feature = "tonic-client" , feature = "reqwest-blocking-client" ) ) ]
182- pub fn logs_simple_non_tokio_main ( ) -> Result < ( ) > {
183- logs_non_tokio_helper ( true )
184- }
185- }
186-
187- pub fn assert_logs_results_contains ( result : & str , expected_content : & str ) -> Result < ( ) > {
188- let file = File :: open ( result) ?;
189- let mut contents = String :: new ( ) ;
190- let mut reader = std:: io:: BufReader :: new ( & file) ;
191- reader. read_to_string ( & mut contents) ?;
192- assert ! ( contents. contains( expected_content) ) ;
193- Ok ( ( ) )
194229}
195-
196- pub fn assert_logs_results ( result : & str , expected : & str ) -> Result < ( ) > {
197- let left = read_logs_from_json ( File :: open ( expected) ?) ?;
198- let right = read_logs_from_json ( File :: open ( result) ?) ?;
199-
200- LogsAsserter :: new ( left, right) . assert ( ) ;
201-
202- assert ! ( File :: open( result) . unwrap( ) . metadata( ) . unwrap( ) . size( ) > 0 ) ;
203- Ok ( ( ) )
204- }
205-
206230///
207231/// Make sure we stop the collector container, otherwise it will sit around hogging our
208232/// ports and subsequent test runs will fail.
0 commit comments