opentelemetry_sdk/logs/
export.rs

1//! Log exporters
2use crate::error::OTelSdkResult;
3use crate::logs::SdkLogRecord;
4use crate::Resource;
5#[cfg(feature = "spec_unstable_logs_enabled")]
6use opentelemetry::logs::Severity;
7use opentelemetry::InstrumentationScope;
8use std::fmt::Debug;
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 an iterator over the log records and instrumentation scopes in the batch.
66    ///
67    /// Each item yielded by the iterator is a tuple containing references to a `LogRecord`
68    /// and an `InstrumentationScope`.
69    ///
70    /// # Returns
71    ///
72    /// An iterator that yields references to the `LogRecord` and `InstrumentationScope` in the batch.
73    ///
74    pub fn iter(&self) -> impl Iterator<Item = (&SdkLogRecord, &InstrumentationScope)> {
75        LogBatchDataIter {
76            data: &self.data,
77            index: 0,
78        }
79    }
80}
81
82struct LogBatchDataIter<'a> {
83    data: &'a LogBatchData<'a>,
84    index: usize,
85}
86
87impl<'a> Iterator for LogBatchDataIter<'a> {
88    type Item = (&'a SdkLogRecord, &'a InstrumentationScope);
89
90    fn next(&mut self) -> Option<Self::Item> {
91        match self.data {
92            LogBatchData::SliceOfOwnedData(data) => {
93                if self.index < data.len() {
94                    let record = &*data[self.index];
95                    self.index += 1;
96                    Some((&record.0, &record.1))
97                } else {
98                    None
99                }
100            }
101            LogBatchData::SliceOfBorrowedData(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        }
111    }
112}
113
114/// `LogExporter` defines the interface that log exporters should implement.
115pub trait LogExporter: Send + Sync + Debug {
116    /// Exports a batch of log records and their associated instrumentation scopes.
117    ///
118    /// The `export` method is responsible for sending a batch of log records to an external
119    /// destination. It takes a `LogBatch` as an argument, which contains references to the
120    /// log records and their corresponding instrumentation scopes. The method returns
121    /// a `LogResult` indicating the success or failure of the export operation.
122    ///
123    /// # Arguments
124    ///
125    /// * `batch` - A `LogBatch` containing the log records and instrumentation scopes
126    ///   to be exported.
127    ///
128    /// # Returns
129    ///
130    /// A `LogResult<()>`, which is a result type indicating either a successful export (with
131    /// `Ok(())`) or an error (`Err(LogError)`) if the export operation failed.
132    ///
133    fn export(
134        &self,
135        batch: LogBatch<'_>,
136    ) -> impl std::future::Future<Output = OTelSdkResult> + Send;
137
138    /// Shuts down the exporter.
139    fn shutdown(&mut self) -> OTelSdkResult {
140        Ok(())
141    }
142    #[cfg(feature = "spec_unstable_logs_enabled")]
143    /// Chek if logs are enabled.
144    fn event_enabled(&self, _level: Severity, _target: &str, _name: &str) -> bool {
145        // By default, all logs are enabled
146        true
147    }
148    /// Set the resource for the exporter.
149    fn set_resource(&mut self, _resource: &Resource) {}
150}