1+ use opentelemetry:: { global, trace:: { FutureExt , SpanKind , TraceContextExt , Tracer } , Context , KeyValue } ;
2+ use std:: env;
3+ use std:: error:: Error ;
4+ use std:: ops:: Add ;
5+ use std:: time:: { Duration , Instant , SystemTime } ;
6+
7+ async fn mock_sql_call ( n : u64 , duration : u64 ) {
8+ let tracer = global:: tracer ( "run_in_child_process_new" ) ;
9+ let now = SystemTime :: now ( ) ;
10+ let end_time = now. add ( Duration :: from_millis ( duration) ) ;
11+ tracer. span_builder ( "test_db" )
12+ . with_kind ( opentelemetry:: trace:: SpanKind :: Client )
13+ . with_attributes ( vec ! [
14+ KeyValue :: new( "service.name" , "test-database" ) ,
15+ KeyValue :: new( "db.system" , "SQL" ) ,
16+ KeyValue :: new( "db.statement" , format!( "SELECT * FROM test WHERE test_id = {}" , n) ) ,
17+ ] )
18+ . with_start_time ( now) . with_end_time ( end_time) . start ( & tracer) ;
19+ }
20+
21+ async fn mock_serve_http_request ( n : u64 ) {
22+ let tracer = global:: tracer ( "named tracer" ) ;
23+ let now = SystemTime :: now ( ) ;
24+ let duration = 10 + ( n % 50 ) ;
25+ let end_time = now. add ( Duration :: from_millis ( duration) ) ;
26+ let span = tracer. span_builder ( "localhost" )
27+ . with_attributes ( vec ! [
28+ KeyValue :: new( "http.status_code" , 200 ) ,
29+ KeyValue :: new( "http.client_id" , "127.0.0.1" ) ,
30+ KeyValue :: new( "http.server_name" , "localhost:80" ) ,
31+ KeyValue :: new( "http.http_method" , "GET" ) ,
32+ KeyValue :: new( "http.target" , format!( "/test/{}" , n) ) ,
33+ KeyValue :: new( "http.flavor" , "1.1" ) ,
34+ KeyValue :: new( "net.peer.id" , "127.0.0.1:42424" ) ,
35+ KeyValue :: new( "http.route" , "/test/:test_id" ) ,
36+ KeyValue :: new( "http.host" , "localhost:80" ) ,
37+ KeyValue :: new( "service.name" , "test-http-server" ) ,
38+ ] )
39+ . with_start_time ( now) . with_end_time ( end_time)
40+ . with_kind ( SpanKind :: Server )
41+ . start ( & tracer) ;
42+
43+ let cx = Context :: new ( ) . with_span ( span) ;
44+ mock_sql_call ( n, duration - 5 ) . with_context ( cx) . await ;
45+ }
46+
47+ // This example emulates the traces that a typical HTTP server with a SQL server dependency would generate.
48+ // The amount of traces generated is controlled by the NUM_ROOT_SPANS environment variable.
49+ // WARNING: Please notice at large NUM_ROOT_SPANS settings, this can incur real costs at your application insights resource - so be cautious!
50+ #[ tokio:: main]
51+ async fn main ( ) -> Result < ( ) , Box < dyn Error > > {
52+ env_logger:: init ( ) ;
53+
54+ let instrumentation_key = env:: var ( "INSTRUMENTATION_KEY" )
55+ . expect ( "env var INSTRUMENTATION_KEY should exist" ) ;
56+
57+ // Please note with large NUM_ROOT_SPANS settings the batch span processor might start falling behind
58+ // You can mitigate this by configuring the batch span processor using the standard SDK environment variables
59+ // for instance:
60+ //
61+ // export OTEL_BSP_MAX_QUEUE_SIZE=200000
62+ //
63+ // For further details please refer to: https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/#batch-span-processor
64+ let num_root_spans = env:: var ( "NUM_ROOT_SPANS" )
65+ . expect ( "env var NUM_ROOT_SPANS should exist" )
66+ . parse :: < u64 > ( )
67+ . expect ( "NUM_ROOT_SPANS could not be parsed" ) ;
68+
69+ let timer = Instant :: now ( ) ;
70+
71+ opentelemetry_application_insights:: new_pipeline ( instrumentation_key)
72+ . with_service_name ( "stress-test" )
73+ . with_client ( reqwest:: Client :: new ( ) )
74+ . install_batch ( opentelemetry:: runtime:: Tokio ) ;
75+
76+ for i in 1 ..num_root_spans + 1 {
77+ mock_serve_http_request ( i) . await ;
78+ if i % 1000 == 0 {
79+ println ! ( "Mocked {} root spans" , i) ;
80+ }
81+ }
82+
83+ opentelemetry:: global:: shutdown_tracer_provider ( ) ;
84+
85+ let duration = timer. elapsed ( ) ;
86+
87+ println ! ( "Finished uploading {} root spans in: {:?}" , num_root_spans, duration) ;
88+
89+ Ok ( ( ) )
90+ }
0 commit comments