opentelemetry_sdk/logs/
export.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! Log exporters
use crate::error::OTelSdkResult;
use crate::logs::SdkLogRecord;
use crate::Resource;
#[cfg(feature = "spec_unstable_logs_enabled")]
use opentelemetry::logs::Severity;
use opentelemetry::InstrumentationScope;
use std::fmt::Debug;

/// A batch of log records to be exported by a `LogExporter`.
///
/// The `LogBatch` struct holds a collection of log records along with their associated
/// instrumentation scopes. This structure is used to group log records together for efficient
/// export operations.
///
/// # Type Parameters
/// - `'a`: The lifetime of the references to the log records and instrumentation scopes.
///
#[derive(Debug)]
pub struct LogBatch<'a> {
    data: LogBatchData<'a>,
}

/// The `LogBatchData` enum represents the data field of a `LogBatch`.
/// It can either be:
/// - A shared reference to a slice of boxed tuples, where each tuple consists of an owned `LogRecord` and an owned `InstrumentationScope`.
/// - 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`.
#[derive(Debug)]
enum LogBatchData<'a> {
    SliceOfOwnedData(&'a [Box<(SdkLogRecord, InstrumentationScope)>]), // Used by BatchProcessor which clones the LogRecords for its own use.
    SliceOfBorrowedData(&'a [(&'a SdkLogRecord, &'a InstrumentationScope)]),
}

impl<'a> LogBatch<'a> {
    /// Creates a new instance of `LogBatch`.
    ///
    /// # Arguments
    ///
    /// * `data` - A slice of tuples, where each tuple consists of a reference to a `LogRecord`
    ///   and a reference to an `InstrumentationScope`. These tuples represent the log records
    ///   and their associated instrumentation scopes to be exported.
    ///
    /// # Returns
    ///
    /// A `LogBatch` instance containing the provided log records and instrumentation scopes.
    ///
    /// Note - this is not a public function, and should not be used directly. This would be
    /// made private in the future.
    pub fn new(data: &'a [(&'a SdkLogRecord, &'a InstrumentationScope)]) -> LogBatch<'a> {
        LogBatch {
            data: LogBatchData::SliceOfBorrowedData(data),
        }
    }

    pub(crate) fn new_with_owned_data(
        data: &'a [Box<(SdkLogRecord, InstrumentationScope)>],
    ) -> LogBatch<'a> {
        LogBatch {
            data: LogBatchData::SliceOfOwnedData(data),
        }
    }
}

impl LogBatch<'_> {
    /// Returns an iterator over the log records and instrumentation scopes in the batch.
    ///
    /// Each item yielded by the iterator is a tuple containing references to a `LogRecord`
    /// and an `InstrumentationScope`.
    ///
    /// # Returns
    ///
    /// An iterator that yields references to the `LogRecord` and `InstrumentationScope` in the batch.
    ///
    pub fn iter(&self) -> impl Iterator<Item = (&SdkLogRecord, &InstrumentationScope)> {
        LogBatchDataIter {
            data: &self.data,
            index: 0,
        }
    }
}

struct LogBatchDataIter<'a> {
    data: &'a LogBatchData<'a>,
    index: usize,
}

impl<'a> Iterator for LogBatchDataIter<'a> {
    type Item = (&'a SdkLogRecord, &'a InstrumentationScope);

    fn next(&mut self) -> Option<Self::Item> {
        match self.data {
            LogBatchData::SliceOfOwnedData(data) => {
                if self.index < data.len() {
                    let record = &*data[self.index];
                    self.index += 1;
                    Some((&record.0, &record.1))
                } else {
                    None
                }
            }
            LogBatchData::SliceOfBorrowedData(data) => {
                if self.index < data.len() {
                    let record = &data[self.index];
                    self.index += 1;
                    Some((record.0, record.1))
                } else {
                    None
                }
            }
        }
    }
}

/// `LogExporter` defines the interface that log exporters should implement.
pub trait LogExporter: Send + Sync + Debug {
    /// Exports a batch of log records and their associated instrumentation scopes.
    ///
    /// The `export` method is responsible for sending a batch of log records to an external
    /// destination. It takes a `LogBatch` as an argument, which contains references to the
    /// log records and their corresponding instrumentation scopes. The method returns
    /// a `LogResult` indicating the success or failure of the export operation.
    ///
    /// # Arguments
    ///
    /// * `batch` - A `LogBatch` containing the log records and instrumentation scopes
    ///   to be exported.
    ///
    /// # Returns
    ///
    /// A `LogResult<()>`, which is a result type indicating either a successful export (with
    /// `Ok(())`) or an error (`Err(LogError)`) if the export operation failed.
    ///
    fn export(
        &self,
        batch: LogBatch<'_>,
    ) -> impl std::future::Future<Output = OTelSdkResult> + Send;

    /// Shuts down the exporter.
    fn shutdown(&mut self) -> OTelSdkResult {
        Ok(())
    }
    #[cfg(feature = "spec_unstable_logs_enabled")]
    /// Chek if logs are enabled.
    fn event_enabled(&self, _level: Severity, _target: &str, _name: &str) -> bool {
        // By default, all logs are enabled
        true
    }
    /// Set the resource for the exporter.
    fn set_resource(&mut self, _resource: &Resource) {}
}