Skip to main content

opentelemetry_sdk/logs/
export.rs

1//! Log exporters
2use crate::error::OTelSdkResult;
3use crate::logs::SdkLogRecord;
4use crate::Resource;
5use opentelemetry::logs::Severity;
6use opentelemetry::InstrumentationScope;
7use std::fmt::Debug;
8use std::time;
9
10/// A batch of log records to be exported by a `LogExporter`.
11///
12/// The `LogBatch` struct holds a collection of log records along with their associated
13/// instrumentation scopes. This structure is used to group log records together for efficient
14/// export operations.
15///
16/// # Type Parameters
17/// - `'a`: The lifetime of the references to the log records and instrumentation scopes.
18///
19#[derive(Debug)]
20pub struct LogBatch<'a> {
21    data: LogBatchData<'a>,
22}
23
24/// The `LogBatchData` enum represents the data field of a `LogBatch`.
25/// It can either be:
26/// - A shared reference to a slice of boxed tuples, where each tuple consists of an owned `LogRecord` and an owned `InstrumentationScope`.
27/// - Or it can be a shared reference to a slice of tuples, where each tuple consists of a reference to a `LogRecord` and a reference to an `InstrumentationScope`.
28#[derive(Debug)]
29enum LogBatchData<'a> {
30    SliceOfOwnedData(&'a [Box<(SdkLogRecord, InstrumentationScope)>]), // Used by BatchProcessor which clones the LogRecords for its own use.
31    SliceOfBorrowedData(&'a [(&'a SdkLogRecord, &'a InstrumentationScope)]),
32}
33
34impl<'a> LogBatch<'a> {
35    /// Creates a new instance of `LogBatch`.
36    ///
37    /// # Arguments
38    ///
39    /// * `data` - A slice of tuples, where each tuple consists of a reference to a `LogRecord`
40    ///   and a reference to an `InstrumentationScope`. These tuples represent the log records
41    ///   and their associated instrumentation scopes to be exported.
42    ///
43    /// # Returns
44    ///
45    /// A `LogBatch` instance containing the provided log records and instrumentation scopes.
46    ///
47    /// Note - this is not a public function, and should not be used directly. This would be
48    /// made private in the future.
49    pub fn new(data: &'a [(&'a SdkLogRecord, &'a InstrumentationScope)]) -> LogBatch<'a> {
50        LogBatch {
51            data: LogBatchData::SliceOfBorrowedData(data),
52        }
53    }
54
55    pub(crate) fn new_with_owned_data(
56        data: &'a [Box<(SdkLogRecord, InstrumentationScope)>],
57    ) -> LogBatch<'a> {
58        LogBatch {
59            data: LogBatchData::SliceOfOwnedData(data),
60        }
61    }
62}
63
64impl LogBatch<'_> {
65    /// Returns the number of log records in the batch.
66    #[cfg(test)]
67    pub(crate) fn len(&self) -> usize {
68        match &self.data {
69            LogBatchData::SliceOfOwnedData(data) => data.len(),
70            LogBatchData::SliceOfBorrowedData(data) => data.len(),
71        }
72    }
73
74    /// Returns an iterator over the log records and instrumentation scopes in the batch.
75    ///
76    /// Each item yielded by the iterator is a tuple containing references to a `LogRecord`
77    /// and an `InstrumentationScope`.
78    ///
79    /// # Returns
80    ///
81    /// An iterator that yields references to the `LogRecord` and `InstrumentationScope` in the batch.
82    ///
83    pub fn iter(&self) -> impl Iterator<Item = (&SdkLogRecord, &InstrumentationScope)> {
84        LogBatchDataIter {
85            data: &self.data,
86            index: 0,
87        }
88    }
89}
90
91struct LogBatchDataIter<'a> {
92    data: &'a LogBatchData<'a>,
93    index: usize,
94}
95
96impl<'a> Iterator for LogBatchDataIter<'a> {
97    type Item = (&'a SdkLogRecord, &'a InstrumentationScope);
98
99    fn next(&mut self) -> Option<Self::Item> {
100        match self.data {
101            LogBatchData::SliceOfOwnedData(data) => {
102                if self.index < data.len() {
103                    let record = &*data[self.index];
104                    self.index += 1;
105                    Some((&record.0, &record.1))
106                } else {
107                    None
108                }
109            }
110            LogBatchData::SliceOfBorrowedData(data) => {
111                if self.index < data.len() {
112                    let record = &data[self.index];
113                    self.index += 1;
114                    Some((record.0, record.1))
115                } else {
116                    None
117                }
118            }
119        }
120    }
121}
122
123/// `LogExporter` defines the interface that log exporters should implement.
124pub trait LogExporter: Send + Sync + Debug {
125    /// Exports a batch of log records and their associated instrumentation scopes.
126    ///
127    /// The `export` method is responsible for sending a batch of log records to an external
128    /// destination. It takes a `LogBatch` as an argument, which contains references to the
129    /// log records and their corresponding instrumentation scopes. The method returns
130    /// a `LogResult` indicating the success or failure of the export operation.
131    ///
132    /// # Arguments
133    ///
134    /// * `batch` - A `LogBatch` containing the log records and instrumentation scopes
135    ///   to be exported.
136    ///
137    /// # Returns
138    ///
139    /// A `LogResult<()>`, which is a result type indicating either a successful export (with
140    /// `Ok(())`) or an error (`Err(LogError)`) if the export operation failed.
141    ///
142    fn export(
143        &self,
144        batch: LogBatch<'_>,
145    ) -> impl std::future::Future<Output = OTelSdkResult> + Send;
146    /// Shuts down the exporter.
147    fn shutdown_with_timeout(&self, _timeout: time::Duration) -> OTelSdkResult {
148        Ok(())
149    }
150    /// Shuts down the exporter with a default timeout.
151    fn shutdown(&self) -> OTelSdkResult {
152        self.shutdown_with_timeout(time::Duration::from_secs(5))
153    }
154
155    /// Check if logs are enabled.
156    fn event_enabled(&self, _level: Severity, _target: &str, _name: Option<&str>) -> bool {
157        // By default, all logs are enabled
158        true
159    }
160    /// Set the resource for the exporter.
161    fn set_resource(&mut self, _resource: &Resource) {}
162}