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