187 lines
5.2 KiB
Rust
187 lines
5.2 KiB
Rust
|
|
//! Tests for task instrumentation.
|
||
|
|
//!
|
||
|
|
//! These tests ensure that the instrumentation for task spawning and task
|
||
|
|
//! lifecycles is correct.
|
||
|
|
#![warn(rust_2018_idioms)]
|
||
|
|
#![cfg(all(tokio_unstable, feature = "tracing", target_has_atomic = "64"))]
|
||
|
|
|
||
|
|
use std::{mem, time::Duration};
|
||
|
|
|
||
|
|
use tokio::task;
|
||
|
|
use tracing_mock::{expect, span::NewSpan, subscriber};
|
||
|
|
|
||
|
|
#[tokio::test]
|
||
|
|
async fn task_spawn_creates_span() {
|
||
|
|
let task_span = expect::span()
|
||
|
|
.named("runtime.spawn")
|
||
|
|
.with_target("tokio::task");
|
||
|
|
|
||
|
|
let (subscriber, handle) = subscriber::mock()
|
||
|
|
.new_span(&task_span)
|
||
|
|
.enter(&task_span)
|
||
|
|
.exit(&task_span)
|
||
|
|
// The task span is entered once more when it gets dropped
|
||
|
|
.enter(&task_span)
|
||
|
|
.exit(&task_span)
|
||
|
|
.drop_span(task_span)
|
||
|
|
.run_with_handle();
|
||
|
|
|
||
|
|
{
|
||
|
|
let _guard = tracing::subscriber::set_default(subscriber);
|
||
|
|
tokio::spawn(futures::future::ready(()))
|
||
|
|
.await
|
||
|
|
.expect("failed to await join handle");
|
||
|
|
}
|
||
|
|
|
||
|
|
handle.assert_finished();
|
||
|
|
}
|
||
|
|
|
||
|
|
#[tokio::test]
|
||
|
|
async fn task_spawn_loc_file_recorded() {
|
||
|
|
let task_span = expect::span()
|
||
|
|
.named("runtime.spawn")
|
||
|
|
.with_target("tokio::task")
|
||
|
|
.with_fields(expect::field("loc.file").with_value(&file!()));
|
||
|
|
|
||
|
|
let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle();
|
||
|
|
|
||
|
|
{
|
||
|
|
let _guard = tracing::subscriber::set_default(subscriber);
|
||
|
|
|
||
|
|
tokio::spawn(futures::future::ready(()))
|
||
|
|
.await
|
||
|
|
.expect("failed to await join handle");
|
||
|
|
}
|
||
|
|
|
||
|
|
handle.assert_finished();
|
||
|
|
}
|
||
|
|
|
||
|
|
#[tokio::test]
|
||
|
|
async fn task_builder_name_recorded() {
|
||
|
|
let task_span = expect_task_named("test-task");
|
||
|
|
|
||
|
|
let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle();
|
||
|
|
|
||
|
|
{
|
||
|
|
let _guard = tracing::subscriber::set_default(subscriber);
|
||
|
|
task::Builder::new()
|
||
|
|
.name("test-task")
|
||
|
|
.spawn(futures::future::ready(()))
|
||
|
|
.unwrap()
|
||
|
|
.await
|
||
|
|
.expect("failed to await join handle");
|
||
|
|
}
|
||
|
|
|
||
|
|
handle.assert_finished();
|
||
|
|
}
|
||
|
|
|
||
|
|
#[tokio::test]
|
||
|
|
async fn task_builder_loc_file_recorded() {
|
||
|
|
let task_span = expect::span()
|
||
|
|
.named("runtime.spawn")
|
||
|
|
.with_target("tokio::task")
|
||
|
|
.with_fields(expect::field("loc.file").with_value(&file!()));
|
||
|
|
|
||
|
|
let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle();
|
||
|
|
|
||
|
|
{
|
||
|
|
let _guard = tracing::subscriber::set_default(subscriber);
|
||
|
|
|
||
|
|
task::Builder::new()
|
||
|
|
.spawn(futures::future::ready(()))
|
||
|
|
.unwrap()
|
||
|
|
.await
|
||
|
|
.expect("failed to await join handle");
|
||
|
|
}
|
||
|
|
|
||
|
|
handle.assert_finished();
|
||
|
|
}
|
||
|
|
|
||
|
|
#[tokio::test]
|
||
|
|
async fn task_spawn_sizes_recorded() {
|
||
|
|
let future = futures::future::ready(());
|
||
|
|
let size = mem::size_of_val(&future) as u64;
|
||
|
|
|
||
|
|
let task_span = expect::span()
|
||
|
|
.named("runtime.spawn")
|
||
|
|
.with_target("tokio::task")
|
||
|
|
// TODO(hds): check that original_size.bytes is NOT recorded when this can be done in
|
||
|
|
// tracing-mock without listing every other field.
|
||
|
|
.with_fields(expect::field("size.bytes").with_value(&size));
|
||
|
|
|
||
|
|
let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle();
|
||
|
|
|
||
|
|
{
|
||
|
|
let _guard = tracing::subscriber::set_default(subscriber);
|
||
|
|
|
||
|
|
task::Builder::new()
|
||
|
|
.spawn(future)
|
||
|
|
.unwrap()
|
||
|
|
.await
|
||
|
|
.expect("failed to await join handle");
|
||
|
|
}
|
||
|
|
|
||
|
|
handle.assert_finished();
|
||
|
|
}
|
||
|
|
|
||
|
|
#[tokio::test]
|
||
|
|
async fn task_big_spawn_sizes_recorded() {
|
||
|
|
let future = {
|
||
|
|
async fn big<const N: usize>() {
|
||
|
|
let mut a = [0_u8; N];
|
||
|
|
for (idx, item) in a.iter_mut().enumerate() {
|
||
|
|
*item = (idx % 256) as u8;
|
||
|
|
}
|
||
|
|
tokio::time::sleep(Duration::from_millis(10)).await;
|
||
|
|
for (idx, item) in a.iter_mut().enumerate() {
|
||
|
|
assert_eq!(*item, (idx % 256) as u8);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// This is larger than the release auto-boxing threshold
|
||
|
|
big::<20_000>()
|
||
|
|
};
|
||
|
|
|
||
|
|
fn boxed_size<T>(_: &T) -> usize {
|
||
|
|
mem::size_of::<Box<T>>()
|
||
|
|
}
|
||
|
|
let size = mem::size_of_val(&future) as u64;
|
||
|
|
let boxed_size = boxed_size(&future);
|
||
|
|
|
||
|
|
let task_span = expect::span()
|
||
|
|
.named("runtime.spawn")
|
||
|
|
.with_target("tokio::task")
|
||
|
|
.with_fields(
|
||
|
|
expect::field("size.bytes")
|
||
|
|
.with_value(&boxed_size)
|
||
|
|
.and(expect::field("original_size.bytes").with_value(&size)),
|
||
|
|
);
|
||
|
|
|
||
|
|
let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle();
|
||
|
|
|
||
|
|
{
|
||
|
|
let _guard = tracing::subscriber::set_default(subscriber);
|
||
|
|
|
||
|
|
task::Builder::new()
|
||
|
|
.spawn(future)
|
||
|
|
.unwrap()
|
||
|
|
.await
|
||
|
|
.expect("failed to await join handle");
|
||
|
|
}
|
||
|
|
|
||
|
|
handle.assert_finished();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Expect a task with name
|
||
|
|
///
|
||
|
|
/// This is a convenience function to create the expectation for a new task
|
||
|
|
/// with the `task.name` field set to the provided name.
|
||
|
|
fn expect_task_named(name: &str) -> NewSpan {
|
||
|
|
expect::span()
|
||
|
|
.named("runtime.spawn")
|
||
|
|
.with_target("tokio::task")
|
||
|
|
.with_fields(
|
||
|
|
expect::field("task.name").with_value(&tracing::field::debug(format_args!("{name}"))),
|
||
|
|
)
|
||
|
|
}
|