Skip to content

Conversation

@bdraco
Copy link

@bdraco bdraco commented Jan 29, 2026

Fixes #379

PR #371 switched ESP8266 logging from ets_printf to Serial.printf_P, while nice and convenient for PROGMEM strings on ESP8266, it requires the global Serial object. This breaks builds using NO_GLOBAL_SERIAL to free up UART0 pins for other purposes.

This change restores using ets_printf with PROGMEM format strings and %c for the log level (char literals don't consume RAM).

Note: ESPHome may additionally use ASYNCWEBSERVER_LOG_CUSTOM to integrate with its own logging system, but that's a separate decision. This PR fixes the regression for all other users.

Untested - written while traveling and only verified it compiles ok for now. Will test on a real device when I reach a stable work environment.

Tested on an esp8266

@bdraco
Copy link
Author

bdraco commented Jan 29, 2026

tested on a real esp8266 with ets_printf (may route to nothing), and ets_uart_printf (always uart) and no crashes

❯ SSE Crash Reproducer Starting...                                                                                                                             
  E async_ws 52: Test error log: 42                                                                                                                            
  W async_ws 53: Test warning log: 43                                                                                                                          
  I async_ws 54: Test info log: 44                                                                                                                             
  After logging macros   

@bdraco bdraco marked this pull request as ready for review January 29, 2026 15:52
Copy link

@willmmiles willmmiles left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice! This is strictly superior to the previous version.

Two non-blocking questions:

  • Is there any value in moving the hardcoded buffer size constant 64 to a separate #define, in case it needs to be adjusted? Or - given that the macro is instantiated at each call site - could the buffer size be set to sizeof(__fmt), so it'll float to the correct size for each format string?
  • As another way to save code space, could the fixed portion of the format string ("%c async_ws %d: ") be stored in a common location for all calls instead of replicated for every call?

@bdraco
Copy link
Author

bdraco commented Jan 29, 2026

Is there any value in moving the hardcoded buffer size constant 64 to a separate #define, in case it needs to be adjusted? Or - given that the macro is instantiated at each call site - could the buffer size be set to sizeof(__fmt), so it'll float to the correct size for each format string?

I didn't add a #define since there's only one use site and it's immediately visible. For the sizeof(__fmt) suggestion, that would size the buffer to the format string length, but the actual output can be larger once %d, %s, etc. are expanded with real values. A fixed buffer handles that safely.

As another way to save code space, could the fixed portion of the format string ("%c async_ws %d: ") be stored in a common location for all calls instead of replicated for every call?

Moving the prefix to a shared location would require two strcpy_P/strncpy_P operations at runtime instead of one. The extra complexity didn't justify the small flash savings. For RAM savings, that trade-off would be worthwhile.

@mathieucarbou
Copy link
Member

I will merge and issue a fix release tomorrow.

@wmiles-sgl
Copy link

For the sizeof(__fmt) suggestion, that would size the buffer to the format string length, but the actual output can be larger once %d, %s, etc. are expanded with real values. A fixed buffer handles that safely.

That's true, but we aren't expanding text in to that buffer: it exists only to hold the format string.

@bdraco
Copy link
Author

bdraco commented Jan 29, 2026

For the sizeof(__fmt) suggestion, that would size the buffer to the format string length, but the actual output can be larger once %d, %s, etc. are expanded with real values. A fixed buffer handles that safely.

That's true, but we aren't expanding text in to that buffer: it exists only to hold the format string.

You are right, I was thinking about the earlier iteration. Let me fix that.

@bdraco bdraco marked this pull request as draft January 29, 2026 20:40
@bdraco bdraco marked this pull request as ready for review January 29, 2026 20:45
@bdraco
Copy link
Author

bdraco commented Jan 29, 2026

SSE connect, heap: 34688
E async_ws 234: Event message queue overflow: discard message
E async_ws 234: Event message queue overflow: discard message
E async_ws 234: Event message queue overflow: discard message
SSE disconnect, heap: 35008
E async_ws 234: Event message queue overflow: discard message
E async_ws 234: Event message queue overflow: discard message
E async_ws 234: Event message queue overflow: discard message
SSE connect, heap: 33504
E async_ws 234: Event message queue overflow: discard message
E async_ws 234: Event message queue overflow: discard message
SSE disconnect, heap: 31296
SSE disconnect, heap: 33712
SSE connect, heap: 35776
SSE connect, heap: 35600

still works fine

@mathieucarbou mathieucarbou merged commit 4d36225 into ESP32Async:main Jan 30, 2026
33 checks passed
@bdraco
Copy link
Author

bdraco commented Jan 30, 2026

Thanks for the quick release and review

@bdraco bdraco deleted the esp8266_logging_no_serial branch January 30, 2026 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AsyncWebServerLogging doesnt compile on ESP8266

4 participants