use crate::tag::Tag;
#[cfg(feature = "chrono")]
use chrono::{DateTime, Utc};
#[cfg(feature = "serde")]
use serde::Serialize;
use std::time::Duration;
use thiserror::Error;
use tracing::Level;
#[cfg(feature = "uuid")]
use uuid::Uuid;
mod field;
#[cfg(feature = "serde")]
mod ser;
pub use field::Field;
pub(crate) use field::FieldSet;
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[allow(clippy::large_enum_variant)] pub enum Tree {
Event(Event),
Span(Span),
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct Event {
#[cfg_attr(feature = "serde", serde(flatten))]
pub(crate) shared: Shared,
pub(crate) message: Option<String>,
pub(crate) tag: Option<Tag>,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct Span {
#[cfg_attr(feature = "serde", serde(flatten))]
pub(crate) shared: Shared,
pub(crate) name: &'static str,
#[cfg_attr(
feature = "serde",
serde(rename = "nanos_total", serialize_with = "ser::nanos")
)]
pub(crate) total_duration: Duration,
#[cfg_attr(
feature = "serde",
serde(rename = "nanos_nested", serialize_with = "ser::nanos")
)]
pub(crate) inner_duration: Duration,
pub(crate) nodes: Vec<Tree>,
#[cfg(feature = "defer")]
pub(crate) defer_unless_children_attached: bool,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub(crate) struct Shared {
#[cfg(feature = "uuid")]
pub(crate) uuid: Uuid,
#[cfg(feature = "chrono")]
#[cfg_attr(feature = "serde", serde(serialize_with = "ser::timestamp"))]
pub(crate) timestamp: DateTime<Utc>,
#[cfg_attr(feature = "serde", serde(serialize_with = "ser::level"))]
pub(crate) level: Level,
#[cfg_attr(feature = "serde", serde(serialize_with = "ser::fields"))]
pub(crate) fields: FieldSet,
}
#[derive(Error, Debug)]
#[error("Expected an event, found a span")]
pub struct ExpectedEventError(());
#[derive(Error, Debug)]
#[error("Expected a span, found an event")]
pub struct ExpectedSpanError(());
impl Tree {
pub fn event(&self) -> Result<&Event, ExpectedEventError> {
match self {
Tree::Event(event) => Ok(event),
Tree::Span(_) => Err(ExpectedEventError(())),
}
}
pub fn span(&self) -> Result<&Span, ExpectedSpanError> {
match self {
Tree::Event(_) => Err(ExpectedSpanError(())),
Tree::Span(span) => Ok(span),
}
}
pub(crate) fn should_render(&self) -> bool {
match self {
Tree::Event(_) => true,
Tree::Span(span) => span.should_render(),
}
}
}
impl Event {
#[cfg(feature = "uuid")]
pub fn uuid(&self) -> Uuid {
self.shared.uuid
}
#[cfg(feature = "chrono")]
pub fn timestamp(&self) -> DateTime<Utc> {
self.shared.timestamp
}
pub fn level(&self) -> Level {
self.shared.level
}
pub fn message(&self) -> Option<&str> {
self.message.as_deref()
}
pub fn tag(&self) -> Option<Tag> {
self.tag
}
pub fn fields(&self) -> &[Field] {
&self.shared.fields
}
}
impl Span {
pub(crate) fn new(shared: Shared, name: &'static str) -> Self {
Span {
shared,
name,
total_duration: Duration::ZERO,
inner_duration: Duration::ZERO,
nodes: Vec::new(),
#[cfg(feature = "defer")]
defer_unless_children_attached: false,
}
}
#[cfg(feature = "defer")]
pub(crate) fn defer_unless_children_attached(mut self, defer: bool) -> Self {
self.defer_unless_children_attached = defer;
self
}
#[cfg(feature = "defer")]
pub(crate) fn should_render(&self) -> bool {
!(self.defer_unless_children_attached && self.nodes().is_empty())
}
#[cfg(not(feature = "defer"))]
pub(crate) fn should_render(&self) -> bool {
true
}
#[cfg(feature = "uuid")]
pub fn uuid(&self) -> Uuid {
self.shared.uuid
}
#[cfg(feature = "chrono")]
pub fn timestamp(&self) -> DateTime<Utc> {
self.shared.timestamp
}
pub fn level(&self) -> Level {
self.shared.level
}
pub fn name(&self) -> &str {
self.name
}
pub fn fields(&self) -> &[Field] {
&self.shared.fields
}
pub fn nodes(&self) -> &[Tree] {
&self.nodes
}
pub fn total_duration(&self) -> Duration {
self.total_duration
}
pub fn inner_duration(&self) -> Duration {
self.inner_duration
}
pub fn base_duration(&self) -> Duration {
self.total_duration - self.inner_duration
}
}