1use crate::{
2 field::RecordFields,
3 fmt::{format, FormatEvent, FormatFields, MakeWriter, TestWriter},
4 registry::{self, LookupSpan, SpanRef},
5 subscribe::{self, Context},
6};
7use format::{FmtSpan, TimingDisplay};
8use std::{
9 any::TypeId, cell::RefCell, env, fmt, io, marker::PhantomData, ops::Deref, ptr::NonNull,
10 time::Instant,
11};
12use tracing_core::{
13 field,
14 span::{Attributes, Current, Id, Record},
15 Collect, Event, Metadata,
16};
17
18#[derive(Debug)]
64#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
65pub struct Subscriber<C, N = format::DefaultFields, E = format::Format, W = fn() -> io::Stdout> {
66 make_writer: W,
67 fmt_fields: N,
68 fmt_event: E,
69 fmt_span: format::FmtSpanConfig,
70 is_ansi: bool,
71 log_internal_errors: bool,
72 _inner: PhantomData<fn(C)>,
73}
74
75impl<C> Subscriber<C> {
76 pub fn new() -> Self {
78 Self::default()
79 }
80}
81
82impl<C, N, E, W> Subscriber<C, N, E, W>
84where
85 C: Collect + for<'a> LookupSpan<'a>,
86 N: for<'writer> FormatFields<'writer> + 'static,
87 W: for<'writer> MakeWriter<'writer> + 'static,
88{
89 pub fn event_format<E2>(self, e: E2) -> Subscriber<C, N, E2, W>
112 where
113 E2: FormatEvent<C, N> + 'static,
114 {
115 Subscriber {
116 fmt_fields: self.fmt_fields,
117 fmt_event: e,
118 fmt_span: self.fmt_span,
119 make_writer: self.make_writer,
120 is_ansi: self.is_ansi,
121 log_internal_errors: self.log_internal_errors,
122 _inner: self._inner,
123 }
124 }
125
126 pub fn map_event_format<E2>(self, f: impl FnOnce(E) -> E2) -> Subscriber<C, N, E2, W>
142 where
143 E2: FormatEvent<C, N> + 'static,
144 {
145 Subscriber {
146 fmt_fields: self.fmt_fields,
147 fmt_event: f(self.fmt_event),
148 fmt_span: self.fmt_span,
149 make_writer: self.make_writer,
150 is_ansi: self.is_ansi,
151 log_internal_errors: self.log_internal_errors,
152 _inner: self._inner,
153 }
154 }
155}
156
157impl<C, N, E, W> Subscriber<C, N, E, W> {
159 pub fn with_writer<W2>(self, make_writer: W2) -> Subscriber<C, N, E, W2>
179 where
180 W2: for<'writer> MakeWriter<'writer> + 'static,
181 {
182 Subscriber {
183 fmt_fields: self.fmt_fields,
184 fmt_event: self.fmt_event,
185 fmt_span: self.fmt_span,
186 is_ansi: self.is_ansi,
187 log_internal_errors: self.log_internal_errors,
188 make_writer,
189 _inner: self._inner,
190 }
191 }
192
193 pub fn writer(&self) -> &W {
197 &self.make_writer
198 }
199
200 pub fn writer_mut(&mut self) -> &mut W {
228 &mut self.make_writer
229 }
230
231 #[cfg(feature = "ansi")]
238 #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
239 pub fn set_ansi(&mut self, ansi: bool) {
240 self.is_ansi = ansi;
241 }
242
243 pub fn set_span_events(&mut self, kind: FmtSpan) {
258 self.fmt_span = format::FmtSpanConfig {
259 kind,
260 fmt_timing: self.fmt_span.fmt_timing,
261 }
262 }
263
264 pub fn with_test_writer(self) -> Subscriber<C, N, E, TestWriter> {
287 Subscriber {
288 fmt_fields: self.fmt_fields,
289 fmt_event: self.fmt_event,
290 fmt_span: self.fmt_span,
291 is_ansi: self.is_ansi,
292 log_internal_errors: self.log_internal_errors,
293 make_writer: TestWriter::default(),
294 _inner: self._inner,
295 }
296 }
297
298 pub fn with_ansi(self, ansi: bool) -> Self {
326 #[cfg(not(feature = "ansi"))]
327 if ansi {
328 const ERROR: &str =
329 "tracing-subscriber: the `ansi` crate feature is required to enable ANSI terminal colors";
330 #[cfg(debug_assertions)]
331 panic!("{}", ERROR);
332 #[cfg(not(debug_assertions))]
333 eprintln!("{}", ERROR);
334 }
335
336 Subscriber {
337 is_ansi: ansi,
338 ..self
339 }
340 }
341
342 pub fn log_internal_errors(self, log_internal_errors: bool) -> Self {
354 Self {
355 log_internal_errors,
356 ..self
357 }
358 }
359
360 pub fn map_writer<W2>(self, f: impl FnOnce(W) -> W2) -> Subscriber<C, N, E, W2>
380 where
381 W2: for<'writer> MakeWriter<'writer> + 'static,
382 {
383 Subscriber {
384 fmt_fields: self.fmt_fields,
385 fmt_event: self.fmt_event,
386 fmt_span: self.fmt_span,
387 is_ansi: self.is_ansi,
388 log_internal_errors: self.log_internal_errors,
389 make_writer: f(self.make_writer),
390 _inner: self._inner,
391 }
392 }
393}
394
395impl<C, N, L, T, W> Subscriber<C, N, format::Format<L, T>, W>
396where
397 N: for<'writer> FormatFields<'writer> + 'static,
398{
399 pub fn with_timer<T2>(self, timer: T2) -> Subscriber<C, N, format::Format<L, T2>, W> {
414 Subscriber {
415 fmt_event: self.fmt_event.with_timer(timer),
416 fmt_fields: self.fmt_fields,
417 fmt_span: self.fmt_span,
418 make_writer: self.make_writer,
419 is_ansi: self.is_ansi,
420 log_internal_errors: self.log_internal_errors,
421 _inner: self._inner,
422 }
423 }
424
425 pub fn without_time(self) -> Subscriber<C, N, format::Format<L, ()>, W> {
427 Subscriber {
428 fmt_event: self.fmt_event.without_time(),
429 fmt_fields: self.fmt_fields,
430 fmt_span: self.fmt_span.without_time(),
431 make_writer: self.make_writer,
432 is_ansi: self.is_ansi,
433 log_internal_errors: self.log_internal_errors,
434 _inner: self._inner,
435 }
436 }
437
438 pub fn with_span_events(self, kind: FmtSpan) -> Self {
480 Subscriber {
481 fmt_span: self.fmt_span.with_kind(kind),
482 ..self
483 }
484 }
485
486 pub fn with_target(self, display_target: bool) -> Subscriber<C, N, format::Format<L, T>, W> {
488 Subscriber {
489 fmt_event: self.fmt_event.with_target(display_target),
490 ..self
491 }
492 }
493 pub fn with_file(self, display_filename: bool) -> Subscriber<C, N, format::Format<L, T>, W> {
498 Subscriber {
499 fmt_event: self.fmt_event.with_file(display_filename),
500 ..self
501 }
502 }
503
504 pub fn with_line_number(
509 self,
510 display_line_number: bool,
511 ) -> Subscriber<C, N, format::Format<L, T>, W> {
512 Subscriber {
513 fmt_event: self.fmt_event.with_line_number(display_line_number),
514 ..self
515 }
516 }
517
518 pub fn with_level(self, display_level: bool) -> Subscriber<C, N, format::Format<L, T>, W> {
520 Subscriber {
521 fmt_event: self.fmt_event.with_level(display_level),
522 ..self
523 }
524 }
525
526 pub fn with_thread_ids(
531 self,
532 display_thread_ids: bool,
533 ) -> Subscriber<C, N, format::Format<L, T>, W> {
534 Subscriber {
535 fmt_event: self.fmt_event.with_thread_ids(display_thread_ids),
536 ..self
537 }
538 }
539
540 pub fn with_thread_names(
545 self,
546 display_thread_names: bool,
547 ) -> Subscriber<C, N, format::Format<L, T>, W> {
548 Subscriber {
549 fmt_event: self.fmt_event.with_thread_names(display_thread_names),
550 ..self
551 }
552 }
553
554 pub fn compact(self) -> Subscriber<C, N, format::Format<format::Compact, T>, W>
556 where
557 N: for<'writer> FormatFields<'writer> + 'static,
558 {
559 Subscriber {
560 fmt_event: self.fmt_event.compact(),
561 fmt_fields: self.fmt_fields,
562 fmt_span: self.fmt_span,
563 make_writer: self.make_writer,
564 is_ansi: self.is_ansi,
565 log_internal_errors: self.log_internal_errors,
566 _inner: self._inner,
567 }
568 }
569
570 #[cfg(feature = "ansi")]
572 #[cfg_attr(docsrs, doc(cfg(feature = "ansi")))]
573 pub fn pretty(self) -> Subscriber<C, format::Pretty, format::Format<format::Pretty, T>, W> {
574 Subscriber {
575 fmt_event: self.fmt_event.pretty(),
576 fmt_fields: format::Pretty::default(),
577 fmt_span: self.fmt_span,
578 make_writer: self.make_writer,
579 is_ansi: self.is_ansi,
580 log_internal_errors: self.log_internal_errors,
581 _inner: self._inner,
582 }
583 }
584
585 #[cfg(feature = "json")]
601 #[cfg_attr(docsrs, doc(cfg(feature = "json")))]
602 pub fn json(self) -> Subscriber<C, format::JsonFields, format::Format<format::Json, T>, W> {
603 Subscriber {
604 fmt_event: self.fmt_event.json(),
605 fmt_fields: format::JsonFields::new(),
606 fmt_span: self.fmt_span,
607 make_writer: self.make_writer,
608 is_ansi: false,
610 log_internal_errors: self.log_internal_errors,
611 _inner: self._inner,
612 }
613 }
614}
615
616#[cfg(feature = "json")]
617#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
618impl<C, T, W> Subscriber<C, format::JsonFields, format::Format<format::Json, T>, W> {
619 pub fn flatten_event(
623 self,
624 flatten_event: bool,
625 ) -> Subscriber<C, format::JsonFields, format::Format<format::Json, T>, W> {
626 Subscriber {
627 fmt_event: self.fmt_event.flatten_event(flatten_event),
628 fmt_fields: format::JsonFields::new(),
629 ..self
630 }
631 }
632
633 pub fn with_current_span(
638 self,
639 display_current_span: bool,
640 ) -> Subscriber<C, format::JsonFields, format::Format<format::Json, T>, W> {
641 Subscriber {
642 fmt_event: self.fmt_event.with_current_span(display_current_span),
643 fmt_fields: format::JsonFields::new(),
644 ..self
645 }
646 }
647
648 pub fn with_span_list(
653 self,
654 display_span_list: bool,
655 ) -> Subscriber<C, format::JsonFields, format::Format<format::Json, T>, W> {
656 Subscriber {
657 fmt_event: self.fmt_event.with_span_list(display_span_list),
658 fmt_fields: format::JsonFields::new(),
659 ..self
660 }
661 }
662}
663
664impl<C, N, E, W> Subscriber<C, N, E, W> {
665 pub fn fmt_fields<N2>(self, fmt_fields: N2) -> Subscriber<C, N2, E, W>
668 where
669 N2: for<'writer> FormatFields<'writer> + 'static,
670 {
671 Subscriber {
672 fmt_event: self.fmt_event,
673 fmt_fields,
674 fmt_span: self.fmt_span,
675 make_writer: self.make_writer,
676 is_ansi: self.is_ansi,
677 log_internal_errors: self.log_internal_errors,
678 _inner: self._inner,
679 }
680 }
681
682 pub fn map_fmt_fields<N2>(self, f: impl FnOnce(N) -> N2) -> Subscriber<C, N2, E, W>
699 where
700 N2: for<'writer> FormatFields<'writer> + 'static,
701 {
702 Subscriber {
703 fmt_event: self.fmt_event,
704 fmt_fields: f(self.fmt_fields),
705 fmt_span: self.fmt_span,
706 make_writer: self.make_writer,
707 is_ansi: self.is_ansi,
708 log_internal_errors: self.log_internal_errors,
709 _inner: self._inner,
710 }
711 }
712}
713
714impl<C> Default for Subscriber<C> {
715 fn default() -> Self {
716 let ansi = cfg!(feature = "ansi") && env::var("NO_COLOR").map_or(true, |v| v.is_empty());
719
720 Subscriber {
721 fmt_fields: format::DefaultFields::default(),
722 fmt_event: format::Format::default(),
723 fmt_span: format::FmtSpanConfig::default(),
724 make_writer: io::stdout,
725 is_ansi: ansi,
726 log_internal_errors: false,
727 _inner: PhantomData,
728 }
729 }
730}
731
732impl<C, N, E, W> Subscriber<C, N, E, W>
733where
734 C: Collect + for<'a> LookupSpan<'a>,
735 N: for<'writer> FormatFields<'writer> + 'static,
736 E: FormatEvent<C, N> + 'static,
737 W: for<'writer> MakeWriter<'writer> + 'static,
738{
739 #[inline]
740 fn make_ctx<'a>(&'a self, ctx: Context<'a, C>, event: &'a Event<'a>) -> FmtContext<'a, C, N> {
741 FmtContext {
742 ctx,
743 fmt_fields: &self.fmt_fields,
744 event,
745 }
746 }
747}
748
749#[derive(Default)]
759pub struct FormattedFields<E: ?Sized> {
760 _format_fields: PhantomData<fn(E)>,
761 was_ansi: bool,
762 pub fields: String,
764}
765
766impl<E: ?Sized> FormattedFields<E> {
767 pub fn new(fields: String) -> Self {
769 Self {
770 fields,
771 was_ansi: false,
772 _format_fields: PhantomData,
773 }
774 }
775
776 pub fn as_writer(&mut self) -> format::Writer<'_> {
781 format::Writer::new(&mut self.fields).with_ansi(self.was_ansi)
782 }
783}
784
785impl<E: ?Sized> fmt::Debug for FormattedFields<E> {
786 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
787 f.debug_struct("FormattedFields")
788 .field("fields", &self.fields)
789 .field("formatter", &format_args!("{}", std::any::type_name::<E>()))
790 .field("was_ansi", &self.was_ansi)
791 .finish()
792 }
793}
794
795impl<E: ?Sized> fmt::Display for FormattedFields<E> {
796 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
797 fmt::Display::fmt(&self.fields, f)
798 }
799}
800
801impl<E: ?Sized> Deref for FormattedFields<E> {
802 type Target = String;
803 fn deref(&self) -> &Self::Target {
804 &self.fields
805 }
806}
807
808macro_rules! with_event_from_span {
811 ($id:ident, $span:ident, $($field:literal = $value:expr),*, |$event:ident| $code:block) => {
812 let meta = $span.metadata();
813 let cs = meta.callsite();
814 let fs = field::FieldSet::new(&[$($field),*], cs);
815 #[allow(unused)]
816 let mut iter = fs.iter();
817 let v = [$(
818 (&iter.next().unwrap(), ::core::option::Option::Some(&$value as &dyn field::Value)),
819 )*];
820 let vs = fs.value_set(&v);
821 let $event = Event::new_child_of($id, meta, &vs);
822 $code
823 };
824}
825
826impl<C, N, E, W> subscribe::Subscribe<C> for Subscriber<C, N, E, W>
827where
828 C: Collect + for<'a> LookupSpan<'a>,
829 N: for<'writer> FormatFields<'writer> + 'static,
830 E: FormatEvent<C, N> + 'static,
831 W: for<'writer> MakeWriter<'writer> + 'static,
832{
833 fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, C>) {
834 let span = ctx.span(id).expect("Span not found, this is a bug");
835 let mut extensions = span.extensions_mut();
836
837 if extensions.get_mut::<FormattedFields<N>>().is_none() {
838 let mut fields = FormattedFields::<N>::new(String::new());
839 if self
840 .fmt_fields
841 .format_fields(fields.as_writer().with_ansi(self.is_ansi), attrs)
842 .is_ok()
843 {
844 fields.was_ansi = self.is_ansi;
845 extensions.insert(fields);
846 } else {
847 eprintln!(
848 "[tracing-subscriber] Unable to format the following event, ignoring: {:?}",
849 attrs
850 );
851 }
852 }
853
854 if self.fmt_span.fmt_timing
855 && self.fmt_span.trace_close()
856 && extensions.get_mut::<Timings>().is_none()
857 {
858 extensions.insert(Timings::new());
859 }
860
861 if self.fmt_span.trace_new() {
862 with_event_from_span!(id, span, "message" = "new", |event| {
863 drop(extensions);
864 drop(span);
865 self.on_event(&event, ctx);
866 });
867 }
868 }
869
870 fn on_record(&self, id: &Id, values: &Record<'_>, ctx: Context<'_, C>) {
871 let span = ctx.span(id).expect("Span not found, this is a bug");
872 let mut extensions = span.extensions_mut();
873 if let Some(fields) = extensions.get_mut::<FormattedFields<N>>() {
874 let _ = self.fmt_fields.add_fields(fields, values);
875 return;
876 }
877
878 let mut fields = FormattedFields::<N>::new(String::new());
879 if self
880 .fmt_fields
881 .format_fields(fields.as_writer().with_ansi(self.is_ansi), values)
882 .is_ok()
883 {
884 fields.was_ansi = self.is_ansi;
885 extensions.insert(fields);
886 }
887 }
888
889 fn on_enter(&self, id: &Id, ctx: Context<'_, C>) {
890 if self.fmt_span.trace_enter() || self.fmt_span.trace_close() && self.fmt_span.fmt_timing {
891 let span = ctx.span(id).expect("Span not found, this is a bug");
892 let mut extensions = span.extensions_mut();
893 if let Some(timings) = extensions.get_mut::<Timings>() {
894 let now = Instant::now();
895 timings.idle += (now - timings.last).as_nanos() as u64;
896 timings.last = now;
897 }
898
899 if self.fmt_span.trace_enter() {
900 with_event_from_span!(id, span, "message" = "enter", |event| {
901 drop(extensions);
902 drop(span);
903 self.on_event(&event, ctx);
904 });
905 }
906 }
907 }
908
909 fn on_exit(&self, id: &Id, ctx: Context<'_, C>) {
910 if self.fmt_span.trace_exit() || self.fmt_span.trace_close() && self.fmt_span.fmt_timing {
911 let span = ctx.span(id).expect("Span not found, this is a bug");
912 let mut extensions = span.extensions_mut();
913 if let Some(timings) = extensions.get_mut::<Timings>() {
914 let now = Instant::now();
915 timings.busy += (now - timings.last).as_nanos() as u64;
916 timings.last = now;
917 }
918
919 if self.fmt_span.trace_exit() {
920 with_event_from_span!(id, span, "message" = "exit", |event| {
921 drop(extensions);
922 drop(span);
923 self.on_event(&event, ctx);
924 });
925 }
926 }
927 }
928
929 fn on_close(&self, id: Id, ctx: Context<'_, C>) {
930 if self.fmt_span.trace_close() {
931 let span = ctx.span(&id).expect("Span not found, this is a bug");
932 let extensions = span.extensions();
933 if let Some(timing) = extensions.get::<Timings>() {
934 let Timings {
935 busy,
936 mut idle,
937 last,
938 } = *timing;
939 idle += (Instant::now() - last).as_nanos() as u64;
940
941 let t_idle = field::display(TimingDisplay(idle));
942 let t_busy = field::display(TimingDisplay(busy));
943
944 with_event_from_span!(
945 id,
946 span,
947 "message" = "close",
948 "time.busy" = t_busy,
949 "time.idle" = t_idle,
950 |event| {
951 drop(extensions);
952 drop(span);
953 self.on_event(&event, ctx);
954 }
955 );
956 } else {
957 with_event_from_span!(id, span, "message" = "close", |event| {
958 drop(extensions);
959 drop(span);
960 self.on_event(&event, ctx);
961 });
962 }
963 }
964 }
965
966 fn on_event(&self, event: &Event<'_>, ctx: Context<'_, C>) {
967 thread_local! {
968 static BUF: RefCell<String> = const { RefCell::new(String::new()) };
969 }
970
971 BUF.with(|buf| {
972 let borrow = buf.try_borrow_mut();
973 let mut a;
974 let mut b;
975 let mut buf = match borrow {
976 Ok(buf) => {
977 a = buf;
978 &mut *a
979 }
980 _ => {
981 b = String::new();
982 &mut b
983 }
984 };
985
986 let ctx = self.make_ctx(ctx, event);
987 if self
988 .fmt_event
989 .format_event(
990 &ctx,
991 format::Writer::new(&mut buf).with_ansi(self.is_ansi),
992 event,
993 )
994 .is_ok()
995 {
996 let mut writer = self.make_writer.make_writer_for(event.metadata());
997 let res = io::Write::write_all(&mut writer, buf.as_bytes());
998 if self.log_internal_errors {
999 if let Err(e) = res {
1000 eprintln!("[tracing-subscriber] Unable to write an event to the Writer for this Subscriber! Error: {}\n", e);
1001 }
1002 }
1003 } else if self.log_internal_errors {
1004 let err_msg = format!("Unable to format the following event. Name: {}; Fields: {:?}\n",
1005 event.metadata().name(), event.fields());
1006 let mut writer = self.make_writer.make_writer_for(event.metadata());
1007 let res = io::Write::write_all(&mut writer, err_msg.as_bytes());
1008 if let Err(e) = res {
1009 eprintln!("[tracing-subscriber] Unable to write an \"event formatting error\" to the Writer for this Subscriber! Error: {}\n", e);
1010 }
1011 }
1012
1013 buf.clear();
1014 });
1015 }
1016
1017 unsafe fn downcast_raw(&self, id: TypeId) -> Option<NonNull<()>> {
1018 match () {
1023 _ if id == TypeId::of::<Self>() => Some(NonNull::from(self).cast()),
1024 _ if id == TypeId::of::<E>() => Some(NonNull::from(&self.fmt_event).cast()),
1025 _ if id == TypeId::of::<N>() => Some(NonNull::from(&self.fmt_fields).cast()),
1026 _ if id == TypeId::of::<W>() => Some(NonNull::from(&self.make_writer).cast()),
1027 _ => None,
1028 }
1029 }
1030}
1031
1032pub struct FmtContext<'a, C, N> {
1034 pub(crate) ctx: Context<'a, C>,
1035 pub(crate) fmt_fields: &'a N,
1036 pub(crate) event: &'a Event<'a>,
1037}
1038
1039impl<C, N> fmt::Debug for FmtContext<'_, C, N> {
1040 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1041 f.debug_struct("FmtContext").finish()
1042 }
1043}
1044
1045impl<'writer, C, N> FormatFields<'writer> for FmtContext<'_, C, N>
1046where
1047 C: Collect + for<'lookup> LookupSpan<'lookup>,
1048 N: FormatFields<'writer> + 'static,
1049{
1050 fn format_fields<R: RecordFields>(
1051 &self,
1052 writer: format::Writer<'writer>,
1053 fields: R,
1054 ) -> fmt::Result {
1055 self.fmt_fields.format_fields(writer, fields)
1056 }
1057}
1058
1059impl<C, N> FmtContext<'_, C, N>
1060where
1061 C: Collect + for<'lookup> LookupSpan<'lookup>,
1062 N: for<'writer> FormatFields<'writer> + 'static,
1063{
1064 pub fn visit_spans<E, F>(&self, mut f: F) -> Result<(), E>
1070 where
1071 F: FnMut(&SpanRef<'_, C>) -> Result<(), E>,
1072 {
1073 if let Some(scope) = self.event_scope() {
1075 for span in scope.from_root() {
1076 f(&span)?;
1077 }
1078 }
1079 Ok(())
1080 }
1081
1082 #[inline]
1087 pub fn metadata(&self, id: &Id) -> Option<&'static Metadata<'static>>
1088 where
1089 C: for<'lookup> LookupSpan<'lookup>,
1090 {
1091 self.ctx.metadata(id)
1092 }
1093
1094 #[inline]
1101 pub fn span(&self, id: &Id) -> Option<SpanRef<'_, C>>
1102 where
1103 C: for<'lookup> LookupSpan<'lookup>,
1104 {
1105 self.ctx.span(id)
1106 }
1107
1108 #[inline]
1110 pub fn exists(&self, id: &Id) -> bool
1111 where
1112 C: for<'lookup> LookupSpan<'lookup>,
1113 {
1114 self.ctx.exists(id)
1115 }
1116
1117 #[inline]
1124 pub fn lookup_current(&self) -> Option<SpanRef<'_, C>>
1125 where
1126 C: for<'lookup> LookupSpan<'lookup>,
1127 {
1128 self.ctx.lookup_current()
1129 }
1130
1131 pub fn current_span(&self) -> Current {
1133 self.ctx.current_span()
1134 }
1135
1136 pub fn parent_span(&self) -> Option<SpanRef<'_, C>> {
1145 self.ctx.event_span(self.event)
1146 }
1147
1148 pub fn span_scope(&self, id: &Id) -> Option<registry::Scope<'_, C>>
1175 where
1176 C: for<'lookup> LookupSpan<'lookup>,
1177 {
1178 self.ctx.span_scope(id)
1179 }
1180
1181 pub fn event_scope(&self) -> Option<registry::Scope<'_, C>>
1206 where
1207 C: for<'lookup> registry::LookupSpan<'lookup>,
1208 {
1209 self.ctx.event_scope(self.event)
1210 }
1211
1212 pub fn field_format(&self) -> &N {
1220 self.fmt_fields
1221 }
1222}
1223
1224struct Timings {
1225 idle: u64,
1226 busy: u64,
1227 last: Instant,
1228}
1229
1230impl Timings {
1231 fn new() -> Self {
1232 Self {
1233 idle: 0,
1234 busy: 0,
1235 last: Instant::now(),
1236 }
1237 }
1238}
1239
1240#[cfg(test)]
1241mod test {
1242 use super::*;
1243 use crate::fmt::{
1244 self,
1245 format::{self, test::MockTime, Format},
1246 subscribe::Subscribe as _,
1247 test::{MockMakeWriter, MockWriter},
1248 time,
1249 };
1250 use crate::Registry;
1251 use format::FmtSpan;
1252 use regex::Regex;
1253 use tracing::collect::with_default;
1254 use tracing_core::dispatch::Dispatch;
1255
1256 #[test]
1257 fn impls() {
1258 let f = Format::default().with_timer(time::Uptime::default());
1259 let fmt = fmt::Subscriber::default().event_format(f);
1260 let subscriber = fmt.with_collector(Registry::default());
1261 let _dispatch = Dispatch::new(subscriber);
1262
1263 let f = format::Format::default();
1264 let fmt = fmt::Subscriber::default().event_format(f);
1265 let subscriber = fmt.with_collector(Registry::default());
1266 let _dispatch = Dispatch::new(subscriber);
1267
1268 let f = format::Format::default().compact();
1269 let fmt = fmt::Subscriber::default().event_format(f);
1270 let subscriber = fmt.with_collector(Registry::default());
1271 let _dispatch = Dispatch::new(subscriber);
1272 }
1273
1274 #[test]
1275 fn fmt_subscriber_downcasts() {
1276 let f = format::Format::default();
1277 let fmt = fmt::Subscriber::default().event_format(f);
1278 let subscriber = fmt.with_collector(Registry::default());
1279
1280 let dispatch = Dispatch::new(subscriber);
1281 assert!(dispatch
1282 .downcast_ref::<fmt::Subscriber<Registry>>()
1283 .is_some());
1284 }
1285
1286 #[test]
1287 fn fmt_subscriber_downcasts_to_parts() {
1288 let f = format::Format::default();
1289 let fmt = fmt::Subscriber::default().event_format(f);
1290 let subscriber = fmt.with_collector(Registry::default());
1291 let dispatch = Dispatch::new(subscriber);
1292 assert!(dispatch.downcast_ref::<format::DefaultFields>().is_some());
1293 assert!(dispatch.downcast_ref::<format::Format>().is_some())
1294 }
1295
1296 #[test]
1297 fn is_lookup_span() {
1298 fn assert_lookup_span<T: for<'a> crate::registry::LookupSpan<'a>>(_: T) {}
1299 let fmt = fmt::Subscriber::default();
1300 let subscriber = fmt.with_collector(Registry::default());
1301 assert_lookup_span(subscriber)
1302 }
1303
1304 fn sanitize_timings(s: String) -> String {
1305 let re = Regex::new("time\\.(idle|busy)=([0-9.]+)[mµn]s").unwrap();
1306 re.replace_all(s.as_str(), "timing").to_string()
1307 }
1308
1309 #[test]
1310 fn format_error_print_to_stderr() {
1311 struct AlwaysError;
1312
1313 impl std::fmt::Debug for AlwaysError {
1314 fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1315 Err(std::fmt::Error)
1316 }
1317 }
1318
1319 let make_writer = MockMakeWriter::default();
1320 let subscriber = crate::fmt::Collector::builder()
1321 .with_writer(make_writer.clone())
1322 .with_level(false)
1323 .with_ansi(false)
1324 .with_timer(MockTime)
1325 .finish();
1326
1327 with_default(subscriber, || {
1328 tracing::info!(?AlwaysError);
1329 });
1330 let actual = sanitize_timings(make_writer.get_string());
1331
1332 let expected = concat!(
1334 "Unable to format the following event. Name: event ",
1335 file!(),
1336 ":"
1337 );
1338 assert!(
1339 actual.as_str().starts_with(expected),
1340 "\nactual = {}\nshould start with expected = {}\n",
1341 actual,
1342 expected
1343 );
1344 }
1345
1346 #[test]
1347 fn format_error_ignore_if_log_internal_errors_is_false() {
1348 struct AlwaysError;
1349
1350 impl std::fmt::Debug for AlwaysError {
1351 fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1352 Err(std::fmt::Error)
1353 }
1354 }
1355
1356 let make_writer = MockMakeWriter::default();
1357 let subscriber = crate::fmt::Collector::builder()
1358 .with_writer(make_writer.clone())
1359 .with_level(false)
1360 .with_ansi(false)
1361 .with_timer(MockTime)
1362 .log_internal_errors(false)
1363 .finish();
1364
1365 with_default(subscriber, || {
1366 tracing::info!(?AlwaysError);
1367 });
1368 let actual = sanitize_timings(make_writer.get_string());
1369 assert_eq!("", actual.as_str());
1370 }
1371
1372 #[test]
1373 fn synthesize_span_none() {
1374 let make_writer = MockMakeWriter::default();
1375 let subscriber = crate::fmt::Collector::builder()
1376 .with_writer(make_writer.clone())
1377 .with_level(false)
1378 .with_ansi(false)
1379 .with_timer(MockTime)
1380 .finish();
1382
1383 with_default(subscriber, || {
1384 let span1 = tracing::info_span!("span1", x = 42);
1385 let _e = span1.enter();
1386 });
1387 let actual = sanitize_timings(make_writer.get_string());
1388 assert_eq!("", actual.as_str());
1389 }
1390
1391 #[test]
1392 fn synthesize_span_active() {
1393 let make_writer = MockMakeWriter::default();
1394 let subscriber = crate::fmt::Collector::builder()
1395 .with_writer(make_writer.clone())
1396 .with_level(false)
1397 .with_ansi(false)
1398 .with_timer(MockTime)
1399 .with_span_events(FmtSpan::ACTIVE)
1400 .finish();
1401
1402 with_default(subscriber, || {
1403 let span1 = tracing::info_span!("span1", x = 42);
1404 let _e = span1.enter();
1405 });
1406 let actual = sanitize_timings(make_writer.get_string());
1407 assert_eq!(
1408 "fake time span1{x=42}: tracing_subscriber::fmt::fmt_subscriber::test: enter\n\
1409 fake time span1{x=42}: tracing_subscriber::fmt::fmt_subscriber::test: exit\n",
1410 actual.as_str()
1411 );
1412 }
1413
1414 #[test]
1415 fn synthesize_span_close() {
1416 let make_writer = MockMakeWriter::default();
1417 let subscriber = crate::fmt::Collector::builder()
1418 .with_writer(make_writer.clone())
1419 .with_level(false)
1420 .with_ansi(false)
1421 .with_timer(MockTime)
1422 .with_span_events(FmtSpan::CLOSE)
1423 .finish();
1424
1425 with_default(subscriber, || {
1426 let span1 = tracing::info_span!("span1", x = 42);
1427 let _e = span1.enter();
1428 });
1429 let actual = sanitize_timings(make_writer.get_string());
1430 assert_eq!(
1431 "fake time span1{x=42}: tracing_subscriber::fmt::fmt_subscriber::test: close timing timing\n",
1432 actual.as_str()
1433 );
1434 }
1435
1436 #[test]
1437 fn synthesize_span_close_no_timing() {
1438 let make_writer = MockMakeWriter::default();
1439 let subscriber = crate::fmt::Collector::builder()
1440 .with_writer(make_writer.clone())
1441 .with_level(false)
1442 .with_ansi(false)
1443 .with_timer(MockTime)
1444 .without_time()
1445 .with_span_events(FmtSpan::CLOSE)
1446 .finish();
1447
1448 with_default(subscriber, || {
1449 let span1 = tracing::info_span!("span1", x = 42);
1450 let _e = span1.enter();
1451 });
1452 let actual = sanitize_timings(make_writer.get_string());
1453 assert_eq!(
1454 "span1{x=42}: tracing_subscriber::fmt::fmt_subscriber::test: close\n",
1455 actual.as_str()
1456 );
1457 }
1458
1459 #[test]
1460 fn synthesize_span_full() {
1461 let make_writer = MockMakeWriter::default();
1462 let subscriber = crate::fmt::Collector::builder()
1463 .with_writer(make_writer.clone())
1464 .with_level(false)
1465 .with_ansi(false)
1466 .with_timer(MockTime)
1467 .with_span_events(FmtSpan::FULL)
1468 .finish();
1469
1470 with_default(subscriber, || {
1471 let span1 = tracing::info_span!("span1", x = 42);
1472 let _e = span1.enter();
1473 });
1474 let actual = sanitize_timings(make_writer.get_string());
1475 assert_eq!(
1476 "fake time span1{x=42}: tracing_subscriber::fmt::fmt_subscriber::test: new\n\
1477 fake time span1{x=42}: tracing_subscriber::fmt::fmt_subscriber::test: enter\n\
1478 fake time span1{x=42}: tracing_subscriber::fmt::fmt_subscriber::test: exit\n\
1479 fake time span1{x=42}: tracing_subscriber::fmt::fmt_subscriber::test: close timing timing\n",
1480 actual.as_str()
1481 );
1482 }
1483
1484 #[test]
1485 fn make_writer_based_on_meta() {
1486 struct MakeByTarget {
1487 make_writer1: MockMakeWriter,
1488 make_writer2: MockMakeWriter,
1489 }
1490
1491 impl<'a> MakeWriter<'a> for MakeByTarget {
1492 type Writer = MockWriter;
1493
1494 fn make_writer(&'a self) -> Self::Writer {
1495 self.make_writer1.make_writer()
1496 }
1497
1498 fn make_writer_for(&'a self, meta: &Metadata<'_>) -> Self::Writer {
1499 if meta.target() == "writer2" {
1500 return self.make_writer2.make_writer();
1501 }
1502 self.make_writer()
1503 }
1504 }
1505
1506 let make_writer1 = MockMakeWriter::default();
1507 let make_writer2 = MockMakeWriter::default();
1508
1509 let make_writer = MakeByTarget {
1510 make_writer1: make_writer1.clone(),
1511 make_writer2: make_writer2.clone(),
1512 };
1513
1514 let subscriber = crate::fmt::Collector::builder()
1515 .with_writer(make_writer)
1516 .with_level(false)
1517 .with_target(false)
1518 .with_ansi(false)
1519 .with_timer(MockTime)
1520 .with_span_events(FmtSpan::CLOSE)
1521 .finish();
1522
1523 with_default(subscriber, || {
1524 let span1 = tracing::info_span!("writer1_span", x = 42);
1525 let _e = span1.enter();
1526 tracing::info!(target: "writer2", "hello writer2!");
1527 let span2 = tracing::info_span!(target: "writer2", "writer2_span");
1528 let _e = span2.enter();
1529 tracing::warn!(target: "writer1", "hello writer1!");
1530 });
1531
1532 let actual = sanitize_timings(make_writer1.get_string());
1533 assert_eq!(
1534 "fake time writer1_span{x=42}:writer2_span: hello writer1!\n\
1535 fake time writer1_span{x=42}: close timing timing\n",
1536 actual.as_str()
1537 );
1538 let actual = sanitize_timings(make_writer2.get_string());
1539 assert_eq!(
1540 "fake time writer1_span{x=42}: hello writer2!\n\
1541 fake time writer1_span{x=42}:writer2_span: close timing timing\n",
1542 actual.as_str()
1543 );
1544 }
1545
1546 #[cfg(feature = "ansi")]
1549 #[test]
1550 fn subscriber_no_color() {
1551 const NO_COLOR: &str = "NO_COLOR";
1552
1553 struct RestoreEnvVar(Result<String, env::VarError>);
1560 impl Drop for RestoreEnvVar {
1561 fn drop(&mut self) {
1562 match self.0 {
1563 Ok(ref var) => env::set_var(NO_COLOR, var),
1564 Err(_) => env::remove_var(NO_COLOR),
1565 }
1566 }
1567 }
1568
1569 let _saved_no_color = RestoreEnvVar(env::var(NO_COLOR));
1570
1571 let cases: Vec<(Option<&str>, bool)> = vec![
1572 (Some("0"), false), (Some("off"), false), (Some("1"), false),
1575 (Some(""), true), (None, true),
1577 ];
1578
1579 for (var, ansi) in cases {
1580 if let Some(value) = var {
1581 env::set_var(NO_COLOR, value);
1582 } else {
1583 env::remove_var(NO_COLOR);
1584 }
1585
1586 let subscriber: Subscriber<()> = fmt::Subscriber::default();
1587 assert_eq!(
1588 subscriber.is_ansi, ansi,
1589 "NO_COLOR={:?}; Subscriber::default().is_ansi should be {}",
1590 var, ansi
1591 );
1592
1593 let subscriber: Subscriber<()> = fmt::Subscriber::default().with_ansi(true);
1595 assert!(
1596 subscriber.is_ansi,
1597 "NO_COLOR={:?}; Subscriber::default().with_ansi(true).is_ansi should be true",
1598 var
1599 );
1600
1601 let mut subscriber: Subscriber<()> = fmt::Subscriber::default();
1603 subscriber.set_ansi(true);
1604 assert!(
1605 subscriber.is_ansi,
1606 "NO_COLOR={:?}; subscriber.set_ansi(true); subscriber.is_ansi should be true",
1607 var
1608 );
1609 }
1610
1611 }
1614
1615 #[test]
1617 fn modify_span_events() {
1618 let make_writer = MockMakeWriter::default();
1619
1620 let inner_subscriber = fmt::Subscriber::default()
1621 .with_writer(make_writer.clone())
1622 .with_level(false)
1623 .with_ansi(false)
1624 .with_timer(MockTime)
1625 .with_span_events(FmtSpan::ACTIVE);
1626
1627 let (reloadable_subscriber, reload_handle) =
1628 crate::reload::Subscriber::new(inner_subscriber);
1629 let reload = reloadable_subscriber.with_collector(Registry::default());
1630
1631 with_default(reload, || {
1632 {
1633 let span1 = tracing::info_span!("span1", x = 42);
1634 let _e = span1.enter();
1635 }
1636
1637 let _ = reload_handle.modify(|s| s.set_span_events(FmtSpan::NONE));
1638
1639 {
1641 let span2 = tracing::info_span!("span2", x = 100);
1642 let _e = span2.enter();
1643 }
1644
1645 {
1646 let span3 = tracing::info_span!("span3", x = 42);
1647 let _e = span3.enter();
1648
1649 let _ = reload_handle.modify(|s| s.set_span_events(FmtSpan::ACTIVE));
1652 }
1653 });
1654 let actual = sanitize_timings(make_writer.get_string());
1655 assert_eq!(
1656 "fake time span1{x=42}: tracing_subscriber::fmt::fmt_subscriber::test: enter\n\
1657 fake time span1{x=42}: tracing_subscriber::fmt::fmt_subscriber::test: exit\n\
1658 fake time span3{x=42}: tracing_subscriber::fmt::fmt_subscriber::test: exit\n",
1659 actual.as_str()
1660 );
1661 }
1662}