opentelemetry/logs/
record.rs

1use crate::{Key, StringValue};
2
3use crate::{SpanId, TraceFlags, TraceId};
4
5use std::{borrow::Cow, collections::HashMap, time::SystemTime};
6
7/// SDK implemented trait for managing log records
8pub trait LogRecord {
9    /// Sets the `event_name` of a record
10    fn set_event_name(&mut self, name: &'static str);
11
12    /// Sets the `target` of a record.
13    /// Currently, both `opentelemetry-appender-tracing` and `opentelemetry-appender-log` create a single logger
14    /// with a scope that doesn't accurately reflect the component emitting the logs.
15    /// Exporters MAY use this field to override the `instrumentation_scope.name`.
16    fn set_target<T>(&mut self, _target: T)
17    where
18        T: Into<Cow<'static, str>>;
19
20    /// Sets the time when the event occurred measured by the origin clock, i.e. the time at the source.
21    fn set_timestamp(&mut self, timestamp: SystemTime);
22
23    /// Sets the observed event timestamp.
24    fn set_observed_timestamp(&mut self, timestamp: SystemTime);
25
26    /// Sets severity as text.
27    fn set_severity_text(&mut self, text: &'static str);
28
29    /// Sets severity as a numeric value.
30    fn set_severity_number(&mut self, number: Severity);
31
32    /// Sets the message body of the log.
33    fn set_body(&mut self, body: AnyValue);
34
35    /// Adds multiple attributes.
36    fn add_attributes<I, K, V>(&mut self, attributes: I)
37    where
38        I: IntoIterator<Item = (K, V)>,
39        K: Into<Key>,
40        V: Into<AnyValue>;
41
42    /// Adds a single attribute.
43    fn add_attribute<K, V>(&mut self, key: K, value: V)
44    where
45        K: Into<Key>,
46        V: Into<AnyValue>;
47
48    /// Sets the trace context of the log.
49    fn set_trace_context(
50        &mut self,
51        trace_id: TraceId,
52        span_id: SpanId,
53        trace_flags: Option<TraceFlags>,
54    ) {
55        let _ = trace_id;
56        let _ = span_id;
57        let _ = trace_flags;
58    }
59}
60
61/// Value types for representing arbitrary values in a log record.
62/// Note: The `tracing` and `log` crates only support basic types that can be
63/// converted to these core variants: `i64`, `f64`, `StringValue`, and `bool`.
64/// Any complex and custom types are supported through their Debug implementation,
65/// and converted to String. More complex types (`Bytes`, `ListAny`, and `Map`) are
66/// included here to meet specification requirements and are available to support
67/// custom appenders that may be implemented for other logging crates.
68/// These types allow for handling dynamic data structures, so keep in mind the
69/// potential performance overhead of using boxed vectors and maps in appenders.
70#[derive(Debug, Clone, PartialEq)]
71#[non_exhaustive]
72pub enum AnyValue {
73    /// An integer value
74    Int(i64),
75    /// A double value
76    Double(f64),
77    /// A string value
78    String(StringValue),
79    /// A boolean value
80    Boolean(bool),
81    /// A byte array
82    Bytes(Box<Vec<u8>>),
83    /// An array of `Any` values
84    ListAny(Box<Vec<AnyValue>>),
85    /// A map of string keys to `Any` values, arbitrarily nested.
86    Map(Box<HashMap<Key, AnyValue>>),
87}
88
89macro_rules! impl_trivial_from {
90    ($t:ty, $variant:path) => {
91        impl From<$t> for AnyValue {
92            fn from(val: $t) -> AnyValue {
93                $variant(val.into())
94            }
95        }
96    };
97}
98
99impl_trivial_from!(i8, AnyValue::Int);
100impl_trivial_from!(i16, AnyValue::Int);
101impl_trivial_from!(i32, AnyValue::Int);
102impl_trivial_from!(i64, AnyValue::Int);
103
104impl_trivial_from!(u8, AnyValue::Int);
105impl_trivial_from!(u16, AnyValue::Int);
106impl_trivial_from!(u32, AnyValue::Int);
107
108impl_trivial_from!(f64, AnyValue::Double);
109impl_trivial_from!(f32, AnyValue::Double);
110
111impl_trivial_from!(String, AnyValue::String);
112impl_trivial_from!(Cow<'static, str>, AnyValue::String);
113impl_trivial_from!(&'static str, AnyValue::String);
114impl_trivial_from!(StringValue, AnyValue::String);
115
116impl_trivial_from!(bool, AnyValue::Boolean);
117
118impl<T: Into<AnyValue>> FromIterator<T> for AnyValue {
119    /// Creates an [`AnyValue::ListAny`] value from a sequence of `Into<AnyValue>` values.
120    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
121        AnyValue::ListAny(Box::new(iter.into_iter().map(Into::into).collect()))
122    }
123}
124
125impl<K: Into<Key>, V: Into<AnyValue>> FromIterator<(K, V)> for AnyValue {
126    /// Creates an [`AnyValue::Map`] value from a sequence of key-value pairs
127    /// that can be converted into a `Key` and `AnyValue` respectively.
128    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
129        AnyValue::Map(Box::new(HashMap::from_iter(
130            iter.into_iter().map(|(k, v)| (k.into(), v.into())),
131        )))
132    }
133}
134
135/// A normalized severity value.
136#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)]
137pub enum Severity {
138    /// TRACE
139    Trace = 1,
140    /// TRACE2
141    Trace2 = 2,
142    /// TRACE3
143    Trace3 = 3,
144    /// TRACE4
145    Trace4 = 4,
146    /// DEBUG
147    Debug = 5,
148    /// DEBUG2
149    Debug2 = 6,
150    /// DEBUG3
151    Debug3 = 7,
152    /// DEBUG4
153    Debug4 = 8,
154    /// INFO
155    Info = 9,
156    /// INFO2
157    Info2 = 10,
158    /// INFO3
159    Info3 = 11,
160    /// INFO4
161    Info4 = 12,
162    /// WARN
163    Warn = 13,
164    /// WARN2
165    Warn2 = 14,
166    /// WARN3
167    Warn3 = 15,
168    /// WARN4
169    Warn4 = 16,
170    /// ERROR
171    Error = 17,
172    /// ERROR2
173    Error2 = 18,
174    /// ERROR3
175    Error3 = 19,
176    /// ERROR4
177    Error4 = 20,
178    /// FATAL
179    Fatal = 21,
180    /// FATAL2
181    Fatal2 = 22,
182    /// FATAL3
183    Fatal3 = 23,
184    /// FATAL4
185    Fatal4 = 24,
186}
187
188impl Severity {
189    /// Return the string representing the short name for the `Severity`
190    /// value as specified by the OpenTelemetry logs data model.
191    pub const fn name(&self) -> &'static str {
192        match &self {
193            Severity::Trace => "TRACE",
194            Severity::Trace2 => "TRACE2",
195            Severity::Trace3 => "TRACE3",
196            Severity::Trace4 => "TRACE4",
197
198            Severity::Debug => "DEBUG",
199            Severity::Debug2 => "DEBUG2",
200            Severity::Debug3 => "DEBUG3",
201            Severity::Debug4 => "DEBUG4",
202
203            Severity::Info => "INFO",
204            Severity::Info2 => "INFO2",
205            Severity::Info3 => "INFO3",
206            Severity::Info4 => "INFO4",
207
208            Severity::Warn => "WARN",
209            Severity::Warn2 => "WARN2",
210            Severity::Warn3 => "WARN3",
211            Severity::Warn4 => "WARN4",
212
213            Severity::Error => "ERROR",
214            Severity::Error2 => "ERROR2",
215            Severity::Error3 => "ERROR3",
216            Severity::Error4 => "ERROR4",
217
218            Severity::Fatal => "FATAL",
219            Severity::Fatal2 => "FATAL2",
220            Severity::Fatal3 => "FATAL3",
221            Severity::Fatal4 => "FATAL4",
222        }
223    }
224}