-
Notifications
You must be signed in to change notification settings - Fork 220
esp/modesp.c: Add osdebug() and oslog() #112
Conversation
Code lineage: osdebug() is based loosely on the version in esp8266, but there didn't seem to be an obvious way of choosing a particular UART. The basic behavior is the same, though: provide None, and logging is disabled; provide an integer and logging is restored to the default level. To build on that, and because the IDF provides more functionality, a second parameter has now been implemented which allows the active log level to be set: esp.osdebug(uart[, level]) The module has a corresponding set of LOG_ values to set this accordingly. An additional level esp.LOG_CRITICAL, which maps to esp.LOG_ERROR has been included in order to provide better symetry with standard Python logging frameworks. In order to test out correct behavior, it was straightforward to add a second function that calls the IDF to perform a logging operation: esp.oslog(level, tag, message) Because our intent to write anything in Python that can be in Python, the thought is that format and parameters will be transformed to a simple string in Python, to them be passed here for rendering.
I wanted to be able to switch off logging to the console, and was disappointed to see esp.osdebug() missing. I mean, esp32 is an evolving platform, so it's totally fair, but I still wanted it. There are a couple of other things that I want to work on, but this one seemed like relatively low hanging fruit that I could use to learn the platform. Hopefully I haven't made too many rookie mistakes along the way, and that I've observed style guidelines and pull request convention, but let me know if I need to do anything differently in the future. |
|
||
return mp_const_none; | ||
} | ||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_osdebug_obj, 1, 2, esp_osdebug); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be better to have this function just take 1 arg, esp.osdebug(level), same as esp8266, and just have level=None mean disable, and any other value is an integer that is passed as the second arg to esp_log_level_set?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the case of the ESP32 it doesn't really allow you to redirect errors to different UARTs (?) so I'd say it's fine to repurpose the single argument to this function to be the log level.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe? You're the maintainer, so get the final say.
The reasoning for the additional parameter is twofold: that repurposing the existing argument would break backwards compatibility for anyone migrating code from ESP8266 in a minor but unpredictable way; the other is that although I can't see how to do it yet, the ESP32 does have two UARTs, and the hardware allows developers to change pin assignments for how UARTs are routed... it may be that at some point this would become possible.
But would appreciate your thoughts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, points taken. But I think the implementation should be adjusted so that passing None
as the first arg always disables logging, even if there are 2 args passed (eg esp.osdebug(None, 123)
).
esp32/modesp.c
Outdated
|
||
return mp_const_none; | ||
} | ||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_oslog_obj, esp_oslog); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a neat function, but is it useful? What was your use case for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Python you can just use "print" to write logging info, or use the logging module (which is already ported to MicroPython).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're absolutely right... there are other ways of delivering text. I think that use cases for print and logging are different though. I like the way that (regular) Python at least allows for different types of endpoints. If the endpoint is the console, then it occurred to me (after I'd added the thing for testing) that it might be less jarring to present log output in a manner consistent with the OS (in terms of tags, colors, and so on).
(so basically a shim between the python logging module and the OS)
Again, though, I'll leave you to decide.
esp32/modesp.c
Outdated
{ MP_OBJ_NEW_QSTR(MP_QSTR_LOG_DEBUG), MP_OBJ_NEW_SMALL_INT((mp_uint_t)ESP_LOG_DEBUG)}, | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR_LOG_VERBOSE), MP_OBJ_NEW_SMALL_INT((mp_uint_t)ESP_LOG_VERBOSE)}, | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR_LOG_DEFAULT), MP_OBJ_NEW_SMALL_INT((mp_uint_t)LOG_LOCAL_LEVEL)}, | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to have this protected by MODESP_INCLUDE_CONSTANTS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That did seem a bit weird. Thanks for the pointer.
esp32/modesp.c
Outdated
|
||
#if MODESP_INCLUDE_CONSTANTS | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR_LOG_NONE), MP_OBJ_NEW_SMALL_INT((mp_uint_t)ESP_LOG_NONE)}, | ||
{ MP_OBJ_NEW_QSTR(MP_QSTR_LOG_CRITICAL), MP_OBJ_NEW_SMALL_INT((mp_uint_t)ESP_LOG_ERROR)}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be ESP_LOG_CRITICAL?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The levels are defined as an enum and typedef in esp-idf/components/log/include/esp_log.h, and there isn't a ESP_LOG_CRITICAL. I wanted to provide some equivalence for the Python abstraction, though: the absence of the level in the base OS, shouldn't be something that your casual developer needs to worry about.
esp32/modesp.c
Outdated
@@ -101,6 +146,17 @@ STATIC const mp_rom_map_elem_t esp_module_globals_table[] = { | |||
|
|||
{ MP_ROM_QSTR(MP_QSTR_neopixel_write), MP_ROM_PTR(&esp_neopixel_write_obj) }, | |||
{ MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) }, | |||
|
|||
#if MODESP_INCLUDE_CONSTANTS | |||
{ MP_OBJ_NEW_QSTR(MP_QSTR_LOG_NONE), MP_OBJ_NEW_SMALL_INT((mp_uint_t)ESP_LOG_NONE)}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use MP_ROM_QSTR and MP_ROM_INT for the macro wrappers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Thank you!
I reviewed the code before reading the above comments, sorry!
IMO this is not necessary. The less constants in the esp module the better.
With that philosophy (which is a good philosophy) one should use the Python logging module, not have something extra like oslog. |
Yes, I agree, the info messages can get annoying (not to mention mess up scripts/tests that don't expect them). So the addition of esp.osdebug is certainly welcome, thanks! |
I just commented on your original comments before I saw your latest messages. Unless I hear otherwise, I'll remove oslog from the pull request. Thanks for your attention, Damien! |
Code lineage:
osdebug() is based loosely on the version in esp8266, but there didn't
seem to be an obvious way of choosing a particular UART. The basic
behavior is the same, though: provide None, and logging is disabled;
provide an integer and logging is restored to the default level.
To build on that, and because the IDF provides more functionality, a
second parameter has now been implemented which allows the active log
level to be set:
esp.osdebug(uart[, level])
The module has a corresponding set of LOG_ values to set this
accordingly. An additional level esp.LOG_CRITICAL, which maps to
esp.LOG_ERROR has been included in order to provide better
symetry with standard Python logging frameworks.
In order to test out correct behavior, it was straightforward to add a
second function that calls the IDF to perform a logging operation:
esp.oslog(level, tag, message)
Because our intent to write anything in Python that can be in Python,
the thought is that format and parameters will be transformed to a
simple string in Python, to them be passed here for rendering.