ESPHome 2026.4.0-dev
Loading...
Searching...
No Matches
task_log_buffer_esp32.cpp
Go to the documentation of this file.
1#ifdef USE_ESP32
2
4#include "esphome/core/log.h"
5
6#ifdef USE_ESPHOME_TASK_LOG_BUFFER
7
8namespace esphome::logger {
9
11 // Create a static ring buffer with RINGBUF_TYPE_NOSPLIT for message integrity
12 // Storage is a member array (embedded in Logger), no heap allocation needed
13 this->ring_buffer_ =
14 xRingbufferCreateStatic(sizeof(this->storage_), RINGBUF_TYPE_NOSPLIT, this->storage_, &this->structure_);
15}
16
18 if (this->ring_buffer_ != nullptr) {
19 vRingbufferDelete(this->ring_buffer_);
20 this->ring_buffer_ = nullptr;
21 }
22}
23
25 if (this->current_token_) {
26 return false;
27 }
28
29 size_t item_size = 0;
30 void *received_item = xRingbufferReceive(ring_buffer_, &item_size, 0);
31 if (received_item == nullptr) {
32 return false;
33 }
34
35 LogMessage *msg = static_cast<LogMessage *>(received_item);
36 message = msg;
37 text_length = msg->text_length;
38 this->current_token_ = received_item;
39
40 return true;
41}
42
44 if (this->current_token_ == nullptr) {
45 return;
46 }
47 vRingbufferReturnItem(ring_buffer_, this->current_token_);
48 this->current_token_ = nullptr;
49 // Update counter to mark all messages as processed
50 last_processed_counter_ = message_counter_.load(std::memory_order_relaxed);
51}
52
53bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name,
54 const char *format, va_list args) {
55 // First, calculate the exact length needed using a null buffer (no actual writing)
56 va_list args_copy;
57 va_copy(args_copy, args);
58 int ret = vsnprintf(nullptr, 0, format, args_copy);
59 va_end(args_copy);
60
61 if (ret <= 0) {
62 return false; // Formatting error or empty message
63 }
64
65 // Calculate actual text length (capped to maximum size)
66 static constexpr size_t MAX_TEXT_SIZE = 255;
67 size_t text_length = (static_cast<size_t>(ret) > MAX_TEXT_SIZE) ? MAX_TEXT_SIZE : ret;
68
69 // Calculate total size needed (header + text length + null terminator)
70 size_t total_size = sizeof(LogMessage) + text_length + 1;
71
72 // Acquire memory directly from the ring buffer
73 void *acquired_memory = nullptr;
74 BaseType_t result = xRingbufferSendAcquire(ring_buffer_, &acquired_memory, total_size, 0);
75
76 if (result != pdTRUE || acquired_memory == nullptr) {
77 return false; // Failed to acquire memory
78 }
79
80 // Set up the message header in the acquired memory
81 LogMessage *msg = static_cast<LogMessage *>(acquired_memory);
82 msg->level = level;
83 msg->tag = tag;
84 msg->line = line;
85
86 // Store the thread name now instead of waiting until main loop processing
87 // This avoids crashes if the task completes or is deleted between when this message
88 // is enqueued and when it's processed by the main loop
89 if (thread_name != nullptr) {
90 strncpy(msg->thread_name, thread_name, sizeof(msg->thread_name) - 1);
91 msg->thread_name[sizeof(msg->thread_name) - 1] = '\0'; // Ensure null termination
92 } else {
93 msg->thread_name[0] = '\0'; // Empty string if no thread name
94 }
95
96 // Format the message text directly into the acquired memory
97 // We add 1 to text_length to ensure space for null terminator during formatting
98 char *text_area = msg->text_data();
99 ret = vsnprintf(text_area, text_length + 1, format, args);
100
101 // Handle unexpected formatting error
102 if (ret <= 0) {
103 vRingbufferReturnItem(ring_buffer_, acquired_memory);
104 return false;
105 }
106
107 // Remove trailing newlines
108 while (text_length > 0 && text_area[text_length - 1] == '\n') {
109 text_length--;
110 }
111
112 msg->text_length = text_length;
113 // Complete the send operation with the acquired memory
114 result = xRingbufferSendComplete(ring_buffer_, acquired_memory);
115
116 if (result != pdTRUE) {
117 return false; // Failed to complete the message send
118 }
119
120 // Message sent successfully, increment the counter
121 message_counter_.fetch_add(1, std::memory_order_relaxed);
122 return true;
123}
124
125} // namespace esphome::logger
126
127#endif // USE_ESPHOME_TASK_LOG_BUFFER
128#endif // USE_ESP32
bool borrow_message_main_loop(LogMessage *&message, uint16_t &text_length)
bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, const char *format, va_list args)
const char * message
Definition component.cpp:35
const char int line
Definition log.h:74
const char * tag
Definition log.h:74
const char int const __FlashStringHelper * format
Definition log.h:74
const char int const __FlashStringHelper va_list args
Definition log.h:74
va_end(args)