1#![doc(html_root_url = "https://docs.rs/tracing-serde-structured/0.1.3")]
175#![doc(
176 html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
177 html_favicon_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/favicon.ico",
178 issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
179)]
180#![cfg_attr(docsrs, feature(doc_cfg))]
181#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))]
182#![warn(
183 missing_debug_implementations,
184 rust_2018_idioms,
186 unreachable_pub,
187 bad_style,
188 dead_code,
189 improper_ctypes,
190 non_shorthand_field_patterns,
191 no_mangle_generic_items,
192 overflowing_literals,
193 path_statements,
194 patterns_in_fns_without_body,
195 unconditional_recursion,
197 unused,
198 unused_allocation,
199 unused_comparisons,
200 unused_parens,
201 while_true
202)]
203#![cfg_attr(not(feature = "std"), no_std)]
205
206use core::fmt;
207use core::fmt::Arguments;
208use core::hash::Hash;
209use core::num::NonZeroU64;
210use core::ops::Deref;
211
212use serde::{
213 ser::{SerializeMap, SerializeSeq, Serializer},
214 Deserialize, Serialize,
215};
216
217use tracing_core::{
218 event::Event,
219 field::{Field, FieldSet, Visit},
220 metadata::{Level, Metadata},
221 span::{Attributes, Id, Record},
222};
223
224#[cfg(feature = "postcard-schema")]
225impl<'a> postcard_schema::Schema for CowString<'a> {
226 const SCHEMA: &'static postcard_schema::schema::NamedType =
227 &postcard_schema::schema::NamedType {
228 name: "CowString",
229 ty: <&str>::SCHEMA.ty,
230 };
231}
232
233#[derive(Debug, Deserialize, Eq, PartialOrd, Ord)]
234#[serde(from = "&'a str")]
235pub enum CowString<'a> {
236 Borrowed(&'a str),
237 #[cfg(feature = "std")]
238 Owned(String),
239}
240
241impl<'a> Deref for CowString<'a> {
242 type Target = str;
243
244 fn deref(&self) -> &Self::Target {
245 self.as_str()
246 }
247}
248
249impl<'a> CowString<'a> {
250 pub fn as_str(&'a self) -> &'a str {
251 match self {
252 CowString::Borrowed(b) => b,
253 #[cfg(feature = "std")]
254 CowString::Owned(o) => o.as_str(),
255 }
256 }
257}
258
259#[cfg(feature = "std")]
260impl<'a> CowString<'a> {
261 pub fn to_owned(&'a self) -> CowString<'static> {
262 CowString::Owned(self.as_str().to_string())
263 }
264}
265
266impl<'a> Hash for CowString<'a> {
267 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
268 self.as_str().hash(state)
269 }
270}
271
272impl<'a> hash32::Hash for CowString<'a> {
273 fn hash<H>(&self, state: &mut H)
274 where
275 H: hash32::Hasher,
276 {
277 <str as hash32::Hash>::hash(self.as_str(), state)
278 }
279}
280
281impl<'a> PartialEq for CowString<'a> {
282 fn eq(&self, other: &Self) -> bool {
283 self.as_str().eq(other.as_str())
284 }
285}
286
287impl<'a> From<&'a str> for CowString<'a> {
288 fn from(other: &'a str) -> Self {
289 Self::Borrowed(other)
290 }
291}
292
293impl<'a> Serialize for CowString<'a> {
294 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
295 where
296 S: Serializer,
297 {
298 self.as_str().serialize(serializer)
299 }
300}
301
302#[cfg(not(feature = "std"))]
303type TracingVec<T> = heapless::Vec<T, 32>;
304
305#[cfg(not(feature = "std"))]
306type TracingMap<K, V> = heapless::FnvIndexMap<K, V, 32>;
307
308#[cfg(feature = "std")]
309type TracingVec<T> = std::vec::Vec<T>;
310
311#[cfg(feature = "std")]
312type TracingMap<K, V> = std::collections::BTreeMap<K, V>;
313
314#[derive(Debug, Deserialize)]
315#[serde(from = "TracingVec<CowString<'a>>")]
316pub enum SerializeFieldSet<'a> {
317 Ser(&'a FieldSet),
318 #[serde(borrow)]
319 De(TracingVec<CowString<'a>>),
320}
321
322impl<'a> Serialize for SerializeFieldSet<'a> {
323 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
324 where
325 S: Serializer,
326 {
327 match self {
328 SerializeFieldSet::Ser(sfs) => {
329 let mut seq = serializer.serialize_seq(Some(sfs.len()))?;
330 for element in sfs.iter() {
331 seq.serialize_element(element.name())?;
332 }
333 seq.end()
334 }
335 SerializeFieldSet::De(dfs) => dfs.serialize(serializer),
336 }
337 }
338}
339
340impl<'a> From<TracingVec<CowString<'a>>> for SerializeFieldSet<'a> {
341 fn from(other: TracingVec<CowString<'a>>) -> Self {
342 SerializeFieldSet::De(other)
343 }
344}
345
346#[cfg(feature = "postcard-schema")]
347impl<'a> postcard_schema::Schema for SerializeFieldSet<'a> {
348 const SCHEMA: &'static postcard_schema::schema::NamedType =
349 &postcard_schema::schema::NamedType {
350 name: "SerializeFieldSet",
351 ty: &postcard_schema::schema::DataModelType::Seq(CowString::SCHEMA),
352 };
353}
354
355#[repr(usize)]
356#[cfg_attr(
357 feature = "postcard-schema",
358 derive(postcard_schema::Schema)
359)]
360#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
361#[serde(rename_all = "UPPERCASE")]
362pub enum SerializeLevel {
363 Trace = 0,
367 Debug = 1,
371 Info = 2,
375 Warn = 3,
379 Error = 4,
383}
384
385#[derive(Debug, Serialize, Deserialize, Clone)]
386#[cfg_attr(
387 feature = "postcard-schema",
388 derive(postcard_schema::Schema)
389)]
390pub struct SerializeId {
391 pub id: NonZeroU64,
392}
393
394#[derive(Debug, Serialize, Deserialize)]
395#[cfg_attr(
396 feature = "postcard-schema",
397 derive(postcard_schema::Schema)
398)]
399pub struct SerializeMetadata<'a> {
400 #[serde(borrow)]
401 pub name: CowString<'a>,
402 pub target: CowString<'a>,
403 pub level: SerializeLevel,
404 pub module_path: Option<CowString<'a>>,
405 pub file: Option<CowString<'a>>,
406 pub line: Option<u32>,
407 pub fields: SerializeFieldSet<'a>,
408 pub is_span: bool,
409 pub is_event: bool,
410}
411
412#[derive(Debug, Serialize, Deserialize)]
414#[cfg_attr(
415 feature = "postcard-schema",
416 derive(postcard_schema::Schema)
417)]
418pub struct SerializeEvent<'a> {
419 #[serde(borrow)]
420 pub fields: SerializeRecordFields<'a>,
421 pub metadata: SerializeMetadata<'a>,
422 pub parent: Option<SerializeId>,
423}
424
425#[derive(Debug, Serialize, Deserialize)]
427#[cfg_attr(
428 feature = "postcard-schema",
429 derive(postcard_schema::Schema)
430)]
431pub struct SerializeAttributes<'a> {
432 #[serde(borrow)]
433 pub metadata: SerializeMetadata<'a>,
434 pub parent: Option<SerializeId>,
435 pub is_root: bool,
436}
437
438type RecordMap<'a> = TracingMap<CowString<'a>, SerializeValue<'a>>;
439
440#[derive(Debug, Deserialize)]
442#[serde(from = "RecordMap<'a>")]
443pub enum SerializeRecord<'a> {
444 #[serde(borrow)]
445 Ser(&'a Record<'a>),
446 De(RecordMap<'a>),
447}
448
449impl<'a> Serialize for SerializeRecord<'a> {
450 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
451 where
452 S: Serializer,
453 {
454 match self {
455 SerializeRecord::Ser(serf) => {
456 let items = serf.len();
457
458 let serializer = serializer.serialize_map(Some(items))?;
459 let mut ssv = SerdeMapVisitor::new(serializer);
460 serf.record(&mut ssv);
461 ssv.finish()
462 }
463 SerializeRecord::De(derf) => derf.serialize(serializer),
464 }
465 }
466}
467
468impl<'a> From<RecordMap<'a>> for SerializeRecord<'a> {
469 fn from(other: RecordMap<'a>) -> Self {
470 Self::De(other)
471 }
472}
473
474#[cfg(feature = "postcard-schema")]
475impl<'a> postcard_schema::Schema for SerializeRecord<'a> {
476 const SCHEMA: &'static postcard_schema::schema::NamedType =
477 &postcard_schema::schema::NamedType {
478 name: "SerializeRecord",
479 ty: &postcard_schema::schema::DataModelType::Map {
480 key: CowString::SCHEMA,
481 val: SerializeValue::SCHEMA,
482 },
483 };
484}
485
486#[derive(Debug, Serialize, Deserialize)]
487#[non_exhaustive]
488#[cfg_attr(
489 feature = "postcard-schema",
490 derive(postcard_schema::Schema)
491)]
492pub enum SerializeValue<'a> {
493 #[serde(borrow)]
494 Debug(DebugRecord<'a>),
495 Str(CowString<'a>),
496 F64(f64),
497 I64(i64),
498 U64(u64),
499 Bool(bool),
500}
501
502#[derive(Debug, Deserialize)]
503#[serde(from = "CowString<'a>")]
504pub enum DebugRecord<'a> {
505 #[serde(borrow)]
506 Ser(&'a Arguments<'a>),
507 De(CowString<'a>),
508}
509
510impl<'a> From<CowString<'a>> for DebugRecord<'a> {
511 fn from(other: CowString<'a>) -> Self {
512 Self::De(other)
513 }
514}
515
516impl<'a> Serialize for DebugRecord<'a> {
517 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
518 where
519 S: Serializer,
520 {
521 match self {
522 DebugRecord::Ser(args) => args.serialize(serializer),
523 DebugRecord::De(msg) => msg.serialize(serializer),
524 }
525 }
526}
527
528#[cfg(feature = "postcard-schema")]
529impl<'a> postcard_schema::Schema for DebugRecord<'a> {
530 const SCHEMA: &'static postcard_schema::schema::NamedType =
531 &postcard_schema::schema::NamedType {
532 name: "DebugRecord",
533 ty: CowString::SCHEMA.ty,
534 };
535}
536
537#[derive(Debug, Deserialize)]
538#[serde(from = "RecordMap<'a>")]
539pub enum SerializeRecordFields<'a> {
540 #[serde(borrow)]
541 Ser(&'a Event<'a>),
542 De(RecordMap<'a>),
543}
544
545impl<'a> From<RecordMap<'a>> for SerializeRecordFields<'a> {
546 fn from(other: RecordMap<'a>) -> Self {
547 Self::De(other)
548 }
549}
550
551impl<'a> Serialize for SerializeRecordFields<'a> {
552 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
553 where
554 S: Serializer,
555 {
556 match self {
557 SerializeRecordFields::Ser(serf) => {
558 let items = serf.fields().count();
559
560 let serializer = serializer.serialize_map(Some(items))?;
561 let mut ssv = SerdeMapVisitor::new(serializer);
562 serf.record(&mut ssv);
563 ssv.finish()
564 }
565 SerializeRecordFields::De(derf) => derf.serialize(serializer),
566 }
567 }
568}
569
570#[cfg(feature = "postcard-schema")]
571impl<'a> postcard_schema::Schema for SerializeRecordFields<'a> {
572 const SCHEMA: &'static postcard_schema::schema::NamedType =
573 &postcard_schema::schema::NamedType {
574 name: "SerializeRecordFields",
575 ty: &postcard_schema::schema::DataModelType::Map {
576 key: CowString::SCHEMA,
577 val: SerializeValue::SCHEMA,
578 },
579 };
580}
581
582#[derive(Debug)]
584pub struct SerdeMapVisitor<S: SerializeMap> {
585 serializer: S,
586 state: Result<(), S::Error>,
587}
588
589impl<S> SerdeMapVisitor<S>
590where
591 S: SerializeMap,
592{
593 pub fn new(serializer: S) -> Self {
595 Self {
596 serializer,
597 state: Ok(()),
598 }
599 }
600
601 pub fn finish(self) -> Result<S::Ok, S::Error> {
605 self.state?;
606 self.serializer.end()
607 }
608
609 pub fn take_serializer(self) -> Result<S, S::Error> {
613 self.state?;
614 Ok(self.serializer)
615 }
616}
617
618impl<S> Visit for SerdeMapVisitor<S>
619where
620 S: SerializeMap,
621{
622 #[cfg(all(tracing_unstable, feature = "valuable"))]
623 #[cfg_attr(docsrs, doc(cfg(all(tracing_unstable, feature = "valuable"))))]
624 fn record_value(&mut self, field: &Field, value: valuable_crate::Value<'_>) {
625 if self.state.is_ok() {
626 self.state = self
627 .serializer
628 .serialize_entry(field.name(), &valuable_serde::Serializable::new(value));
629 }
630 }
631
632 fn record_bool(&mut self, field: &Field, value: bool) {
633 if self.state.is_ok() {
636 self.state = self
637 .serializer
638 .serialize_entry(field.name(), &SerializeValue::Bool(value))
639 }
640 }
641
642 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
643 if self.state.is_ok() {
644 self.state = self.serializer.serialize_entry(
645 field.name(),
646 &SerializeValue::Debug(DebugRecord::Ser(&format_args!("{:?}", value))),
647 )
648 }
649 }
650
651 fn record_u64(&mut self, field: &Field, value: u64) {
652 if self.state.is_ok() {
653 self.state = self
654 .serializer
655 .serialize_entry(field.name(), &SerializeValue::U64(value))
656 }
657 }
658
659 fn record_i64(&mut self, field: &Field, value: i64) {
660 if self.state.is_ok() {
661 self.state = self
662 .serializer
663 .serialize_entry(field.name(), &SerializeValue::I64(value))
664 }
665 }
666
667 fn record_f64(&mut self, field: &Field, value: f64) {
668 if self.state.is_ok() {
669 self.state = self
670 .serializer
671 .serialize_entry(field.name(), &SerializeValue::F64(value))
672 }
673 }
674
675 fn record_str(&mut self, field: &Field, value: &str) {
676 if self.state.is_ok() {
677 self.state = self
678 .serializer
679 .serialize_entry(field.name(), &SerializeValue::Str(value.into()))
680 }
681 }
682}
683
684pub trait AsSerde<'a>: self::sealed::Sealed {
685 type Serializable: serde::Serialize + 'a;
686
687 fn as_serde(&'a self) -> Self::Serializable;
689}
690
691impl<'a> AsSerde<'a> for tracing_core::Metadata<'a> {
692 type Serializable = SerializeMetadata<'a>;
693
694 fn as_serde(&'a self) -> Self::Serializable {
695 SerializeMetadata {
696 name: self.name().into(),
697 target: self.target().into(),
698 level: self.level().as_serde(),
699 module_path: self.module_path().map(Into::into),
700 file: self.file().map(Into::into),
701 line: self.line(),
702 fields: SerializeFieldSet::Ser(self.fields()),
703 is_span: self.is_span(),
704 is_event: self.is_event(),
705 }
706 }
707}
708
709unsafe impl Send for SerializeFieldSet<'static> {}
712
713#[cfg(feature = "std")]
714impl<'a> SerializeFieldSet<'a> {
715 pub fn to_owned(&self) -> SerializeFieldSet<'static> {
716 match self {
717 SerializeFieldSet::Ser(sfs) => SerializeFieldSet::De(
718 sfs.iter()
719 .map(|i| CowString::from(i.name()).to_owned())
720 .collect(),
721 ),
722 SerializeFieldSet::De(dfs) => {
723 SerializeFieldSet::De(dfs.iter().map(CowString::to_owned).collect())
724 }
725 }
726 }
727}
728
729unsafe impl Send for SerializeMetadata<'static> {}
732
733#[cfg(feature = "std")]
734impl<'a> SerializeMetadata<'a> {
735 pub fn to_owned(&self) -> SerializeMetadata<'static> {
736 SerializeMetadata {
737 name: self.name.to_owned(),
738 target: self.target.to_owned(),
739 level: self.level,
740 module_path: self.module_path.as_ref().map(CowString::to_owned),
741 file: self.file.as_ref().map(CowString::to_owned),
742 line: self.line,
743 fields: self.fields.to_owned(),
744 is_span: self.is_span,
745 is_event: self.is_event,
746 }
747 }
748}
749
750impl<'a> AsSerde<'a> for tracing_core::Event<'a> {
751 type Serializable = SerializeEvent<'a>;
752
753 fn as_serde(&'a self) -> Self::Serializable {
754 SerializeEvent {
755 fields: SerializeRecordFields::Ser(self),
756 metadata: self.metadata().as_serde(),
757 parent: self.parent().map(|p| p.as_serde()),
758 }
759 }
760}
761
762unsafe impl Send for DebugRecord<'static> {}
765
766#[cfg(feature = "std")]
767impl<'a> DebugRecord<'a> {
768 pub fn to_owned(&self) -> DebugRecord<'static> {
769 match self {
770 DebugRecord::Ser(args) => DebugRecord::De(CowString::Owned(args.to_string())),
771 DebugRecord::De(d) => DebugRecord::De(d.to_owned()),
772 }
773 }
774}
775
776unsafe impl Send for SerializeValue<'static> {}
779
780#[cfg(feature = "std")]
781impl<'a> SerializeValue<'a> {
782 pub fn to_owned(&self) -> SerializeValue<'static> {
783 match self {
784 SerializeValue::Debug(dr) => SerializeValue::Debug(dr.to_owned()),
785 SerializeValue::Str(s) => SerializeValue::Str(s.to_owned()),
786 SerializeValue::F64(x) => SerializeValue::F64(*x),
787 SerializeValue::I64(x) => SerializeValue::I64(*x),
788 SerializeValue::U64(x) => SerializeValue::U64(*x),
789 SerializeValue::Bool(x) => SerializeValue::Bool(*x),
790 }
791 }
792}
793
794#[cfg(feature = "std")]
795struct HashVisit(std::collections::BTreeMap<CowString<'static>, SerializeValue<'static>>);
796
797#[cfg(feature = "std")]
798impl Visit for HashVisit {
799 fn record_bool(&mut self, field: &Field, value: bool) {
800 self.0.insert(
801 CowString::Owned(field.name().to_string()),
802 SerializeValue::Bool(value),
803 );
804 }
805
806 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
807 self.0.insert(
808 CowString::Owned(field.name().to_string()),
809 SerializeValue::Debug(DebugRecord::De(CowString::Owned(format!("{:?}", value)))),
810 );
811 }
812
813 fn record_u64(&mut self, field: &Field, value: u64) {
814 self.0.insert(
815 CowString::Owned(field.name().to_string()),
816 SerializeValue::U64(value),
817 );
818 }
819
820 fn record_i64(&mut self, field: &Field, value: i64) {
821 self.0.insert(
822 CowString::Owned(field.name().to_string()),
823 SerializeValue::I64(value),
824 );
825 }
826
827 fn record_f64(&mut self, field: &Field, value: f64) {
828 self.0.insert(
829 CowString::Owned(field.name().to_string()),
830 SerializeValue::F64(value),
831 );
832 }
833
834 fn record_str(&mut self, field: &Field, value: &str) {
835 self.0.insert(
836 CowString::Owned(field.name().to_string()),
837 SerializeValue::Str(CowString::Owned(value.to_string())),
838 );
839 }
840}
841
842unsafe impl Send for SerializeRecordFields<'static> {}
845
846#[cfg(feature = "std")]
847impl<'a> SerializeRecordFields<'a> {
848 pub fn to_owned(&self) -> SerializeRecordFields<'static> {
849 match self {
850 SerializeRecordFields::Ser(e) => {
851 let mut hv = HashVisit(std::collections::BTreeMap::new());
852 e.record(&mut hv);
853 SerializeRecordFields::De(hv.0)
854 }
855 SerializeRecordFields::De(dsrf) => SerializeRecordFields::De(
856 dsrf.iter()
857 .map(|(k, v)| (k.to_owned(), v.to_owned()))
858 .collect(),
859 ),
860 }
861 }
862}
863
864unsafe impl Send for SerializeEvent<'static> {}
867
868#[cfg(feature = "std")]
869impl<'a> SerializeEvent<'a> {
870 pub fn to_owned(&self) -> SerializeEvent<'static> {
871 SerializeEvent {
872 fields: self.fields.to_owned(),
873 metadata: self.metadata.to_owned(),
874 parent: self.parent.clone(),
875 }
876 }
877}
878
879impl<'a> AsSerde<'a> for tracing_core::span::Attributes<'a> {
880 type Serializable = SerializeAttributes<'a>;
881
882 fn as_serde(&'a self) -> Self::Serializable {
883 SerializeAttributes {
884 metadata: self.metadata().as_serde(),
885 parent: self.parent().map(|p| p.as_serde()),
886 is_root: self.is_root(),
887 }
888 }
889}
890
891unsafe impl Send for SerializeAttributes<'static> {}
894
895#[cfg(feature = "std")]
896impl<'a> SerializeAttributes<'a> {
897 pub fn to_owned(&self) -> SerializeAttributes<'static> {
898 SerializeAttributes {
899 metadata: self.metadata.to_owned(),
900 parent: self.parent.clone(),
901 is_root: self.is_root,
902 }
903 }
904}
905
906impl<'a> AsSerde<'a> for tracing_core::span::Id {
907 type Serializable = SerializeId;
908
909 fn as_serde(&'a self) -> Self::Serializable {
910 SerializeId {
911 id: self.into_non_zero_u64(),
912 }
913 }
914}
915
916#[cfg(feature = "std")]
917impl SerializeId {
918 pub fn to_owned(&self) -> Self {
919 self.clone()
920 }
921}
922
923impl<'a> AsSerde<'a> for tracing_core::span::Record<'a> {
924 type Serializable = SerializeRecord<'a>;
925
926 fn as_serde(&'a self) -> Self::Serializable {
927 SerializeRecord::Ser(self)
928 }
929}
930
931unsafe impl Send for SerializeRecord<'static> {}
934
935#[cfg(feature = "std")]
936impl<'a> SerializeRecord<'a> {
937 pub fn to_owned(&self) -> SerializeRecord<'static> {
938 match self {
939 SerializeRecord::Ser(s) => {
940 let mut hv = HashVisit(std::collections::BTreeMap::new());
941 s.record(&mut hv);
942 SerializeRecord::De(hv.0)
943 }
944 SerializeRecord::De(d) => SerializeRecord::De(
945 d.iter()
946 .map(|(k, v)| (k.to_owned(), v.to_owned()))
947 .collect(),
948 ),
949 }
950 }
951}
952
953impl<'a> AsSerde<'a> for Level {
954 type Serializable = SerializeLevel;
955
956 fn as_serde(&'a self) -> Self::Serializable {
957 match *self {
958 Level::ERROR => SerializeLevel::Error,
959 Level::WARN => SerializeLevel::Warn,
960 Level::INFO => SerializeLevel::Info,
961 Level::DEBUG => SerializeLevel::Debug,
962 Level::TRACE => SerializeLevel::Trace,
963 }
964 }
965}
966
967#[cfg(feature = "std")]
968impl SerializeLevel {
969 pub fn to_owned(&self) -> Self {
970 *self
971 }
972}
973
974impl<'a> self::sealed::Sealed for Event<'a> {}
975
976impl<'a> self::sealed::Sealed for Attributes<'a> {}
977
978impl self::sealed::Sealed for Id {}
979
980impl self::sealed::Sealed for Level {}
981
982impl<'a> self::sealed::Sealed for Record<'a> {}
983
984impl<'a> self::sealed::Sealed for Metadata<'a> {}
985
986mod sealed {
987 pub trait Sealed {}
988}