1
1
#[ cfg( feature = "activate_context" ) ]
2
2
use crate :: stack:: IdValueStack ;
3
- use crate :: OtelData ;
3
+ use crate :: { OtelData , OtelDataState } ;
4
4
#[ cfg( feature = "activate_context" ) ]
5
5
use opentelemetry:: ContextGuard ;
6
6
use opentelemetry:: {
@@ -9,12 +9,12 @@ use opentelemetry::{
9
9
} ;
10
10
#[ cfg( feature = "activate_context" ) ]
11
11
use std:: cell:: RefCell ;
12
- use std:: marker;
13
12
use std:: thread;
14
13
#[ cfg( not( all( target_arch = "wasm32" , not( target_os = "wasi" ) ) ) ) ]
15
14
use std:: time:: Instant ;
16
15
use std:: { any:: TypeId , borrow:: Cow } ;
17
16
use std:: { fmt, vec} ;
17
+ use std:: { marker, mem:: take} ;
18
18
use tracing_core:: span:: { self , Attributes , Id , Record } ;
19
19
use tracing_core:: { field, Event , Subscriber } ;
20
20
#[ cfg( feature = "tracing-log" ) ]
@@ -165,16 +165,7 @@ struct SpanBuilderUpdates {
165
165
}
166
166
167
167
impl SpanBuilderUpdates {
168
- fn update ( self , span_builder : & mut Option < SpanBuilder > ) -> Option < Self > {
169
- if let Some ( builder) = span_builder. as_mut ( ) {
170
- self . apply ( builder) ;
171
- None
172
- } else {
173
- Some ( self )
174
- }
175
- }
176
-
177
- fn apply ( self , span_builder : & mut SpanBuilder ) {
168
+ fn update ( self , span_builder : & mut SpanBuilder ) {
178
169
let Self {
179
170
name,
180
171
span_kind,
@@ -970,15 +961,26 @@ where
970
961
/// the context in the process.
971
962
///
972
963
fn start_cx ( & self , otel_data : & mut OtelData ) {
973
- if let Some ( builder) = otel_data. builder . take ( ) {
974
- let span = builder. start_with_context ( & self . tracer , & otel_data. parent_cx ) ;
975
- otel_data. parent_cx = otel_data. parent_cx . with_span ( span) ;
964
+ if let OtelDataState :: Context { .. } = & otel_data. state {
965
+ // If the context is already started, we do nothing.
966
+ } else {
967
+ match take ( & mut otel_data. state ) {
968
+ OtelDataState :: Builder { builder, parent_cx } => {
969
+ let span = builder. start_with_context ( & self . tracer , & parent_cx) ;
970
+ let current_cx = parent_cx. with_span ( span) ;
971
+ otel_data. state = OtelDataState :: Context { current_cx } ;
972
+ }
973
+ _ => ( ) , // This should never happen.
974
+ }
976
975
}
977
976
}
978
977
979
978
fn with_started_cx < U > ( & self , otel_data : & mut OtelData , f : & dyn Fn ( & OtelContext ) -> U ) -> U {
980
979
self . start_cx ( otel_data) ;
981
- f ( & otel_data. parent_cx )
980
+ match & otel_data. state {
981
+ OtelDataState :: Context { current_cx, .. } => f ( current_cx) ,
982
+ _ => panic ! ( "OtelDataState should be a Context after starting it; this is a bug!" ) ,
983
+ }
982
984
}
983
985
}
984
986
@@ -1071,12 +1073,10 @@ where
1071
1073
sem_conv_config : self . sem_conv_config ,
1072
1074
} ) ;
1073
1075
1074
- let mut builder = Some ( builder) ;
1075
1076
updates. update ( & mut builder) ;
1076
1077
extensions. insert ( OtelData {
1077
- builder,
1078
- parent_cx,
1079
- ..Default :: default ( )
1078
+ state : OtelDataState :: Builder { builder, parent_cx } ,
1079
+ end_time : None ,
1080
1080
} ) ;
1081
1081
}
1082
1082
@@ -1097,6 +1097,10 @@ where
1097
1097
GUARD_STACK . with ( |stack| stack. borrow_mut ( ) . push ( id. clone ( ) , guard) ) ;
1098
1098
} ) ;
1099
1099
}
1100
+
1101
+ if !self . tracked_inactivity {
1102
+ return ;
1103
+ }
1100
1104
}
1101
1105
1102
1106
if let Some ( timings) = extensions. get_mut :: < Timings > ( ) {
@@ -1145,8 +1149,15 @@ where
1145
1149
} ) ;
1146
1150
let mut extensions = span. extensions_mut ( ) ;
1147
1151
if let Some ( otel_data) = extensions. get_mut :: < OtelData > ( ) {
1148
- if let Some ( updates) = updates. update ( & mut otel_data. builder ) {
1149
- updates. update_span ( & otel_data. parent_cx . span ( ) ) ;
1152
+ match & mut otel_data. state {
1153
+ OtelDataState :: Builder { builder, .. } => {
1154
+ // If the builder is present, then update it.
1155
+ updates. update ( builder) ;
1156
+ }
1157
+ OtelDataState :: Context { current_cx, .. } => {
1158
+ // If the Context has been created, then update the span.
1159
+ updates. update_span ( & current_cx. span ( ) ) ;
1160
+ }
1150
1161
}
1151
1162
}
1152
1163
}
@@ -1168,14 +1179,17 @@ where
1168
1179
. expect ( "Missing otel data span extensions" ) ;
1169
1180
let follows_context =
1170
1181
self . with_started_cx ( follows_data, & |cx| cx. span ( ) . span_context ( ) . clone ( ) ) ;
1171
- if let Some ( builder) = data. builder . as_mut ( ) {
1172
- if let Some ( ref mut links) = builder. links {
1173
- links. push ( otel:: Link :: with_context ( follows_context) ) ;
1174
- } else {
1175
- builder. links = Some ( vec ! [ otel:: Link :: with_context( follows_context) ] ) ;
1182
+ match & mut data. state {
1183
+ OtelDataState :: Builder { builder, .. } => {
1184
+ if let Some ( ref mut links) = builder. links {
1185
+ links. push ( otel:: Link :: with_context ( follows_context) ) ;
1186
+ } else {
1187
+ builder. links = Some ( vec ! [ otel:: Link :: with_context( follows_context) ] ) ;
1188
+ }
1189
+ }
1190
+ OtelDataState :: Context { current_cx, .. } => {
1191
+ current_cx. span ( ) . add_link ( follows_context, vec ! [ ] ) ;
1176
1192
}
1177
- } else {
1178
- data. parent_cx . span ( ) . add_link ( follows_context, vec ! [ ] ) ;
1179
1193
}
1180
1194
}
1181
1195
}
@@ -1280,33 +1294,36 @@ where
1280
1294
}
1281
1295
}
1282
1296
1283
- if let Some ( builder) = otel_data. builder . as_mut ( ) {
1284
- if builder. status == otel:: Status :: Unset
1285
- && * meta. level ( ) == tracing_core:: Level :: ERROR
1286
- {
1287
- builder. status = otel:: Status :: error ( "" ) ;
1288
- }
1289
- if let Some ( builder_updates) = builder_updates {
1290
- builder_updates. apply ( builder) ;
1297
+ match & mut otel_data. state {
1298
+ OtelDataState :: Builder { builder, .. } => {
1299
+ if builder. status == otel:: Status :: Unset
1300
+ && * meta. level ( ) == tracing_core:: Level :: ERROR
1301
+ {
1302
+ builder. status = otel:: Status :: error ( "" ) ;
1303
+ }
1304
+ if let Some ( builder_updates) = builder_updates {
1305
+ builder_updates. update ( builder) ;
1306
+ }
1307
+ if let Some ( ref mut events) = builder. events {
1308
+ events. push ( otel_event) ;
1309
+ } else {
1310
+ builder. events = Some ( vec ! [ otel_event] ) ;
1311
+ }
1291
1312
}
1292
- if let Some ( ref mut events ) = builder . events {
1293
- events . push ( otel_event ) ;
1294
- } else {
1295
- builder . events = Some ( vec ! [ otel_event ] ) ;
1296
- }
1297
- } else {
1298
- let span = otel_data . parent_cx . span ( ) ;
1299
- // TODO:ban fix this with accessor in SpanRef that can check the span status
1300
- if * meta . level ( ) == tracing_core :: Level :: ERROR {
1301
- span. set_status ( otel :: Status :: error ( "" ) ) ;
1313
+ OtelDataState :: Context { current_cx , .. } => {
1314
+ let span = current_cx . span ( ) ;
1315
+ // TODO:ban fix this with accessor in SpanRef that can check the span status
1316
+ if * meta . level ( ) == tracing_core :: Level :: ERROR {
1317
+ span . set_status ( otel :: Status :: error ( "" ) ) ;
1318
+ }
1319
+ if let Some ( builder_updates ) = builder_updates {
1320
+ builder_updates . update_span ( & span) ;
1321
+ }
1322
+ span. add_event ( otel_event . name , otel_event . attributes ) ;
1302
1323
}
1303
- if let Some ( builder_updates) = builder_updates {
1304
- builder_updates. update_span ( & span) ;
1305
- }
1306
- span. add_event ( otel_event. name , otel_event. attributes ) ;
1307
1324
}
1308
- }
1309
- } ;
1325
+ } ;
1326
+ }
1310
1327
}
1311
1328
1312
1329
/// Exports an OpenTelemetry [`Span`] on close.
@@ -1325,12 +1342,7 @@ where
1325
1342
( extensions. remove :: < OtelData > ( ) , timings)
1326
1343
} ;
1327
1344
1328
- if let Some ( OtelData {
1329
- builder,
1330
- parent_cx,
1331
- end_time,
1332
- } ) = otel_data
1333
- {
1345
+ if let Some ( OtelData { state, end_time } ) = otel_data {
1334
1346
// Append busy/idle timings when enabled.
1335
1347
let timings = timings. map ( |timings| {
1336
1348
let busy_ns = Key :: new ( "busy_ns" ) ;
@@ -1342,24 +1354,28 @@ where
1342
1354
]
1343
1355
} ) ;
1344
1356
1345
- if let Some ( builder) = builder {
1346
- // Don't create the context here just to get a SpanRef since it's costly
1347
- let mut span = builder. start_with_context ( & self . tracer , & parent_cx) ;
1348
- if let Some ( timings) = timings {
1349
- span. set_attributes ( timings)
1350
- } ;
1351
- if let Some ( end_time) = end_time {
1352
- span. end_with_timestamp ( end_time) ;
1353
- } else {
1354
- span. end ( ) ;
1357
+ match state {
1358
+ OtelDataState :: Builder { builder, parent_cx } => {
1359
+ // Don't create the context here just to get a SpanRef since it's costly
1360
+ let mut span = builder. start_with_context ( & self . tracer , & parent_cx) ;
1361
+ if let Some ( timings) = timings {
1362
+ span. set_attributes ( timings)
1363
+ } ;
1364
+ if let Some ( end_time) = end_time {
1365
+ span. end_with_timestamp ( end_time) ;
1366
+ } else {
1367
+ span. end ( ) ;
1368
+ }
1355
1369
}
1356
- } else {
1357
- let span = parent_cx. span ( ) ;
1358
- if let Some ( timings) = timings {
1359
- span. set_attributes ( timings)
1360
- } ;
1361
- end_time. map_or_else ( || span. end ( ) , |end_time| span. end_with_timestamp ( end_time) ) ;
1362
- } ;
1370
+ OtelDataState :: Context { current_cx } => {
1371
+ let span = current_cx. span ( ) ;
1372
+ if let Some ( timings) = timings {
1373
+ span. set_attributes ( timings)
1374
+ } ;
1375
+ end_time
1376
+ . map_or_else ( || span. end ( ) , |end_time| span. end_with_timestamp ( end_time) ) ;
1377
+ }
1378
+ }
1363
1379
}
1364
1380
}
1365
1381
0 commit comments