From 6c846506b01231ebf4b5c60c11b036e1a23ffa0f Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 24 Dec 2024 06:06:13 -0800 Subject: [PATCH 1/7] initial commit --- opentelemetry-sdk/src/logs/log_processor.rs | 65 +++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index 9d78383e8b..51b12f8e7f 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -167,6 +167,71 @@ enum BatchMessage { /// A [`LogProcessor`] that buffers log records and reports /// them at a pre-configured interval from a dedicated background thread. + +// **Memory Management in BatchLogProcessor** +// +// The `BatchLogProcessor` manages memory through the following stages of log processing: +// +// 1. **Record Ingestion**: +// - Each `LogRecord` is **cloned** upon entering the processor. +// - `LogRecordAttributes` utilize a hybrid memory model: +// - Attributes up to `PREALLOCATED_ATTRIBUTE_CAPACITY` are **stack-allocated**. +// - Exceeding attributes trigger **heap allocation** in a dynamically growing vector. +// - The `LogRecord` and its associated `InstrumentationScope` are **boxed together** +// to allocate them on the heap before entering the queue. +// +// 2. **Queue Management**: +// - Uses a **bounded synchronous channel** (`sync_channel`) with a maximum size defined by `max_queue_size`. +// - Each queued item is a **heap-allocated** `Box<(LogRecord, InstrumentationScope)>`. +// - When the queue is full: +// - Records are **dropped** (counted but not stored). +// - A warning is logged the first time this occurs. +// +// 3. **Worker Thread Storage**: +// - The worker thread maintains a pre-allocated `Vec` of boxed record pairs: +// - The vector’s capacity is fixed at `max_export_batch_size`. +// - Records are **moved** (not cloned) from the queue to the vector for processing. +// +// 4. **Export Process**: +// - A temporary `Vec` is created during the export process to hold ownership of the boxed records: +// - The contents of the worker thread's buffer (`Vec>`) +// are moved into this temporary vector using `logs.split_off(0)`. +// - Ownership of the boxed records is transferred to the new vector, ensuring efficient +// memory usage without additional cloning. +// - The temporary vector is then used to construct references passed to the exporter via `LogBatch`. +// - The `export()` method receives references to the log records and `InstrumentationScope` +// contained in `LogBatch`. +// - If the exporter requires retaining the log records (e.g., for retries or asynchronous +// operations), it must **clone** the records inside the `export()` implementation. +// - After successful export: +// - The original boxed records are dropped, releasing heap memory. +// - Export is triggered in the following scenarios: +// - When the batch size reaches `max_export_batch_size`. +// - When the scheduled delay timer expires. +// - When `force_flush` is called. +// - During processor shutdown. +// +/// 5. **Memory Limits**: +/// - **Worst-Case Memory Usage**: +/// - **Queue Memory** = `max_queue_size * size of boxed (LogRecord + InstrumentationScope)`. +/// - **Batch Memory** = `max_export_batch_size * size of boxed (LogRecord + InstrumentationScope)`. +/// - **Total Maximum Memory:** +/// - When both the queue and batch vector are full: +/// ``` +/// (max_queue_size + max_export_batch_size) * size of boxed (LogRecord + InstrumentationScope) +/// ``` +/// - The temporary vector used during export only holds references to records, +/// so it does not contribute additional significant memory allocation. +// +// 6. **Key Notes on Memory Behavior**: +// - Boxing a `LogRecord` and `InstrumentationScope` moves the record to the heap, +// including stack-allocated attributes. +// - During the export process, ownership of the boxed records is transferred +// to a temporary vector created by `logs.split_off(0)`. +// - This temporary vector is then used to construct references passed to the exporter. +// - No additional cloning or copying occurs during the export process, minimizing +// memory overhead while ensuring efficient handling of log records. +// pub struct BatchLogProcessor { message_sender: SyncSender, handle: Mutex>>, From 1b5f52b5b7996b6caf00b0da9d13b6e5cb8e3aad Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 24 Dec 2024 06:16:51 -0800 Subject: [PATCH 2/7] more changes --- opentelemetry-sdk/src/logs/log_processor.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index 51b12f8e7f..e1b60cd84a 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -178,7 +178,10 @@ enum BatchMessage { // - Attributes up to `PREALLOCATED_ATTRIBUTE_CAPACITY` are **stack-allocated**. // - Exceeding attributes trigger **heap allocation** in a dynamically growing vector. // - The `LogRecord` and its associated `InstrumentationScope` are **boxed together** -// to allocate them on the heap before entering the queue. +// to allocate them on the heap before entering the queue. Which means: +// - The entire `LogRecord` object, including its stack-allocated inline attributes, is moved to the heap. +// - Any overflow attributes already on the heap remain unaffected. + // // 2. **Queue Management**: // - Uses a **bounded synchronous channel** (`sync_channel`) with a maximum size defined by `max_queue_size`. From 76973f4fcea0f726c033b93b92eed3b72f58812c Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 24 Dec 2024 09:29:45 -0800 Subject: [PATCH 3/7] fix lint --- opentelemetry-sdk/src/logs/log_processor.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index e1b60cd84a..9bbf624796 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -167,7 +167,6 @@ enum BatchMessage { /// A [`LogProcessor`] that buffers log records and reports /// them at a pre-configured interval from a dedicated background thread. - // **Memory Management in BatchLogProcessor** // // The `BatchLogProcessor` manages memory through the following stages of log processing: @@ -181,7 +180,6 @@ enum BatchMessage { // to allocate them on the heap before entering the queue. Which means: // - The entire `LogRecord` object, including its stack-allocated inline attributes, is moved to the heap. // - Any overflow attributes already on the heap remain unaffected. - // // 2. **Queue Management**: // - Uses a **bounded synchronous channel** (`sync_channel`) with a maximum size defined by `max_queue_size`. @@ -202,7 +200,7 @@ enum BatchMessage { // - Ownership of the boxed records is transferred to the new vector, ensuring efficient // memory usage without additional cloning. // - The temporary vector is then used to construct references passed to the exporter via `LogBatch`. -// - The `export()` method receives references to the log records and `InstrumentationScope` +// - The exporter's `export()` method receives references to the log records and `InstrumentationScope` // contained in `LogBatch`. // - If the exporter requires retaining the log records (e.g., for retries or asynchronous // operations), it must **clone** the records inside the `export()` implementation. From ba36c8f68aa9d323f85b5aa57f413ea4816e6605 Mon Sep 17 00:00:00 2001 From: Lalit Date: Sun, 26 Jan 2025 00:45:15 -0800 Subject: [PATCH 4/7] update doc comment --- opentelemetry-sdk/src/logs/log_processor.rs | 25 +++++++++++---------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index 1b2519218e..2d5a0565c9 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -264,7 +264,7 @@ type LogsData = Box<(LogRecord, InstrumentationScope)>; /// .with_log_processor(processor) /// .build(); /// -/// +/// // **Memory Management in BatchLogProcessor** // // The `BatchLogProcessor` manages memory through the following stages of log processing: @@ -272,12 +272,13 @@ type LogsData = Box<(LogRecord, InstrumentationScope)>; // 1. **Record Ingestion**: // - Each `LogRecord` is **cloned** upon entering the processor. // - `LogRecordAttributes` utilize a hybrid memory model: -// - Attributes up to `PREALLOCATED_ATTRIBUTE_CAPACITY` are **stack-allocated**. -// - Exceeding attributes trigger **heap allocation** in a dynamically growing vector. +// - First 5 attributes are **stack-allocated**. +// - Adding additional attribtues trigger **heap allocation** in a dynamically growing vector. // - The `LogRecord` and its associated `InstrumentationScope` are **boxed together** // to allocate them on the heap before entering the queue. This means: -// - The entire `LogRecord` object, including its stack-allocated inline attributes, is moved to the heap. -// - Any overflow attributes already on the heap remain unaffected. +// - The `LogRecord`'s inline attributes (if any) are moved to the heap as part of the boxed structure. +// - Any dynamically allocated data already on the heap (e.g., strings, overflow attributes) remains unaffected. +// - Ownership of the boxed data is transferred to the queue, ensuring it can be processed independently of the original objects. // // 2. **Queue Management**: // - Uses **two bounded synchronous channels** (`sync_channel`): @@ -311,19 +312,19 @@ type LogsData = Box<(LogRecord, InstrumentationScope)>; // - During the export process: // - The worker thread retrieves records from the log record queue until `max_export_batch_size` is reached or the queue is empty. // - The retrieved records are processed in batches and passed to the exporter. -// - The `ExportLog` message in the control queue explicitly triggers an export operation: -// - It is generated when the current batch size reaches `max_export_batch_size`. -// - A flag ensures only one `ExportLog` message is sent at a time to prevent redundant processing. -// - This message prompts the worker thread to process and export the current batch immediately, regardless of the scheduled delay. // - The exporter's `export()` method receives references to the log records and `InstrumentationScope`. // - If the exporter requires retaining the log records (e.g., for retries or asynchronous operations), it must **clone** the records inside the `export()` implementation. // - After successful export: // - The original boxed records are dropped, releasing heap memory. // - Export is triggered in the following scenarios: -// - When the batch size reaches `max_export_batch_size`. +// - When the batch size reaches `max_export_batch_size`, resulting in `ExportLog` control message being sent to the worker thread. // - When the scheduled delay timer expires. -// - When `force_flush` is called. -// - During processor shutdown. +// - When `force_flush` is called by the application, resulting in a `ForceFlush` control message being sent to the worker thread. +// - During processor shutdown initiated by the application, resulting in a `Shutdown` control message being sent to the worker thread. +// - Generation of `ExportLog` control message: +// - The `ExportLog` control message is generated by the application thread when a new record is added to the log record queue, and the current batch size reaches `max_export_batch_size`. +// - To prevent redundant messages, the `ExportLog` message is only sent if the previous one has been processed by the worker thread. +// - Upon receiving this message, the worker thread immediately processes and exports the current batch, overriding any scheduled delay. // // 5. **Memory Limits**: // - **Worst-Case Memory Usage**: From 403a4120c691a541f7d365cce177613232e4b7c9 Mon Sep 17 00:00:00 2001 From: Lalit Date: Sun, 26 Jan 2025 01:01:16 -0800 Subject: [PATCH 5/7] add rough size --- opentelemetry-sdk/src/logs/log_processor.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index 2d5a0565c9..d354b92d2c 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -337,6 +337,9 @@ type LogsData = Box<(LogRecord, InstrumentationScope)>; // ``` // (max_queue_size + max_export_batch_size) * size of boxed (LogRecord + InstrumentationScope) // ``` +// - The average size of a `LogRecord` is ~300 bytes ( assuming 4 attributes), and the `InstrumentationScope` is ~50 bytes assuming no attributes. +// - For `max_queue_size = 2048` and `max_export_batch_size = 512`, the total memory usage is ~900 KB as below: +// Calculation: `(2048 + 512) * (300 + 50) = 2560 * 350 = 896000 bytes = 896 KB`. // // 6. **Key Notes on Memory Behavior**: // - Boxing a `LogRecord` and `InstrumentationScope` moves the record to the heap, From 1282bfcb53fd8d3a28c910b2aac8d75d064b481e Mon Sep 17 00:00:00 2001 From: Lalit Date: Sun, 26 Jan 2025 01:11:17 -0800 Subject: [PATCH 6/7] move it to doc comment --- opentelemetry-sdk/src/logs/log_processor.rs | 172 ++++++++++---------- 1 file changed, 85 insertions(+), 87 deletions(-) diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index d354b92d2c..8243cca391 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -264,94 +264,92 @@ type LogsData = Box<(LogRecord, InstrumentationScope)>; /// .with_log_processor(processor) /// .build(); /// +/// **Memory Management in BatchLogProcessor** /// -// **Memory Management in BatchLogProcessor** -// -// The `BatchLogProcessor` manages memory through the following stages of log processing: -// -// 1. **Record Ingestion**: -// - Each `LogRecord` is **cloned** upon entering the processor. -// - `LogRecordAttributes` utilize a hybrid memory model: -// - First 5 attributes are **stack-allocated**. -// - Adding additional attribtues trigger **heap allocation** in a dynamically growing vector. -// - The `LogRecord` and its associated `InstrumentationScope` are **boxed together** -// to allocate them on the heap before entering the queue. This means: -// - The `LogRecord`'s inline attributes (if any) are moved to the heap as part of the boxed structure. -// - Any dynamically allocated data already on the heap (e.g., strings, overflow attributes) remains unaffected. -// - Ownership of the boxed data is transferred to the queue, ensuring it can be processed independently of the original objects. -// -// 2. **Queue Management**: -// - Uses **two bounded synchronous channels** (`sync_channel`): -// - One for **log records** (`logs_sender` and `logs_receiver`). -// - Another for **control messages** (`message_sender` and `message_receiver`). -// -// - **Log Record Queue**: -// - Stores log records as **heap-allocated** `Box<(LogRecord, InstrumentationScope)>`. -// - The queue size is configurable and defined by `max_queue_size`. -// - If the queue is full: -// - New log records are **dropped**, and a warning is logged the first time this happens. -// - Dropped records are counted for reporting during shutdown. -// -// - **Control Message Queue**: -// - Stores control messages (`BatchMessage`) to manage operations like exporting, force flushing, setting resources, and shutting down. -// - The control message queue has a fixed size (e.g., 64 messages). -// - Control messages are processed with higher priority, ensuring operational commands are handled promptly. -// - The use of a separate control queue ensures that critical commands, such as `Shutdown`, are not lost even if the log record queue is full. -// - Messages supported include: -// - `ExportLog`: Triggers an immediate export of log records. -// - `ForceFlush`: Flushes all buffered log records to the exporter. -// - `SetResource`: Updates the exporter with a new resource. -// - `Shutdown`: Cleans up and flushes logs before terminating the processor. -// -// 3. **Worker Thread Storage**: -// - The worker thread maintains a pre-allocated `Vec` of boxed record pairs: -// - The vector’s capacity is fixed at `max_export_batch_size`. -// - Records are **moved** (not cloned) from the log record queue to the vector for processing. -// -// 4. **Export Process**: -// - During the export process: -// - The worker thread retrieves records from the log record queue until `max_export_batch_size` is reached or the queue is empty. -// - The retrieved records are processed in batches and passed to the exporter. -// - The exporter's `export()` method receives references to the log records and `InstrumentationScope`. -// - If the exporter requires retaining the log records (e.g., for retries or asynchronous operations), it must **clone** the records inside the `export()` implementation. -// - After successful export: -// - The original boxed records are dropped, releasing heap memory. -// - Export is triggered in the following scenarios: -// - When the batch size reaches `max_export_batch_size`, resulting in `ExportLog` control message being sent to the worker thread. -// - When the scheduled delay timer expires. -// - When `force_flush` is called by the application, resulting in a `ForceFlush` control message being sent to the worker thread. -// - During processor shutdown initiated by the application, resulting in a `Shutdown` control message being sent to the worker thread. -// - Generation of `ExportLog` control message: -// - The `ExportLog` control message is generated by the application thread when a new record is added to the log record queue, and the current batch size reaches `max_export_batch_size`. -// - To prevent redundant messages, the `ExportLog` message is only sent if the previous one has been processed by the worker thread. -// - Upon receiving this message, the worker thread immediately processes and exports the current batch, overriding any scheduled delay. -// -// 5. **Memory Limits**: -// - **Worst-Case Memory Usage**: -// - **Log Record Queue Memory** = `max_queue_size * size of boxed (LogRecord + InstrumentationScope)`. -// - **Batch Memory** = `max_export_batch_size * size of boxed (LogRecord + InstrumentationScope)`. -// - **Control Message Queue Memory**: -// - Fixed at 64 messages, with negligible memory overhead. -// - **Total Maximum Memory:** -// - When both the log record queue and batch vector are full: -// ``` -// (max_queue_size + max_export_batch_size) * size of boxed (LogRecord + InstrumentationScope) -// ``` -// - The average size of a `LogRecord` is ~300 bytes ( assuming 4 attributes), and the `InstrumentationScope` is ~50 bytes assuming no attributes. -// - For `max_queue_size = 2048` and `max_export_batch_size = 512`, the total memory usage is ~900 KB as below: -// Calculation: `(2048 + 512) * (300 + 50) = 2560 * 350 = 896000 bytes = 896 KB`. -// -// 6. **Key Notes on Memory Behavior**: -// - Boxing a `LogRecord` and `InstrumentationScope` moves the record to the heap, -// including stack-allocated attributes. -// - During the export process, records are moved from the log record queue to the worker thread’s vector. -// - No additional cloning or copying occurs during the export process, minimizing memory overhead while ensuring efficient handling of log records. -// -// 7. **Control Queue Prioritization**: -// - Control messages take precedence over log record processing to ensure timely execution of critical operations. -// - For instance, a `Shutdown` message is processed before continuing with log exports, guaranteeing graceful cleanup. -// - The use of a separate control queue ensures responsiveness to operational commands without the risk of losing critical messages, even if the log record queue is full. - +/// The `BatchLogProcessor` manages memory through the following stages of log processing: +/// +/// 1. **Record Ingestion**: +/// - Each `LogRecord` is **cloned** upon entering the processor. +/// - `LogRecordAttributes` utilize a hybrid memory model: +/// - First 5 attributes are **stack-allocated**. +/// - Adding additional attribtues trigger **heap allocation** in a dynamically growing vector. +/// - The `LogRecord` and its associated `InstrumentationScope` are **boxed together** +/// to allocate them on the heap before entering the queue. This means: +/// - The `LogRecord`'s inline attributes (if any) are moved to the heap as part of the boxed structure. +/// - Any dynamically allocated data already on the heap (e.g., strings, overflow attributes) remains unaffected. +/// - Ownership of the boxed data is transferred to the queue, ensuring it can be processed independently of the original objects. +/// +/// 2. **Queue Management**: +/// - Uses **two bounded synchronous channels** (`sync_channel`): +/// - One for **log records** (`logs_sender` and `logs_receiver`). +/// - Another for **control messages** (`message_sender` and `message_receiver`). +/// +/// - **Log Record Queue**: +/// - Stores log records as **heap-allocated** `Box<(LogRecord, InstrumentationScope)>`. +/// - The queue size is configurable and defined by `max_queue_size`. +/// - If the queue is full: +/// - New log records are **dropped**, and a warning is logged the first time this happens. +/// - Dropped records are counted for reporting during shutdown. +/// +/// - **Control Message Queue**: +/// - Stores control messages (`BatchMessage`) to manage operations like exporting, force flushing, setting resources, and shutting down. +/// - The control message queue has a fixed size (e.g., 64 messages). +/// - Control messages are processed with higher priority, ensuring operational commands are handled promptly. +/// - The use of a separate control queue ensures that critical commands, such as `Shutdown`, are not lost even if the log record queue is full. +/// - Messages supported include: +/// - `ExportLog`: Triggers an immediate export of log records. +/// - `ForceFlush`: Flushes all buffered log records to the exporter. +/// - `SetResource`: Updates the exporter with a new resource. +/// - `Shutdown`: Cleans up and flushes logs before terminating the processor. +/// +/// 3. **Worker Thread Storage**: +/// - The worker thread maintains a pre-allocated `Vec` of boxed record pairs: +/// - The vector’s capacity is fixed at `max_export_batch_size`. +/// - Records are **moved** (not cloned) from the log record queue to the vector for processing. +/// +/// 4. **Export Process**: +/// - During the export process: +/// - The worker thread retrieves records from the log record queue until `max_export_batch_size` is reached or the queue is empty. +/// - The retrieved records are processed in batches and passed to the exporter. +/// - The exporter's `export()` method receives references to the log records and `InstrumentationScope`. +/// - If the exporter requires retaining the log records (e.g., for retries or asynchronous operations), it must **clone** the records inside the `export()` implementation. +/// - After successful export: +/// - The original boxed records are dropped, releasing heap memory. +/// - Export is triggered in the following scenarios: +/// - When the batch size reaches `max_export_batch_size`, resulting in `ExportLog` control message being sent to the worker thread. +/// - When the scheduled delay timer expires. +/// - When `force_flush` is called by the application, resulting in a `ForceFlush` control message being sent to the worker thread. +/// - During processor shutdown initiated by the application, resulting in a `Shutdown` control message being sent to the worker thread. +/// - Generation of `ExportLog` control message: +/// - The `ExportLog` control message is generated by the application thread when a new record is added to the log record queue, and the current batch size reaches `max_export_batch_size`. +/// - To prevent redundant messages, the `ExportLog` message is only sent if the previous one has been processed by the worker thread. +/// - Upon receiving this message, the worker thread immediately processes and exports the current batch, overriding any scheduled delay. +/// +/// 5. **Memory Limits**: +/// - **Worst-Case Memory Usage**: +/// - **Log Record Queue Memory** = `max_queue_size * size of boxed (LogRecord + InstrumentationScope)`. +/// - **Batch Memory** = `max_export_batch_size * size of boxed (LogRecord + InstrumentationScope)`. +/// - **Control Message Queue Memory**: +/// - Fixed at 64 messages, with negligible memory overhead. +/// - **Total Maximum Memory:** +/// - When both the log record queue and batch vector are full: +/// ``` +/// (max_queue_size + max_export_batch_size) * size of boxed (LogRecord + InstrumentationScope) +/// ``` +/// - The average size of a `LogRecord` is ~300 bytes ( assuming 4 attributes), and the `InstrumentationScope` is ~50 bytes assuming no attributes. +/// - For `max_queue_size = 2048` and `max_export_batch_size = 512`, the total memory usage is ~900 KB as below: +/// Calculation: `(2048 + 512) * (300 + 50) = 2560 * 350 = 896000 bytes = 896 KB`. +/// +/// 6. **Key Notes on Memory Behavior**: +/// - Boxing a `LogRecord` and `InstrumentationScope` moves the record to the heap, +/// including stack-allocated attributes. +/// - During the export process, records are moved from the log record queue to the worker thread’s vector. +/// - No additional cloning or copying occurs during the export process, minimizing memory overhead while ensuring efficient handling of log records. +/// +/// 7. **Control Queue Prioritization**: +/// - Control messages take precedence over log record processing to ensure timely execution of critical operations. +/// - For instance, a `Shutdown` message is processed before continuing with log exports, guaranteeing graceful cleanup. +/// - The use of a separate control queue ensures responsiveness to operational commands without the risk of losing critical messages, even if the log record queue is full. pub struct BatchLogProcessor { logs_sender: SyncSender, // Data channel to store log records and instrumentation scopes message_sender: SyncSender, // Control channel to store control messages for the worker thread From 24797bb5d502036e64016cdf621d63129cb75d53 Mon Sep 17 00:00:00 2001 From: Lalit Date: Sun, 26 Jan 2025 01:17:04 -0800 Subject: [PATCH 7/7] doc ci --- opentelemetry-sdk/src/logs/log_processor.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index 8243cca391..c5eacac3a6 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -263,6 +263,7 @@ type LogsData = Box<(LogRecord, InstrumentationScope)>; /// let provider = LoggerProvider::builder() /// .with_log_processor(processor) /// .build(); +/// ``` /// /// **Memory Management in BatchLogProcessor** /// @@ -272,7 +273,7 @@ type LogsData = Box<(LogRecord, InstrumentationScope)>; /// - Each `LogRecord` is **cloned** upon entering the processor. /// - `LogRecordAttributes` utilize a hybrid memory model: /// - First 5 attributes are **stack-allocated**. -/// - Adding additional attribtues trigger **heap allocation** in a dynamically growing vector. +/// - Adding additional attributes trigger **heap allocation** in a dynamically growing vector. /// - The `LogRecord` and its associated `InstrumentationScope` are **boxed together** /// to allocate them on the heap before entering the queue. This means: /// - The `LogRecord`'s inline attributes (if any) are moved to the heap as part of the boxed structure.