1use hyper::rt::Executor;
72use tracing::{
73 Span,
74 instrument::{Instrument, Instrumented},
75};
76
77#[derive(Clone, Copy, Debug, Default)]
96pub struct CurrentSpanExecutor<E> {
97 inner: E,
98}
99
100#[derive(Clone, Debug)]
120pub struct WithSpanExecutor<E> {
121 inner: E,
122 span: Span,
123}
124
125#[derive(Clone, Debug)]
168pub struct MkSpanExecutor<E, F> {
169 inner: E,
170 mk: F,
171}
172
173impl<E> CurrentSpanExecutor<E> {
176 pub fn new(inner: E) -> Self {
178 Self { inner }
179 }
180}
181
182impl<E, F> Executor<F> for CurrentSpanExecutor<E>
183where
184 E: Executor<Instrumented<F>>,
185 F: Future,
186{
187 fn execute(&self, future: F) {
188 self.inner.execute(future.in_current_span());
189 }
190}
191
192impl<E> WithSpanExecutor<E> {
195 pub fn new(inner: E, span: Span) -> Self {
197 Self { inner, span }
198 }
199
200 pub fn current(inner: E) -> Self {
207 Self {
208 inner,
209 span: Span::current(),
210 }
211 }
212}
213
214impl<E, F> Executor<F> for WithSpanExecutor<E>
215where
216 E: Executor<Instrumented<F>>,
217 F: Future,
218{
219 fn execute(&self, future: F) {
220 self.inner.execute(future.instrument(self.span.clone()));
221 }
222}
223
224impl<E, F> MkSpanExecutor<E, F> {
227 pub fn new(inner: E, mk: F) -> Self {
229 Self { inner, mk }
230 }
231}
232
233impl<E, F, Fut> Executor<Fut> for MkSpanExecutor<E, F>
234where
235 E: Executor<Instrumented<Fut>>,
236 F: Fn() -> Span,
237 Fut: Future,
238{
239 fn execute(&self, future: Fut) {
240 let span = (self.mk)();
241 self.inner.execute(future.instrument(span));
242 }
243}
244
245#[cfg(test)]
246mod tests {
247 use super::{CurrentSpanExecutor, MkSpanExecutor, WithSpanExecutor};
248 use hyper::rt::Executor;
249 use std::{
250 cell::RefCell,
251 future::poll_fn,
252 pin::Pin,
253 sync::{Arc, Mutex},
254 task::Poll,
255 };
256
257 #[derive(Default)]
258 struct DeferredExecutor<'a> {
259 future: RefCell<Option<Pin<Box<dyn Future<Output = ()> + 'a>>>>,
260 }
261
262 impl<'a, F: Future<Output = ()> + 'a> Executor<F> for &DeferredExecutor<'a> {
263 fn execute(&self, future: F) {
264 *self.future.borrow_mut() = Some(Box::pin(future));
265 }
266 }
267
268 #[test]
269 fn current_span_executor_propagates_span_from_execute_on_each_poll() {
270 let _subscriber = tracing::subscriber::set_default(tracing_subscriber::registry());
271 let construction_span = tracing::info_span!("construction");
272 let execution_span = tracing::info_span!("execution");
273 let polling_span = tracing::info_span!("polling");
274 assert!(execution_span.id().is_some());
275
276 let polls = RefCell::new(0);
279 let inner = DeferredExecutor::default();
280 let executor = construction_span.in_scope(|| CurrentSpanExecutor::new(&inner));
281 execution_span.in_scope(|| {
282 executor.execute(poll_fn(|_| {
283 assert_eq!(tracing::Span::current().id(), execution_span.id());
284 *polls.borrow_mut() += 1;
285 if *polls.borrow() == 1 {
286 Poll::Pending
287 } else {
288 Poll::Ready(())
289 }
290 }));
291 });
292
293 let _entered = polling_span.enter();
294 let mut task = tokio_test::task::spawn(inner.future.borrow_mut().take().unwrap());
295 assert!(task.poll().is_pending());
296 assert_eq!(tracing::Span::current().id(), polling_span.id());
297 assert!(task.poll().is_ready());
298 assert_eq!(tracing::Span::current().id(), polling_span.id());
299 assert_eq!(*polls.borrow(), 2);
300 }
301
302 #[test]
303 fn with_span_executor_propagates_given_span_on_each_poll() {
304 let _subscriber = tracing::subscriber::set_default(tracing_subscriber::registry());
305 let construction_span = tracing::info_span!("construction");
306 let execution_span = tracing::info_span!("execution");
307 let polling_span = tracing::info_span!("polling");
308 let with_span = tracing::info_span!("with");
309 assert!(execution_span.id().is_some());
310
311 let polls = RefCell::new(0);
314 let inner = DeferredExecutor::default();
315 let executor =
316 construction_span.in_scope(|| WithSpanExecutor::new(&inner, with_span.clone()));
317 execution_span.in_scope(|| {
318 executor.execute(poll_fn(|_| {
319 assert_eq!(tracing::Span::current().id(), with_span.id());
321 *polls.borrow_mut() += 1;
322 if *polls.borrow() == 1 {
323 Poll::Pending
324 } else {
325 Poll::Ready(())
326 }
327 }));
328 });
329
330 let _entered = polling_span.enter();
331 let mut task = tokio_test::task::spawn(inner.future.borrow_mut().take().unwrap());
332 assert!(task.poll().is_pending());
333 assert_eq!(tracing::Span::current().id(), polling_span.id());
334 assert!(task.poll().is_ready());
335 assert_eq!(tracing::Span::current().id(), polling_span.id());
336 assert_eq!(*polls.borrow(), 2);
337 }
338
339 #[test]
340 fn with_span_executor_current_propagates_construction_span() {
341 let _subscriber = tracing::subscriber::set_default(tracing_subscriber::registry());
342 let construction_span = tracing::info_span!("construction");
343 let execution_span = tracing::info_span!("execution");
344 let polling_span = tracing::info_span!("polling");
345 assert!(execution_span.id().is_some());
346
347 let polls = RefCell::new(0);
350 let inner = DeferredExecutor::default();
351 let executor = construction_span.in_scope(|| WithSpanExecutor::current(&inner));
352 execution_span.in_scope(|| {
353 executor.execute(poll_fn(|_| {
354 assert_eq!(tracing::Span::current().id(), construction_span.id());
356 *polls.borrow_mut() += 1;
357 if *polls.borrow() == 1 {
358 Poll::Pending
359 } else {
360 Poll::Ready(())
361 }
362 }));
363 });
364
365 let _entered = polling_span.enter();
366 let mut task = tokio_test::task::spawn(inner.future.borrow_mut().take().unwrap());
367 assert!(task.poll().is_pending());
368 assert_eq!(tracing::Span::current().id(), polling_span.id());
369 assert!(task.poll().is_ready());
370 assert_eq!(tracing::Span::current().id(), polling_span.id());
371 assert_eq!(*polls.borrow(), 2);
372 }
373
374 #[test]
375 fn mk_span_executor_current_propagates_child_span() {
376 let _subscriber = tracing::subscriber::set_default(tracing_subscriber::registry());
377 let construction_span = tracing::info_span!("construction");
378 let execution_span = tracing::info_span!("execution");
379 let polling_span = tracing::info_span!("polling");
380 assert!(execution_span.id().is_some());
381
382 let mk = || tracing::info_span!(parent: tracing::Span::current(), "child");
384
385 let polls = RefCell::new(0);
388 let inner = DeferredExecutor::default();
389 let executor = construction_span.in_scope(|| MkSpanExecutor::new(&inner, mk));
390 execution_span.in_scope(|| {
391 executor.execute(poll_fn(|_| {
392 let span = tracing::Span::current();
394 assert_eq!(span.metadata().unwrap().name(), "child");
395 *polls.borrow_mut() += 1;
396 if *polls.borrow() == 1 {
397 Poll::Pending
398 } else {
399 Poll::Ready(())
400 }
401 }));
402 });
403
404 let _entered = polling_span.enter();
405 let mut task = tokio_test::task::spawn(inner.future.borrow_mut().take().unwrap());
406 assert!(task.poll().is_pending());
407 assert_eq!(tracing::Span::current().id(), polling_span.id());
408 assert!(task.poll().is_ready());
409 assert_eq!(tracing::Span::current().id(), polling_span.id());
410 assert_eq!(*polls.borrow(), 2);
411 }
412
413 struct FollowsFromSubscriber<S> {
415 inner: S,
416 follows_from: Arc<Mutex<Vec<FollowsFrom>>>,
417 }
418
419 type FollowsFrom = (tracing::span::Id, tracing::span::Id);
423
424 impl<S> FollowsFromSubscriber<S> {
425 fn new(inner: S) -> Self {
426 Self {
427 inner,
428 follows_from: Default::default(),
429 }
430 }
431
432 fn follows_from(&self) -> Arc<Mutex<Vec<FollowsFrom>>> {
434 Arc::clone(&self.follows_from)
435 }
436 }
437
438 impl<S> tracing::Subscriber for FollowsFromSubscriber<S>
439 where
440 S: tracing::Subscriber,
441 {
442 fn record_follows_from(&self, span: &tracing::span::Id, follows: &tracing::span::Id) {
443 self.follows_from
444 .lock()
445 .unwrap()
446 .push((span.clone(), follows.clone()));
447 self.inner.record_follows_from(span, follows);
448 }
449
450 fn current_span(&self) -> tracing_core::span::Current {
451 self.inner.current_span()
452 }
453
454 fn enabled(&self, metadata: &tracing::Metadata<'_>) -> bool {
457 self.inner.enabled(metadata)
458 }
459
460 fn enter(&self, span: &tracing::span::Id) {
461 self.inner.enter(span);
462 }
463
464 fn event(&self, event: &tracing::Event<'_>) {
465 self.inner.event(event);
466 }
467
468 fn exit(&self, span: &tracing::span::Id) {
469 self.inner.exit(span);
470 }
471
472 fn new_span(&self, span: &tracing::span::Attributes<'_>) -> tracing::span::Id {
473 self.inner.new_span(span)
474 }
475
476 fn record(&self, span: &tracing::span::Id, values: &tracing::span::Record<'_>) {
477 self.inner.record(span, values);
478 }
479 }
480
481 #[test]
482 fn mk_span_executor_current_propagates_causal_span_relationships() {
483 let subscriber = FollowsFromSubscriber::new(tracing_subscriber::registry());
485 let relationships = subscriber.follows_from();
486 let _subscriber = tracing::subscriber::set_default(subscriber);
487
488 let construction_span = tracing::info_span!("construction");
489 let execution_a_span = tracing::info_span!("execution_a");
490 let execution_b_span = tracing::info_span!("execution_b");
491 let polling_span = tracing::info_span!("polling");
492
493 let mk = || {
495 let span = tracing::info_span!("spawned");
496 span.follows_from(tracing::Span::current());
497 span
498 };
499
500 let polls = RefCell::new(0);
501 let inner = DeferredExecutor::default();
502 let executor = construction_span.in_scope(|| MkSpanExecutor::new(&inner, mk));
503 execution_a_span.in_scope(|| {
504 executor.execute(poll_fn(|_| {
505 let span = tracing::Span::current();
507 assert_eq!(span.metadata().unwrap().name(), "spawned");
508 *polls.borrow_mut() += 1;
509 if *polls.borrow() == 1 {
510 Poll::Pending
511 } else {
512 Poll::Ready(())
513 }
514 }));
515 });
516
517 let _entered = polling_span.enter();
518 let mut task = tokio_test::task::spawn(inner.future.borrow_mut().take().unwrap());
519 assert!(task.poll().is_pending());
520 assert_eq!(tracing::Span::current().id(), polling_span.id());
521 assert_eq!(relationships.lock().unwrap().len(), 1);
522 assert!(task.poll().is_ready());
523 assert_eq!(tracing::Span::current().id(), polling_span.id());
524 assert_eq!(*polls.borrow(), 2);
525 assert_eq!(relationships.lock().unwrap().len(), 1);
526
527 execution_b_span.in_scope(|| {
528 executor.execute(poll_fn(|_| {
529 let span = tracing::Span::current();
530 assert_eq!(span.metadata().unwrap().name(), "spawned");
531 Poll::Ready(())
532 }));
533 });
534
535 let _entered = polling_span.enter();
536 let mut task = tokio_test::task::spawn(inner.future.borrow_mut().take().unwrap());
537 assert!(task.poll().is_ready());
538
539 let relationships = relationships.lock().unwrap();
542 assert_eq!(relationships.len(), 2);
543 assert_eq!(relationships[0].1, execution_a_span.id().unwrap());
544 assert_eq!(relationships[1].1, execution_b_span.id().unwrap());
545 }
546}