|
15 | 15 | #include "freertos/FreeRTOS.h" |
16 | 16 | #include "freertos/semphr.h" |
17 | 17 | #include "log_router.h" |
| 18 | +#include "esp_log_color.h" |
| 19 | + |
| 20 | +#include "sdkconfig.h" |
18 | 21 |
|
19 | 22 | static const char *TAG = "log_router"; |
20 | 23 |
|
| 24 | +// Truncated messages will be immediately followed by this message |
| 25 | +#if (CONFIG_LOG_ROUTER_APPEND_STRING_ON_TRUNCATE) |
| 26 | +#if (CONFIG_LOG_COLORS) |
| 27 | +static const char *TRUNCATE_MESSAGE = LOG_ITALIC(LOG_COLOR_PURPLE) "" CONFIG_LOG_ROUTER_TRUNCATE_STRING "" LOG_RESET_COLOR "\n" ; |
| 28 | +#else |
| 29 | +static const char *TRUNCATE_MESSAGE = CONFIG_LOG_ROUTER_TRUNCATE_STRING "\n" ; |
| 30 | +#endif |
| 31 | +#endif |
21 | 32 | // Global mutex for thread safety |
22 | 33 | static SemaphoreHandle_t g_log_router_mutex = NULL; |
23 | 34 |
|
@@ -93,6 +104,96 @@ static esp_err_t esp_log_router_flush_buffer(esp_log_router_slist_t *item) |
93 | 104 | return ESP_OK; |
94 | 105 | } |
95 | 106 |
|
| 107 | +static void router_fwrite(const void *__restrict buffer, size_t size, size_t n, esp_log_router_slist_t *item, uint32_t now) |
| 108 | +{ |
| 109 | + bool should_flush = false; |
| 110 | + |
| 111 | + size_t len = n * size; |
| 112 | + |
| 113 | + // Check if we need to flush due to threshold |
| 114 | + if ((item->buffer_pos + len) >= item->flush_threshold) { |
| 115 | + should_flush = true; |
| 116 | + log_router_debug_printf("Flush buffer due to threshold\n"); |
| 117 | + } |
| 118 | + |
| 119 | + // Check if we need to flush due to timeout |
| 120 | + if ((now - item->last_flush_time) >= item->flush_timeout_ms) { |
| 121 | + should_flush = true; |
| 122 | + log_router_debug_printf("Flush buffer due to timeout\n"); |
| 123 | + } |
| 124 | + |
| 125 | + // Flush buffer if needed |
| 126 | + if (should_flush) { |
| 127 | +#ifdef CONFIG_LOG_ROUTER_DEBUG_OUTPUT |
| 128 | + uint64_t flush_start_time = esp_timer_get_time(); |
| 129 | +#endif |
| 130 | + esp_err_t flush_ret = esp_log_router_flush_buffer(item); |
| 131 | +#ifdef CONFIG_LOG_ROUTER_DEBUG_OUTPUT |
| 132 | + uint32_t flush_duration_us = esp_timer_get_time() - flush_start_time; |
| 133 | + log_router_debug_printf("Flush operation took %ums, file: %s\n", flush_duration_us / 1000, item->file_path); |
| 134 | +#endif |
| 135 | + if (flush_ret != ESP_OK) { |
| 136 | + log_router_debug_printf("Failed to flush buffer: %s\n", esp_err_to_name(flush_ret)); |
| 137 | + // Flush failed, write directly to file |
| 138 | + size_t written = fwrite(buffer, 1, len, item->log_fp); |
| 139 | + if (written != len) { |
| 140 | + log_router_debug_printf("Failed to write directly to file, written: %zu, expected: %d\n", written, len); |
| 141 | + // Try to seek to beginning and retry |
| 142 | + if (fseek(item->log_fp, 0, SEEK_SET) == 0 && ftruncate(fileno(item->log_fp), 0) == 0) { |
| 143 | + log_router_debug_printf("File truncated, retrying direct write\n"); |
| 144 | + written = fwrite(buffer, 1, len, item->log_fp); |
| 145 | + if (written != len) { |
| 146 | + log_router_debug_printf("Retry direct write also failed\n"); |
| 147 | + return; |
| 148 | + } |
| 149 | + } else { |
| 150 | + log_router_debug_printf("Failed to seek/truncate file for direct write\n"); |
| 151 | + return; |
| 152 | + } |
| 153 | + } |
| 154 | + fflush(item->log_fp); |
| 155 | + fsync(fileno(item->log_fp)); |
| 156 | + return; // Skip buffer write since we already wrote to file |
| 157 | + } |
| 158 | + // Flush successful, buffer is now empty, continue to buffer write |
| 159 | + } |
| 160 | + |
| 161 | + // Try to add to buffer, if still too large, write directly to file |
| 162 | + if ((item->buffer_pos + len) < item->buffer_size) { |
| 163 | + memcpy(item->buffer + item->buffer_pos, buffer, len); |
| 164 | + item->buffer_pos += len; |
| 165 | + } else { |
| 166 | + // Buffer is too small, write directly to file |
| 167 | +#ifdef CONFIG_LOG_ROUTER_DEBUG_OUTPUT |
| 168 | + uint64_t write_start_time = esp_timer_get_time(); |
| 169 | +#endif |
| 170 | + size_t written = fwrite(buffer, 1, len, item->log_fp); |
| 171 | + if (written != len) { |
| 172 | + log_router_debug_printf("Failed to write directly to file, written: %zu, expected: %d\n", written, len); |
| 173 | + // Try to seek to beginning and retry |
| 174 | + if (fseek(item->log_fp, 0, SEEK_SET) == 0 && ftruncate(fileno(item->log_fp), 0) == 0) { |
| 175 | + log_router_debug_printf("File truncated, retrying direct write\n"); |
| 176 | + written = fwrite(buffer, 1, len, item->log_fp); |
| 177 | + if (written != len) { |
| 178 | + log_router_debug_printf("Retry direct write also failed\n"); |
| 179 | + return; |
| 180 | + } |
| 181 | + } else { |
| 182 | + log_router_debug_printf("Failed to seek/truncate file for direct write\n"); |
| 183 | + return; |
| 184 | + } |
| 185 | + } |
| 186 | + fflush(item->log_fp); |
| 187 | + fsync(fileno(item->log_fp)); |
| 188 | +#ifdef CONFIG_LOG_ROUTER_DEBUG_OUTPUT |
| 189 | + uint32_t write_duration_us = esp_timer_get_time() - write_start_time; |
| 190 | + log_router_debug_printf("Direct write took %ums, size: %d, file: %s\n", write_duration_us / 1000, len, item->file_path); |
| 191 | +#endif |
| 192 | + } |
| 193 | + |
| 194 | + return; |
| 195 | +} |
| 196 | + |
96 | 197 | int esp_log_router_flash_vprintf(const char *format, va_list args) |
97 | 198 | { |
98 | 199 | int ret = 0; |
@@ -124,8 +225,9 @@ int esp_log_router_flash_vprintf(const char *format, va_list args) |
124 | 225 | esp_log_router_slist_t *item; |
125 | 226 | int len = vsnprintf(vprintf_buffer, sizeof(vprintf_buffer), format, args); |
126 | 227 | if (len > 0) { |
| 228 | + int trunc_b = 0; |
127 | 229 | if (len > (sizeof(vprintf_buffer) - 1)) { |
128 | | - int trunc_b = len - (sizeof(vprintf_buffer) - 1); |
| 230 | + trunc_b = len - (sizeof(vprintf_buffer) - 1); |
129 | 231 | log_router_debug_printf("Buffer too small, lost %d bytes\n", trunc_b); |
130 | 232 | len = sizeof(vprintf_buffer) - 1; |
131 | 233 | } |
@@ -161,88 +263,13 @@ int esp_log_router_flash_vprintf(const char *format, va_list args) |
161 | 263 | bool tag_match = (item->tag == NULL) || (tag_len > 0 && strncmp(tag_start, item->tag, tag_len) == 0 && item->tag[tag_len] == '\0'); |
162 | 264 |
|
163 | 265 | if (level_match && tag_match && item->log_fp) { |
164 | | - bool should_flush = false; |
165 | | - |
166 | | - // Check if we need to flush due to threshold |
167 | | - if ((item->buffer_pos + len) >= item->flush_threshold) { |
168 | | - should_flush = true; |
169 | | - log_router_debug_printf("Flush buffer due to threshold\n"); |
170 | | - } |
171 | | - |
172 | | - // Check if we need to flush due to timeout |
173 | | - if ((now - item->last_flush_time) >= item->flush_timeout_ms) { |
174 | | - should_flush = true; |
175 | | - log_router_debug_printf("Flush buffer due to timeout\n"); |
176 | | - } |
| 266 | + router_fwrite(vprintf_buffer, 1, len, item, now); |
177 | 267 |
|
178 | | - // Flush buffer if needed |
179 | | - if (should_flush) { |
180 | | -#ifdef CONFIG_LOG_ROUTER_DEBUG_OUTPUT |
181 | | - uint64_t flush_start_time = esp_timer_get_time(); |
182 | | -#endif |
183 | | - esp_err_t flush_ret = esp_log_router_flush_buffer(item); |
184 | | -#ifdef CONFIG_LOG_ROUTER_DEBUG_OUTPUT |
185 | | - uint32_t flush_duration_us = esp_timer_get_time() - flush_start_time; |
186 | | - log_router_debug_printf("Flush operation took %ums, file: %s\n", flush_duration_us / 1000, item->file_path); |
187 | | -#endif |
188 | | - if (flush_ret != ESP_OK) { |
189 | | - log_router_debug_printf("Failed to flush buffer: %s\n", esp_err_to_name(flush_ret)); |
190 | | - // Flush failed, write directly to file |
191 | | - size_t written = fwrite(vprintf_buffer, 1, len, item->log_fp); |
192 | | - if (written != len) { |
193 | | - log_router_debug_printf("Failed to write directly to file, written: %zu, expected: %d\n", written, len); |
194 | | - // Try to seek to beginning and retry |
195 | | - if (fseek(item->log_fp, 0, SEEK_SET) == 0 && ftruncate(fileno(item->log_fp), 0) == 0) { |
196 | | - log_router_debug_printf("File truncated, retrying direct write\n"); |
197 | | - written = fwrite(vprintf_buffer, 1, len, item->log_fp); |
198 | | - if (written != len) { |
199 | | - log_router_debug_printf("Retry direct write also failed\n"); |
200 | | - continue; |
201 | | - } |
202 | | - } else { |
203 | | - log_router_debug_printf("Failed to seek/truncate file for direct write\n"); |
204 | | - continue; |
205 | | - } |
206 | | - } |
207 | | - fflush(item->log_fp); |
208 | | - fsync(fileno(item->log_fp)); |
209 | | - continue; // Skip buffer write since we already wrote to file |
210 | | - } |
211 | | - // Flush successful, buffer is now empty, continue to buffer write |
| 268 | +#if (CONFIG_LOG_ROUTER_APPEND_STRING_ON_TRUNCATE) |
| 269 | + if (trunc_b > 0) { |
| 270 | + router_fwrite(TRUNCATE_MESSAGE, 1, strlen(TRUNCATE_MESSAGE), item, now); |
212 | 271 | } |
213 | | - |
214 | | - // Try to add to buffer, if still too large, write directly to file |
215 | | - if ((item->buffer_pos + len) < item->buffer_size) { |
216 | | - memcpy(item->buffer + item->buffer_pos, vprintf_buffer, len); |
217 | | - item->buffer_pos += len; |
218 | | - } else { |
219 | | - // Buffer is too small, write directly to file |
220 | | -#ifdef CONFIG_LOG_ROUTER_DEBUG_OUTPUT |
221 | | - uint64_t write_start_time = esp_timer_get_time(); |
222 | | -#endif |
223 | | - size_t written = fwrite(vprintf_buffer, 1, len, item->log_fp); |
224 | | - if (written != len) { |
225 | | - log_router_debug_printf("Failed to write directly to file, written: %zu, expected: %d\n", written, len); |
226 | | - // Try to seek to beginning and retry |
227 | | - if (fseek(item->log_fp, 0, SEEK_SET) == 0 && ftruncate(fileno(item->log_fp), 0) == 0) { |
228 | | - log_router_debug_printf("File truncated, retrying direct write\n"); |
229 | | - written = fwrite(vprintf_buffer, 1, len, item->log_fp); |
230 | | - if (written != len) { |
231 | | - log_router_debug_printf("Retry direct write also failed\n"); |
232 | | - continue; |
233 | | - } |
234 | | - } else { |
235 | | - log_router_debug_printf("Failed to seek/truncate file for direct write\n"); |
236 | | - continue; |
237 | | - } |
238 | | - } |
239 | | - fflush(item->log_fp); |
240 | | - fsync(fileno(item->log_fp)); |
241 | | -#ifdef CONFIG_LOG_ROUTER_DEBUG_OUTPUT |
242 | | - uint32_t write_duration_us = esp_timer_get_time() - write_start_time; |
243 | | - log_router_debug_printf("Direct write took %ums, size: %d, file: %s\n", write_duration_us / 1000, len, item->file_path); |
244 | 272 | #endif |
245 | | - } |
246 | 273 | } |
247 | 274 | } |
248 | 275 | } |
|
0 commit comments