use tracing::field::{Field, Visit};
use tracing::span;
use tracing::{Event, Level, Metadata, Subscriber};
pub struct WorkerSubscriber {
max_level: Level,
}
impl WorkerSubscriber {
pub fn new() -> Self {
Self {
max_level: Level::DEBUG,
}
}
pub fn with_max_level(mut self, level: Level) -> Self {
self.max_level = level;
self
}
}
impl Default for WorkerSubscriber {
fn default() -> Self {
Self::new()
}
}
impl Subscriber for WorkerSubscriber {
fn enabled(&self, metadata: &Metadata<'_>) -> bool {
metadata.level() <= &self.max_level
}
fn new_span(&self, _attrs: &span::Attributes<'_>) -> span::Id {
span::Id::from_u64(1)
}
fn record(&self, _span: &span::Id, _values: &span::Record<'_>) {}
fn record_follows_from(&self, _span: &span::Id, _follows: &span::Id) {}
fn event(&self, event: &Event<'_>) {
let metadata = event.metadata();
let level = metadata.level();
let target = metadata.target();
let mut visitor = MessageVisitor::default();
event.record(&mut visitor);
let msg = if visitor.fields.is_empty() {
format!("[{level}] {target}: {}", visitor.message)
} else {
format!(
"[{level}] {target}: {} {{ {} }}",
visitor.message,
visitor.fields.join(", ")
)
};
match *level {
Level::ERROR => worker::console_error!("{}", msg),
Level::WARN => worker::console_warn!("{}", msg),
_ => worker::console_log!("{}", msg),
}
}
fn enter(&self, _span: &span::Id) {}
fn exit(&self, _span: &span::Id) {}
}
#[derive(Default)]
struct MessageVisitor {
message: String,
fields: Vec<String>,
}
impl Visit for MessageVisitor {
fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) {
if field.name() == "message" {
self.message = format!("{:?}", value);
} else {
self.fields.push(format!("{}={:?}", field.name(), value));
}
}
fn record_str(&mut self, field: &Field, value: &str) {
if field.name() == "message" {
self.message = value.to_string();
} else {
self.fields.push(format!("{}=\"{}\"", field.name(), value));
}
}
fn record_u64(&mut self, field: &Field, value: u64) {
self.fields.push(format!("{}={}", field.name(), value));
}
fn record_i64(&mut self, field: &Field, value: i64) {
self.fields.push(format!("{}={}", field.name(), value));
}
fn record_bool(&mut self, field: &Field, value: bool) {
self.fields.push(format!("{}={}", field.name(), value));
}
}