1use std::cell::Cell;
21use std::fmt;
22use std::io;
23use std::io::Write;
24use std::sync::Arc;
25use std::sync::Condvar;
26use std::sync::Mutex;
27use std::sync::OnceLock;
28
29use tracing::Event;
30use tracing::Level;
31use tracing::Subscriber;
32use tracing::field::Field;
33use tracing::field::Visit;
34use tracing::span::Attributes;
35use tracing::span::Id;
36use tracing::span::Record;
37use tracing_log::NormalizeEvent;
38use tracing_subscriber::EnvFilter;
39use tracing_subscriber::Layer;
40use tracing_subscriber::field::RecordFields;
41use tracing_subscriber::field::VisitOutput;
42use tracing_subscriber::fmt::FormattedFields;
43use tracing_subscriber::fmt::MakeWriter;
44use tracing_subscriber::fmt::format::DefaultFields;
45use tracing_subscriber::fmt::format::DefaultVisitor;
46use tracing_subscriber::fmt::format::FormatFields;
47use tracing_subscriber::fmt::format::Writer;
48use tracing_subscriber::fmt::time::FormatTime;
49use tracing_subscriber::fmt::time::SystemTime;
50use tracing_subscriber::layer::Context;
51use tracing_subscriber::layer::SubscriberExt;
52use tracing_subscriber::registry::LookupSpan;
53
54pub const EVENT_BYTES: usize = 1024 * 1024;
58pub const SPAN_BYTES: usize = 64 * 1024;
63
64#[derive(Clone, Copy, Debug)]
71pub struct FormatterLimits {
72 event_bytes: usize,
73 span_bytes: usize,
74}
75
76impl FormatterLimits {
77 pub fn new(event_bytes: usize, span_bytes: usize) -> io::Result<Self> {
78 let envelope = span_bytes
79 .checked_mul(2)
80 .and_then(|spans| spans.checked_add(event_bytes))
81 .and_then(|bytes| bytes.checked_add(8));
82 if event_bytes == 0
83 || span_bytes == 0
84 || envelope.is_none_or(|bytes| bytes > isize::MAX as usize)
85 {
86 return Err(io::Error::new(
87 io::ErrorKind::InvalidInput,
88 "invalid formatter limits",
89 ));
90 }
91 Ok(Self {
92 event_bytes,
93 span_bytes,
94 })
95 }
96}
97
98#[derive(Clone, Copy, Debug, Eq, PartialEq)]
99pub enum BufferKind {
100 Event,
101 Span,
102}
103
104#[derive(Debug)]
106pub enum RecordFailure {
107 Formatting,
108 Sink(io::Error),
109 Reentrant,
110 Unwinding,
111 Size { buffer: BufferKind, limit: usize },
112 Allocation,
113}
114
115impl fmt::Display for RecordFailure {
116 fn fmt(&self, writer: &mut fmt::Formatter<'_>) -> fmt::Result {
117 match self {
118 Self::Formatting => writer.write_str("host record formatting failed"),
119 Self::Sink(error) => write!(writer, "host record sink failed: {error}"),
120 Self::Reentrant => writer.write_str("reentrant host record publication"),
121 Self::Unwinding => writer.write_str("host record formatting or publication unwound"),
122 Self::Size { buffer, limit } => {
123 write!(writer, "{buffer:?} formatter exceeded {limit} bytes")
124 }
125 Self::Allocation => writer.write_str("formatter storage allocation failed"),
126 }
127 }
128}
129
130impl std::error::Error for RecordFailure {
131 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
132 match self {
133 Self::Sink(error) => Some(error),
134 _ => None,
135 }
136 }
137}
138
139#[derive(Clone, Default)]
149pub struct RecordStatus(
150 Arc<Mutex<Option<Arc<RecordFailure>>>>,
151 Arc<OnceLock<Box<dyn Fn() + Send + Sync>>>,
152 Arc<Condvar>,
153);
154
155impl RecordStatus {
156 pub fn failure(&self) -> Option<Arc<RecordFailure>> {
157 self.0
158 .lock()
159 .unwrap_or_else(|error| error.into_inner())
160 .clone()
161 }
162
163 fn fail(&self, failure: RecordFailure) {
164 let mut stored = self.0.lock().unwrap_or_else(|error| error.into_inner());
165 if stored.is_none() {
166 *stored = Some(Arc::new(failure));
167 drop(stored);
168 self.2.notify_all();
171 if let Some(notify) = self.1.get() {
172 notify();
173 }
174 } else {
175 drop(stored);
176 drop(failure);
177 }
178 }
179
180 fn wake_waiters(&self) {
181 let _stored = self.0.lock().unwrap_or_else(|error| error.into_inner());
184 self.2.notify_all();
185 }
186
187 fn formatting(&self, action: impl FnOnce() -> fmt::Result) -> fmt::Result {
188 let attempt = Attempt(Some(self));
189 let result = action();
190 attempt.complete();
191 if result.is_err() {
192 self.fail(RecordFailure::Formatting);
193 }
194 result
195 }
196}
197
198struct Attempt<'status>(Option<&'status RecordStatus>);
199
200impl Attempt<'_> {
201 fn complete(mut self) {
202 self.0 = None;
205 }
206}
207
208impl Drop for Attempt<'_> {
209 fn drop(&mut self) {
210 if let Some(status) = self.0
211 && std::thread::panicking()
212 {
213 status.fail(RecordFailure::Unwinding);
214 }
215 }
216}
217
218struct BoundedBuffer<'status> {
219 bytes: Vec<u8>,
220 limit: usize,
221 failed: bool,
222 kind: BufferKind,
223 status: &'status RecordStatus,
224}
225
226fn reserve_payload(
227 bytes: &mut Vec<u8>,
228 limit: usize,
229) -> Result<(), std::collections::TryReserveError> {
230 #[cfg(test)]
231 tests::before_payload_allocation()?;
232 bytes.try_reserve_exact(limit)
233}
234
235impl<'status> BoundedBuffer<'status> {
236 fn new(
237 limit: usize,
238 kind: BufferKind,
239 status: &'status RecordStatus,
240 ) -> Result<Self, fmt::Error> {
241 let mut bytes = Vec::new();
242 if reserve_payload(&mut bytes, limit).is_err() {
243 status.fail(RecordFailure::Allocation);
244 return Err(fmt::Error);
245 }
246 Ok(Self {
247 bytes,
248 limit,
249 failed: false,
250 kind,
251 status,
252 })
253 }
254
255 fn text(&self) -> &str {
256 std::str::from_utf8(&self.bytes).expect("only complete UTF-8 strings were copied")
257 }
258
259 fn into_string(self) -> String {
260 String::from_utf8(self.bytes).expect("only complete UTF-8 strings were copied")
261 }
262}
263
264impl fmt::Write for BoundedBuffer<'_> {
265 fn write_str(&mut self, text: &str) -> fmt::Result {
266 if self.failed {
267 return Err(fmt::Error);
268 }
269 if self
270 .bytes
271 .len()
272 .checked_add(text.len())
273 .is_none_or(|end| end > self.limit)
274 {
275 self.failed = true;
276 self.status.fail(RecordFailure::Size {
277 buffer: self.kind,
278 limit: self.limit,
279 });
280 return Err(fmt::Error);
281 }
282 self.bytes.extend_from_slice(text.as_bytes());
285 Ok(())
286 }
287}
288
289thread_local! {
292 static ACTIVE: Cell<*const Active> = const { Cell::new(std::ptr::null()) };
293}
294
295struct Active {
296 identity: usize,
297 previous: *const Active,
298}
299
300struct RestoreActive(*const Active);
301
302impl Drop for RestoreActive {
303 fn drop(&mut self) {
304 ACTIVE.set(self.0);
305 }
306}
307
308fn with_active<T>(
309 status: &RecordStatus,
310 action: impl FnOnce() -> Result<T, fmt::Error>,
311) -> Result<T, fmt::Error> {
312 if status.failure().is_some() {
313 return Err(fmt::Error);
314 }
315 let identity = Arc::as_ptr(&status.0) as usize;
316 let previous = ACTIVE.get();
317 let mut current = previous;
318 while !current.is_null() {
319 let active = unsafe { &*current };
323 if active.identity == identity {
324 status.fail(RecordFailure::Reentrant);
325 return Err(fmt::Error);
326 }
327 current = active.previous;
328 }
329 let active = Active { identity, previous };
330 ACTIVE.set(&raw const active);
331 let restore = RestoreActive(previous);
332 let result = action();
333 drop(restore);
334 result
335}
336
337struct CheckedFields;
339
340#[derive(Default)]
345struct SpanCaches(Vec<(Arc<()>, Arc<SpanCache>)>);
346
347impl SpanCaches {
348 fn get(&self, identity: &Arc<()>) -> Option<&Arc<SpanCache>> {
349 self.0
350 .iter()
351 .find(|(owner, _)| Arc::ptr_eq(owner, identity))
352 .map(|(_, fields)| fields)
353 }
354
355 fn get_or_insert(&mut self, identity: &Arc<()>) -> Arc<SpanCache> {
356 if let Some(cache) = self.get(identity) {
357 return cache.clone();
358 }
359 let cache = Arc::new(SpanCache::default());
360 self.0.push((identity.clone(), cache.clone()));
361 cache
362 }
363}
364
365#[derive(Default)]
366struct PendingUpdates {
367 fields: Arc<FormattedFields<CheckedFields>>,
368 leading_empty: usize,
371}
372
373#[derive(Default)]
374struct CacheState {
375 fields: Arc<FormattedFields<CheckedFields>>,
376 pending: Option<PendingUpdates>,
377}
378
379#[derive(Default)]
380struct SpanCache(Mutex<CacheState>);
381
382impl SpanCache {
383 fn snapshot(
384 &self,
385 status: &RecordStatus,
386 ) -> Result<Arc<FormattedFields<CheckedFields>>, fmt::Error> {
387 let mut failure = status.0.lock().unwrap_or_else(|error| error.into_inner());
388 loop {
389 if failure.is_some() {
390 return Err(fmt::Error);
391 }
392 {
393 let state = self.0.lock().unwrap_or_else(|error| error.into_inner());
394 if state.pending.is_none() {
395 return Ok(state.fields.clone());
396 }
397 }
398 failure = status
402 .2
403 .wait(failure)
404 .unwrap_or_else(|error| error.into_inner());
405 }
406 }
407
408 fn initialize(self: &Arc<Self>, status: &RecordStatus) -> Initializing {
409 #[cfg(test)]
410 tests::before_span_initialization();
411 let mut state = self.0.lock().unwrap_or_else(|error| error.into_inner());
412 assert!(
413 state.pending.is_none(),
414 "span initialized twice concurrently"
415 );
416 state.pending = Some(PendingUpdates::default());
417 Initializing {
418 cache: self.clone(),
419 status: status.clone(),
420 }
421 }
422}
423
424struct Initializing {
425 cache: Arc<SpanCache>,
426 status: RecordStatus,
427}
428
429impl Drop for Initializing {
430 fn drop(&mut self) {
431 self.cache
434 .0
435 .lock()
436 .unwrap_or_else(|error| error.into_inner())
437 .pending = None;
438 self.status.wake_waiters();
439 }
440}
441
442struct RecordLayer<Timer, Sink> {
443 identity: Arc<()>,
444 timer: Timer,
445 timestamp: bool,
446 ansi: bool,
447 limits: FormatterLimits,
448 status: RecordStatus,
449 writer: RecordWriterFactory<Sink>,
450}
451
452impl<Timer, Sink> RecordLayer<Timer, Sink> {
453 fn format_span<Fields: RecordFields>(
454 &self,
455 fields: Fields,
456 ) -> Result<BoundedBuffer<'_>, fmt::Error> {
457 let mut buffer =
458 BoundedBuffer::new(self.limits.span_bytes, BufferKind::Span, &self.status)?;
459 self.status
463 .formatting(|| format_fields(Writer::new(&mut buffer), fields, self.ansi))?;
464 if self.status.failure().is_some() {
465 return Err(fmt::Error);
466 }
467 Ok(buffer)
468 }
469
470 fn commit_span(
471 &self,
472 current: &mut Arc<FormattedFields<CheckedFields>>,
473 mut buffer: BoundedBuffer<'_>,
474 append: bool,
475 ) -> Result<(), RecordFailure> {
476 if append && !current.fields.is_empty() {
477 let prefix = current.fields.len() + 1;
478 let length = buffer.bytes.len();
479 let Some(combined) = prefix
480 .checked_add(length)
481 .filter(|combined| *combined <= buffer.limit)
482 else {
483 return Err(RecordFailure::Size {
486 buffer: BufferKind::Span,
487 limit: buffer.limit,
488 });
489 };
490 buffer.bytes.resize(combined, 0);
494 buffer.bytes.copy_within(..length, prefix);
495 buffer.bytes[..current.fields.len()].copy_from_slice(current.fields.as_bytes());
496 buffer.bytes[current.fields.len()] = b' ';
497 }
498 *current = Arc::new(FormattedFields::new(buffer.into_string()));
499 Ok(())
500 }
501
502 fn commit_update(
503 &self,
504 cache: &SpanCache,
505 buffer: BoundedBuffer<'_>,
506 ) -> Result<(), RecordFailure> {
507 let mut state = cache.0.lock().unwrap_or_else(|error| error.into_inner());
508 if let Some(pending) = &mut state.pending {
509 let empty = pending.fields.is_empty() && buffer.bytes.is_empty();
510 self.commit_span(&mut pending.fields, buffer, true)?;
511 if empty {
512 pending.leading_empty = (pending.leading_empty + 1).min(self.limits.span_bytes + 1);
513 }
514 Ok(())
515 } else {
516 self.commit_span(&mut state.fields, buffer, true)
517 }
518 }
519
520 fn commit_initial(
521 &self,
522 cache: &SpanCache,
523 mut buffer: BoundedBuffer<'_>,
524 ) -> Result<(), RecordFailure> {
525 let mut state = cache.0.lock().unwrap_or_else(|error| error.into_inner());
526 let pending = state.pending.as_ref().expect("initialization is active");
527 let spaces = if buffer.bytes.is_empty() {
528 0
529 } else {
530 pending.leading_empty + usize::from(!pending.fields.is_empty())
531 };
532 let combined = buffer
533 .bytes
534 .len()
535 .checked_add(spaces)
536 .and_then(|length| length.checked_add(pending.fields.fields.len()))
537 .filter(|length| *length <= buffer.limit);
538 let Some(combined) = combined else {
539 return Err(RecordFailure::Size {
540 buffer: BufferKind::Span,
541 limit: buffer.limit,
542 });
543 };
544 buffer.bytes.resize(buffer.bytes.len() + spaces, b' ');
547 buffer
548 .bytes
549 .extend_from_slice(pending.fields.fields.as_bytes());
550 debug_assert_eq!(buffer.bytes.len(), combined);
551 state.fields = Arc::new(FormattedFields::new(buffer.into_string()));
552 state.pending = None;
553 Ok(())
554 }
555}
556
557impl<Registry, Timer, Sink> Layer<Registry> for RecordLayer<Timer, Sink>
558where
559 Registry: Subscriber + for<'lookup> LookupSpan<'lookup>,
560 Timer: FormatTime + 'static,
561 Sink: Fn(&[u8]) -> io::Result<()> + 'static,
562{
563 fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, context: Context<'_, Registry>) {
564 let span = context.span(id).expect("new span is registered");
565 let (cache, initializing) = {
566 let mut extensions = span.extensions_mut();
567 if extensions.get_mut::<SpanCaches>().is_none() {
568 extensions.insert(SpanCaches::default());
569 }
570 let caches = extensions.get_mut::<SpanCaches>().unwrap();
571 if caches.get(&self.identity).is_some() {
575 return;
576 }
577 let cache = caches.get_or_insert(&self.identity);
578 let initializing = cache.initialize(&self.status);
581 (cache, initializing)
582 };
583 let _ = with_active(&self.status, || {
584 let _initializing = initializing;
585 let buffer = self.format_span(attrs)?;
586 self.commit_initial(&cache, buffer).map_err(|failure| {
587 self.status.fail(failure);
588 fmt::Error
589 })
590 });
591 }
592
593 fn on_record(&self, id: &Id, fields: &Record<'_>, context: Context<'_, Registry>) {
594 let _ = with_active(&self.status, || {
595 let span = context.span(id).expect("recorded span is registered");
596 let (cache, initializing) = {
597 let mut extensions = span.extensions_mut();
598 if extensions.get_mut::<SpanCaches>().is_none() {
599 extensions.insert(SpanCaches::default());
600 }
601 let caches = extensions.get_mut::<SpanCaches>().unwrap();
602 if let Some(cache) = caches.get(&self.identity) {
603 (cache.clone(), None)
604 } else {
605 let cache = caches.get_or_insert(&self.identity);
606 let initializing = cache.initialize(&self.status);
610 (cache, Some(initializing))
611 }
612 };
613 let _initializing = initializing;
614 let buffer = self.format_span(fields)?;
615 let result = if _initializing.is_some() {
616 self.commit_initial(&cache, buffer)
617 } else {
618 self.commit_update(&cache, buffer)
619 };
620 result.map_err(|failure| {
621 self.status.fail(failure);
622 fmt::Error
623 })
624 });
625 }
626
627 fn on_event(&self, event: &Event<'_>, context: Context<'_, Registry>) {
628 let record = with_active(&self.status, || {
629 let mut buffer =
630 BoundedBuffer::new(self.limits.event_bytes, BufferKind::Event, &self.status)?;
631 self.status.formatting(|| {
632 let mut writer = Writer::new(&mut buffer);
633 if self.timestamp {
635 if self.ansi {
636 writer.write_str("\x1b[2m")?;
637 }
638 if self.timer.format_time(&mut writer).is_err() {
639 writer.write_str("<unknown time>")?;
640 }
641 if self.ansi {
642 writer.write_str("\x1b[0m")?;
643 }
644 writer.write_char(' ')?;
645 }
646 let normalized = event.normalized_metadata();
647 let metadata = normalized.as_ref().unwrap_or_else(|| event.metadata());
648 if self.ansi {
649 let (color, level) = match *metadata.level() {
650 Level::TRACE => ("\x1b[35m", "TRACE"),
651 Level::DEBUG => ("\x1b[34m", "DEBUG"),
652 Level::INFO => ("\x1b[32m", " INFO"),
653 Level::WARN => ("\x1b[33m", " WARN"),
654 Level::ERROR => ("\x1b[31m", "ERROR"),
655 };
656 write_styled(&mut writer, color, level, true)?;
657 writer.write_char(' ')?;
658 } else {
659 write!(writer, "{:>5} ", metadata.level())?;
660 }
661 if let Some(scope) = context.event_scope(event) {
662 let mut seen = false;
663 for span in scope.from_root() {
664 write_styled(&mut writer, "\x1b[1m", span.metadata().name(), self.ansi)?;
665 let fields = span
666 .extensions()
667 .get::<SpanCaches>()
668 .and_then(|caches| caches.get(&self.identity))
669 .cloned();
670 if let Some(cache) = fields {
674 let fields = cache.snapshot(&self.status)?;
675 if !fields.is_empty() {
676 write_styled(&mut writer, "\x1b[1m", "{", self.ansi)?;
677 write!(writer, "{fields}")?;
678 write_styled(&mut writer, "\x1b[1m", "}", self.ansi)?;
679 }
680 }
681 write_styled(&mut writer, "\x1b[2m", ":", self.ansi)?;
682 seen = true;
683 }
684 if seen {
685 writer.write_char(' ')?;
686 }
687 }
688 write_styled(&mut writer, "\x1b[2m", metadata.target(), self.ansi)?;
689 write_styled(&mut writer, "\x1b[2m", ":", self.ansi)?;
690 writer.write_char(' ')?;
691 format_fields(writer.by_ref(), event, self.ansi)?;
692 writeln!(writer)
693 })?;
694 if self.status.failure().is_some() {
695 return Err(fmt::Error);
696 }
697 Ok(buffer)
698 });
699 if let Ok(record) = record {
700 let _ = self
701 .writer
702 .write_record(record.text().as_bytes(), self.limits.event_bytes);
703 }
704 }
705}
706
707fn write_styled(writer: &mut Writer<'_>, prefix: &str, text: &str, ansi: bool) -> fmt::Result {
708 if ansi {
709 writer.write_str(prefix)?;
710 }
711 writer.write_str(text)?;
712 if ansi {
713 writer.write_str("\x1b[0m")?;
714 }
715 Ok(())
716}
717
718fn format_fields(writer: Writer<'_>, fields: impl RecordFields, ansi: bool) -> fmt::Result {
719 if !ansi {
720 return DefaultFields::new().format_fields(writer, fields);
721 }
722 let mut visitor = AnsiVisitor {
723 writer,
724 is_empty: true,
725 result: Ok(()),
726 };
727 fields.record(&mut visitor);
728 visitor.result
729}
730
731struct AnsiVisitor<'a> {
736 writer: Writer<'a>,
737 is_empty: bool,
738 result: fmt::Result,
739}
740
741impl Visit for AnsiVisitor<'_> {
742 fn record_str(&mut self, field: &Field, value: &str) {
743 if field.name() == "message" {
744 self.record_debug(field, &format_args!("{value}"));
745 } else {
746 self.record_debug(field, &value);
747 }
748 }
749
750 fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
751 if let Some(source) = value.source() {
752 self.record_debug(
753 field,
754 &format_args!(
755 "{} \x1b[3m{}\x1b[0m\x1b[3m.sources\x1b[0m\x1b[2m=\x1b[0m{}",
756 Sanitized(value),
757 field.name(),
758 ErrorSources(source),
759 ),
760 );
761 } else {
762 self.record_debug(field, &format_args!("{}", Sanitized(value)));
763 }
764 }
765
766 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
767 if self.result.is_err() || field.name().starts_with("log.") {
768 return;
769 }
770 if field.name() == "message" {
771 let mut visitor = DefaultVisitor::new(self.writer.by_ref(), self.is_empty);
772 visitor.record_debug(field, value);
773 self.result = visitor.finish();
774 } else {
775 self.result = (|| {
776 if !self.is_empty {
777 self.writer.write_char(' ')?;
778 }
779 let name = field.name().strip_prefix("r#").unwrap_or(field.name());
780 write_styled(&mut self.writer, "\x1b[3m", name, true)?;
781 write_styled(&mut self.writer, "\x1b[2m", "=", true)?;
782 write!(self.writer, "{value:?}")
783 })();
784 }
785 self.is_empty = false;
786 }
787}
788
789struct Sanitized<T>(T);
793
794impl<T: fmt::Display> fmt::Display for Sanitized<T> {
795 fn fmt(&self, writer: &mut fmt::Formatter<'_>) -> fmt::Result {
796 struct EscapingWriter<'a, 'b>(&'a mut fmt::Formatter<'b>);
797 impl fmt::Write for EscapingWriter<'_, '_> {
798 fn write_str(&mut self, text: &str) -> fmt::Result {
799 for ch in text.chars() {
800 match ch {
801 '\x1b' => self.0.write_str("\\x1b")?,
802 '\x07' => self.0.write_str("\\x07")?,
803 '\x08' => self.0.write_str("\\x08")?,
804 '\x0c' => self.0.write_str("\\x0c")?,
805 '\x7f' => self.0.write_str("\\x7f")?,
806 '\u{80}'..='\u{9f}' => write!(self.0, "\\u{{{:x}}}", ch as u32)?,
807 _ => fmt::Write::write_char(self.0, ch)?,
808 }
809 }
810 Ok(())
811 }
812 }
813 fmt::Write::write_fmt(&mut EscapingWriter(writer), format_args!("{}", self.0))
814 }
815}
816
817impl<T: fmt::Display> fmt::Debug for Sanitized<T> {
818 fn fmt(&self, writer: &mut fmt::Formatter<'_>) -> fmt::Result {
819 fmt::Display::fmt(self, writer)
820 }
821}
822
823struct ErrorSources<'a>(&'a (dyn std::error::Error + 'static));
824
825impl fmt::Display for ErrorSources<'_> {
826 fn fmt(&self, writer: &mut fmt::Formatter<'_>) -> fmt::Result {
827 let mut list = writer.debug_list();
828 let mut current = Some(self.0);
829 while let Some(error) = current {
830 list.entry(&Sanitized(error));
831 current = error.source();
832 }
833 list.finish()
834 }
835}
836
837struct RecordWriter<'sink, Sink> {
838 sink: &'sink Sink,
839 status: &'sink RecordStatus,
840}
841
842impl<Sink: Fn(&[u8]) -> io::Result<()>> Write for RecordWriter<'_, Sink> {
843 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
844 self.write_all(bytes).map(|()| bytes.len())
845 }
846
847 fn write_all(&mut self, bytes: &[u8]) -> io::Result<()> {
848 with_active(self.status, || {
849 let attempt = Attempt(Some(self.status));
850 let result = (self.sink)(bytes);
851 attempt.complete();
852 match result {
853 Ok(()) => Ok(()),
854 Err(error) => {
855 self.status.fail(RecordFailure::Sink(error));
856 Err(fmt::Error)
857 }
858 }
859 })
860 .map_err(|_| io::Error::other("complete record publication failed"))
861 }
862
863 fn flush(&mut self) -> io::Result<()> {
864 Ok(())
865 }
866}
867
868struct RecordWriterFactory<Sink> {
869 sink: Sink,
870 status: RecordStatus,
871}
872
873impl<Sink: Fn(&[u8]) -> io::Result<()>> RecordWriterFactory<Sink> {
874 fn write_record(&self, bytes: &[u8], limit: usize) -> io::Result<()> {
875 if bytes.len() > limit {
876 self.status.fail(RecordFailure::Size {
877 buffer: BufferKind::Event,
878 limit,
879 });
880 return Err(io::Error::new(
881 io::ErrorKind::InvalidData,
882 "oversized formatted record",
883 ));
884 }
885 self.make_writer().write_all(bytes)
886 }
887}
888
889impl<'sink, Sink: Fn(&[u8]) -> io::Result<()> + 'sink> MakeWriter<'sink>
890 for RecordWriterFactory<Sink>
891{
892 type Writer = RecordWriter<'sink, Sink>;
893
894 fn make_writer(&'sink self) -> Self::Writer {
895 RecordWriter {
896 sink: &self.sink,
897 status: &self.status,
898 }
899 }
900}
901
902pub fn record_subscriber_with_failure<Sink>(
919 filter: EnvFilter,
920 limits: FormatterLimits,
921 sink: Sink,
922 failure: impl Fn() + Send + Sync + 'static,
923) -> (impl Subscriber + Send + Sync, RecordStatus)
924where
925 Sink: Fn(&[u8]) -> io::Result<()> + Send + Sync + 'static,
926{
927 let status = RecordStatus::default();
928 let _ = status.1.set(Box::new(failure));
929 subscriber_with_status(filter, limits, sink, SystemTime, true, status)
930}
931
932pub fn record_layer_with_failure<Registry, Sink>(
944 limits: FormatterLimits,
945 sink: Sink,
946 failure: impl Fn() + Send + Sync + 'static,
947) -> (impl Layer<Registry> + Send + Sync, RecordStatus)
948where
949 Registry: Subscriber + for<'lookup> LookupSpan<'lookup>,
950 Sink: Fn(&[u8]) -> io::Result<()> + Send + Sync + 'static,
951{
952 record_layer_with_failure_and_ansi(limits, sink, failure, false)
953}
954
955pub fn record_layer_with_failure_and_ansi<Registry, Sink>(
964 limits: FormatterLimits,
965 sink: Sink,
966 failure: impl Fn() + Send + Sync + 'static,
967 ansi: bool,
968) -> (impl Layer<Registry> + Send + Sync, RecordStatus)
969where
970 Registry: Subscriber + for<'lookup> LookupSpan<'lookup>,
971 Sink: Fn(&[u8]) -> io::Result<()> + Send + Sync + 'static,
972{
973 let status = RecordStatus::default();
974 let _ = status.1.set(Box::new(failure));
975 (
976 RecordLayer {
977 ansi,
978 ..layer_with_status(limits, sink, SystemTime, true, status.clone())
979 },
980 status,
981 )
982}
983
984fn subscriber_with_status<Sink, Timer>(
985 filter: EnvFilter,
986 limits: FormatterLimits,
987 sink: Sink,
988 timer: Timer,
989 timestamp: bool,
990 status: RecordStatus,
991) -> (impl Subscriber + Send + Sync, RecordStatus)
992where
993 Sink: Fn(&[u8]) -> io::Result<()> + Send + Sync + 'static,
994 Timer: FormatTime + Send + Sync + 'static,
995{
996 let layer = layer_with_status(limits, sink, timer, timestamp, status.clone());
997 (
998 tracing_subscriber::registry().with(layer).with(filter),
999 status,
1000 )
1001}
1002
1003fn layer_with_status<Sink, Timer>(
1004 limits: FormatterLimits,
1005 sink: Sink,
1006 timer: Timer,
1007 timestamp: bool,
1008 status: RecordStatus,
1009) -> RecordLayer<Timer, Sink> {
1010 RecordLayer {
1011 identity: Arc::new(()),
1012 timer,
1013 timestamp,
1014 ansi: false,
1015 limits,
1016 status: status.clone(),
1017 writer: RecordWriterFactory {
1018 sink,
1019 status: status.clone(),
1020 },
1021 }
1022}
1023
1024#[cfg(test)]
1025mod tests;