test_span/
record.rs

1use ::tracing::{
2    field::{Field, Visit},
3    span,
4};
5use serde::{Deserialize, Serialize};
6
7use crate::attribute::OwnedMetadata;
8
9type FieldName = String;
10
11#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
12#[serde(untagged)]
13pub enum RecordValue {
14    Error(String),
15    Value(serde_json::Value),
16    Debug(String),
17}
18
19#[derive(Default, Clone, Debug)]
20pub(crate) struct RecordEverything(Vec<Record>);
21
22impl RecordEverything {
23    pub fn contents(&self) -> impl Iterator<Item = &Record> {
24        self.0.iter()
25    }
26}
27
28impl Visit for RecordEverything {
29    /// Visit a double-precision floating point value.
30    fn record_f64(&mut self, field: &Field, value: f64) {
31        self.0
32            .push((field.name().to_string(), RecordValue::Value(value.into())));
33    }
34
35    /// Visit a signed 64-bit integer value.
36    fn record_i64(&mut self, field: &Field, value: i64) {
37        self.0
38            .push((field.name().to_string(), RecordValue::Value(value.into())));
39    }
40
41    /// Visit an unsigned 64-bit integer value.
42    fn record_u64(&mut self, field: &Field, value: u64) {
43        self.0
44            .push((field.name().to_string(), RecordValue::Value(value.into())));
45    }
46
47    /// Visit a boolean value.
48    fn record_bool(&mut self, field: &Field, value: bool) {
49        self.0
50            .push((field.name().to_string(), RecordValue::Value(value.into())));
51    }
52
53    /// Visit a string value.
54    fn record_str(&mut self, field: &Field, value: &str) {
55        self.0
56            .push((field.name().to_string(), RecordValue::Value(value.into())));
57    }
58
59    /// Records a type implementing `Error`.
60    ///
61    /// <div class="example-wrap" style="display:inline-block">
62    /// <pre class="ignore" style="white-space:normal;font:inherit;">
63    /// <strong>Note</strong>: This is only enabled when the Rust standard library is
64    /// present.
65    /// </pre>
66    #[cfg(feature = "std")]
67    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
68    fn record_error(&mut self, field: &Field, value: &(dyn std::error::Error + 'static)) {
69        self.0.push((
70            field.name().to_string(),
71            RecordValue::Error(&format_args!("{}", value).into()),
72        ));
73    }
74
75    fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) {
76        self.0.push((
77            field.name().to_string(),
78            RecordValue::Debug(format!("{:?}", value)),
79        ));
80    }
81}
82
83pub type Record = (FieldName, RecordValue);
84
85#[derive(Clone, Debug, Default)]
86pub struct Recorder {
87    metadata: Option<OwnedMetadata>,
88    visitor: RecordEverything,
89}
90
91impl Recorder {
92    pub fn attributes(&mut self, span_id: tracing::Id, attributes: &span::Attributes<'_>) {
93        let mut owned_metadata: OwnedMetadata = attributes.metadata().into();
94        owned_metadata.span_id = Some(span_id.into_u64());
95        self.metadata = Some(owned_metadata);
96        attributes.record(&mut self.visitor)
97    }
98
99    pub fn metadata(&self) -> Option<&OwnedMetadata> {
100        self.metadata.as_ref()
101    }
102
103    pub fn record(&mut self, record: &span::Record<'_>) {
104        record.record(&mut self.visitor)
105    }
106
107    pub fn contents(&self, filter: &crate::Filter) -> RecordWithMetadata {
108        let mut r = RecordWithMetadata::new(self.metadata.clone().unwrap());
109
110        if filter.is_enabled(&r.metadata) {
111            r.append(self.visitor.0.clone());
112        }
113        r
114    }
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
118pub struct RecordWithMetadata {
119    entries: Vec<Record>,
120    metadata: OwnedMetadata,
121}
122
123impl RecordWithMetadata {
124    pub fn new(metadata: OwnedMetadata) -> Self {
125        Self {
126            entries: Default::default(),
127            metadata,
128        }
129    }
130
131    pub fn metadata(&self) -> OwnedMetadata {
132        self.metadata.clone()
133    }
134
135    pub fn for_root() -> Self {
136        Self {
137            entries: Vec::new(),
138            metadata: OwnedMetadata {
139                name: "root".to_string(),
140                ..Default::default()
141            },
142        }
143    }
144
145    pub fn entries(&self) -> impl Iterator<Item = &Record> {
146        self.entries.iter()
147    }
148
149    pub fn push(&mut self, entry: Record) {
150        self.entries.push(entry)
151    }
152
153    pub fn append(&mut self, mut entries: Vec<Record>) {
154        self.entries.append(&mut entries)
155    }
156}