use crate::event_formatter::EventFormatter;
use std::{fmt, io, ops::Deref};
use tracing_core::{Event, Subscriber};
use tracing_subscriber::{
fmt::{format::JsonFields, MakeWriter},
registry::LookupSpan,
};
#[derive(Debug, thiserror::Error)]
enum Error {
#[error(transparent)]
Formatting(#[from] fmt::Error),
#[error("JSON serialization error: {0}")]
Serialization(#[from] serde_json::Error),
#[error(transparent)]
Io(#[from] std::io::Error),
#[error("Time formatting error: {0}")]
Time(#[from] time::error::Format),
}
impl From<Error> for fmt::Error {
fn from(_: Error) -> Self {
Self
}
}
pub fn layer<S>() -> Layer<S>
where
S: Subscriber + for<'span> LookupSpan<'span>,
{
Layer(
tracing_subscriber::fmt::layer()
.json()
.event_format(EventFormatter::default()),
)
}
pub struct Layer<S, W = fn() -> io::Stdout>(
tracing_subscriber::fmt::Layer<S, JsonFields, EventFormatter, W>,
)
where
S: Subscriber + for<'span> LookupSpan<'span>;
impl<S, W> Layer<S, W>
where
S: Subscriber + for<'span> LookupSpan<'span>,
W: for<'writer> MakeWriter<'writer> + 'static,
{
pub fn with_writer<M>(self, make_writer: M) -> Layer<S, M>
where
M: for<'writer> MakeWriter<'writer> + 'static,
{
Layer(self.0.with_writer(make_writer))
}
pub fn with_source_location(self, include_source_location: bool) -> Self {
Self(self.0.map_event_format(|mut event_formatter| {
event_formatter.include_source_location = include_source_location;
event_formatter
}))
}
#[cfg_attr(docsrs, doc(cfg(feature = "opentelemetry")))]
#[cfg(any(docsrs, feature = "opentelemetry"))]
pub fn with_cloud_trace(self, configuration: crate::CloudTraceConfiguration) -> Self {
Self(self.0.map_event_format(|mut event_formatter| {
event_formatter.cloud_trace_configuration = Some(configuration);
event_formatter
}))
}
}
impl<S, W> tracing_subscriber::layer::Layer<S> for Layer<S, W>
where
S: Subscriber + for<'span> LookupSpan<'span>,
W: for<'writer> MakeWriter<'writer> + 'static,
{
fn on_new_span(
&self,
attrs: &tracing_core::span::Attributes<'_>,
id: &tracing_core::span::Id,
context: tracing_subscriber::layer::Context<'_, S>,
) {
self.0.on_new_span(attrs, id, context)
}
fn on_record(
&self,
span: &tracing_core::span::Id,
values: &tracing_core::span::Record<'_>,
context: tracing_subscriber::layer::Context<'_, S>,
) {
self.0.on_record(span, values, context)
}
fn on_enter(
&self,
id: &tracing_core::span::Id,
context: tracing_subscriber::layer::Context<'_, S>,
) {
self.0.on_enter(id, context)
}
fn on_exit(
&self,
id: &tracing_core::span::Id,
context: tracing_subscriber::layer::Context<'_, S>,
) {
self.0.on_exit(id, context)
}
fn on_close(
&self,
id: tracing_core::span::Id,
context: tracing_subscriber::layer::Context<'_, S>,
) {
self.0.on_close(id, context)
}
fn on_event(&self, event: &Event<'_>, context: tracing_subscriber::layer::Context<'_, S>) {
self.0.on_event(event, context)
}
unsafe fn downcast_raw(&self, id: std::any::TypeId) -> Option<*const ()> {
self.0.downcast_raw(id)
}
}
impl<S, W> Deref for Layer<S, W>
where
S: Subscriber + for<'span> LookupSpan<'span>,
{
type Target = tracing_subscriber::fmt::Layer<S, JsonFields, EventFormatter, W>;
fn deref(&self) -> &Self::Target {
&self.0
}
}