blob: e35e7ed0f1b360e2757fae43a8537636cd721233 [file] [log] [blame]
#![allow(missing_docs)]
use super::{field, metadata, Parent};
use std::fmt;
/// A mock span.
///
/// This is intended for use with the mock subscriber API in the
/// `subscriber` module.
#[derive(Clone, Default, Eq, PartialEq)]
pub struct MockSpan {
pub(in crate::support) metadata: metadata::Expect,
}
#[derive(Default, Eq, PartialEq)]
pub struct NewSpan {
pub(in crate::support) span: MockSpan,
pub(in crate::support) fields: field::Expect,
pub(in crate::support) parent: Option<Parent>,
}
pub fn mock() -> MockSpan {
MockSpan {
..Default::default()
}
}
impl MockSpan {
pub fn named<I>(self, name: I) -> Self
where
I: Into<String>,
{
Self {
metadata: metadata::Expect {
name: Some(name.into()),
..self.metadata
},
}
}
pub fn at_level(self, level: tracing::Level) -> Self {
Self {
metadata: metadata::Expect {
level: Some(level),
..self.metadata
},
}
}
pub fn with_target<I>(self, target: I) -> Self
where
I: Into<String>,
{
Self {
metadata: metadata::Expect {
target: Some(target.into()),
..self.metadata
},
}
}
pub fn with_explicit_parent(self, parent: Option<&str>) -> NewSpan {
let parent = match parent {
Some(name) => Parent::Explicit(name.into()),
None => Parent::ExplicitRoot,
};
NewSpan {
parent: Some(parent),
span: self,
..Default::default()
}
}
pub fn with_contextual_parent(self, parent: Option<&str>) -> NewSpan {
let parent = match parent {
Some(name) => Parent::Contextual(name.into()),
None => Parent::ContextualRoot,
};
NewSpan {
parent: Some(parent),
span: self,
..Default::default()
}
}
pub fn name(&self) -> Option<&str> {
self.metadata.name.as_ref().map(String::as_ref)
}
pub fn level(&self) -> Option<tracing::Level> {
self.metadata.level
}
pub fn target(&self) -> Option<&str> {
self.metadata.target.as_deref()
}
pub fn with_field<I>(self, fields: I) -> NewSpan
where
I: Into<field::Expect>,
{
NewSpan {
span: self,
fields: fields.into(),
..Default::default()
}
}
}
impl fmt::Debug for MockSpan {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut s = f.debug_struct("MockSpan");
if let Some(name) = self.name() {
s.field("name", &name);
}
if let Some(level) = self.level() {
s.field("level", &format_args!("{:?}", level));
}
if let Some(target) = self.target() {
s.field("target", &target);
}
s.finish()
}
}
impl fmt::Display for MockSpan {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.metadata.name.is_some() {
write!(f, "a span{}", self.metadata)
} else {
write!(f, "any span{}", self.metadata)
}
}
}
impl From<MockSpan> for NewSpan {
fn from(span: MockSpan) -> Self {
Self {
span,
..Default::default()
}
}
}
impl NewSpan {
pub fn with_explicit_parent(self, parent: Option<&str>) -> NewSpan {
let parent = match parent {
Some(name) => Parent::Explicit(name.into()),
None => Parent::ExplicitRoot,
};
NewSpan {
parent: Some(parent),
..self
}
}
pub fn with_contextual_parent(self, parent: Option<&str>) -> NewSpan {
let parent = match parent {
Some(name) => Parent::Contextual(name.into()),
None => Parent::ContextualRoot,
};
NewSpan {
parent: Some(parent),
..self
}
}
pub fn with_field<I>(self, fields: I) -> NewSpan
where
I: Into<field::Expect>,
{
NewSpan {
fields: fields.into(),
..self
}
}
pub fn check(
&mut self,
span: &tracing_core::span::Attributes<'_>,
get_parent_name: impl FnOnce() -> Option<String>,
subscriber_name: &str,
) {
let meta = span.metadata();
let name = meta.name();
self.span
.metadata
.check(meta, format_args!("span `{}`", name), subscriber_name);
let mut checker = self.fields.checker(name, subscriber_name);
span.record(&mut checker);
checker.finish();
if let Some(expected_parent) = self.parent.as_ref() {
let actual_parent = get_parent_name();
expected_parent.check_parent_name(
actual_parent.as_deref(),
span.parent().cloned(),
format_args!("span `{}`", name),
subscriber_name,
)
}
}
}
impl fmt::Display for NewSpan {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "a new span{}", self.span.metadata)?;
if !self.fields.is_empty() {
write!(f, " with {}", self.fields)?;
}
Ok(())
}
}
impl fmt::Debug for NewSpan {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut s = f.debug_struct("NewSpan");
if let Some(name) = self.span.name() {
s.field("name", &name);
}
if let Some(level) = self.span.level() {
s.field("level", &format_args!("{:?}", level));
}
if let Some(target) = self.span.target() {
s.field("target", &target);
}
if let Some(ref parent) = self.parent {
s.field("parent", &format_args!("{:?}", parent));
}
if !self.fields.is_empty() {
s.field("fields", &self.fields);
}
s.finish()
}
}