Skip to content

core/debug.h: refactor functions, implement automatic prefixing - #22525

Open
mguetschow wants to merge 13 commits into
RIOT-OS:masterfrom
mguetschow:debug-thread-names
Open

core/debug.h: refactor functions, implement automatic prefixing#22525
mguetschow wants to merge 13 commits into
RIOT-OS:masterfrom
mguetschow:debug-thread-names

Conversation

@mguetschow

@mguetschow mguetschow commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Contribution description

This PR improves printf debugging with the debug.h file. It adds an automatic prefix to every printout with

  • a developer-defined debug prefix (defaults to "")
  • optionally, the current function name
  • optionally, the thread name of the currently running thread (or <isr>).

It is backwards-compatible by not changing the behavior as long as DEBUG_PREFIX is unset in a file.

I also sneaked in some more fixes to the debug.h file and some nice coloring for the prefix prints.

Testing procedure

Apply the following diff

diff --git a/core/sched.c b/core/sched.c
index 04d0091e27..94a1fd3719 100644
--- a/core/sched.c
+++ b/core/sched.c
@@ -33,7 +33,7 @@
 #include "mpu.h"
 #endif
 
-#define ENABLE_DEBUG 0
+#define ENABLE_DEBUG 1
 #define DEBUG_PREFIX "sched"
 #include "debug.h"
 
diff --git a/examples/basic/blinky/Makefile b/examples/basic/blinky/Makefile
index efff486b3d..f7451292f8 100644
--- a/examples/basic/blinky/Makefile
+++ b/examples/basic/blinky/Makefile
@@ -18,4 +18,7 @@ QUIET ?= 1
 # Use a peripheral timer for the delay, if available
 FEATURES_OPTIONAL += periph_timer
 
+CFLAGS += -DCONFIG_DEBUG_SHOW_THREAD=1
+CFLAGS += -DCONFIG_DEBUG_SHOW_FUNC=1
+
 include $(RIOTBASE)/Makefile.include
diff --git a/sys/ztimer/core.c b/sys/ztimer/core.c
index ea831665c6..9fe2d0b118 100644
--- a/sys/ztimer/core.c
+++ b/sys/ztimer/core.c
@@ -34,7 +34,7 @@
 #include "ztimer.h"
 #include "log.h"
 
-#define ENABLE_DEBUG 0
+#define ENABLE_DEBUG 1
 #define DEBUG_PREFIX "ztimer.core"
 #include "debug.h"

and see it working with

make -C examples/basic/blinky flash term

I've tested it on native and I think I remember to have tested it on an nrf52840dk, too.

Issues/PRs references

This has helped me in the past to debug issues such as #21843

Declaration of AI-Tools / LLMs usage:

AI-Tools / LLMs that were used are:

  • none

@github-actions github-actions Bot added Area: core Area: RIOT kernel. Handle PRs marked with this with care! Area: timers Area: timer subsystems Area: sys Area: System labels Jul 29, 2026
@crasbe crasbe added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Process: needs >1 ACK Integration Process: This PR requires more than one ACK AI: Not Used AI was stated to not be used in this PR/Issue labels Jul 29, 2026
@github-actions github-actions Bot added the Process: missing approvals Integration Process: PR needs more ACKS (handled by action) label Jul 29, 2026
Comment thread core/lib/include/debug.h Outdated
Comment thread core/lib/include/debug.h
Comment thread core/lib/include/debug.h Outdated
Comment thread core/lib/include/debug.h Outdated
Comment thread core/lib/include/debug.h Outdated
Comment thread core/lib/include/debug.h Outdated
Comment thread core/lib/include/debug.h Outdated
Comment thread core/lib/include/debug.h Outdated
Comment thread sys/log_color/log_color.c Outdated
Comment thread sys/log_color/log_color.c
@riot-ci

riot-ci commented Jul 29, 2026

Copy link
Copy Markdown

Murdock results

✔️ PASSED

b4c60d8 fixup! tests/core/debug: add test for prefix printing

Success Failures Total Runtime
11296 0 11297 17m:07s

Artifacts

@crasbe crasbe added the CI: no fast fail don't abort PR build after first error label Jul 30, 2026
@mguetschow

Copy link
Copy Markdown
Contributor Author

I've tested it on native and I think I remember to have tested it on an nrf52840dk, too.

Just retested on that hardware, works as expected after increasing the ISR_STACKSIZE to accomodate the printf debugging (same behavior as on master).

Comment thread core/lib/include/debug.h
@github-actions github-actions Bot added the Area: tests Area: tests and testing framework label Jul 30, 2026
@mguetschow

Copy link
Copy Markdown
Contributor Author

I've added a test to showcase the different possible configurations:

$ make -C tests/core/debug flash test
...
main(): This is RIOT! (Version: 2026.10-devel-234-gd23258-debug-thread-names)
debug puts
debug printf number '42' ... continued
:noprefix_func # debug puts
:noprefix_func # debug printf number '42' ... continued
@main # debug puts
@main # debug printf number '42' ... continued
:noprefix_thread_func@main # debug puts
:noprefix_thread_func@main # debug printf number '42' ... continued
prefix # debug puts
prefix # debug printf number '42' ... continued
prefix:prefix_func # debug puts
prefix:prefix_func # debug printf number '42' ... continued
prefix@main # debug puts
prefix@main # debug printf number '42' ... continued
prefix:prefix_thread_func@main # debug puts
prefix:prefix_thread_func@main # debug printf number '42' ... continued

with colors:

image

Comment thread tests/core/debug/noprefix_thread_func.c Outdated
@mguetschow

Copy link
Copy Markdown
Contributor Author

considering to replace the function separator : with & or ! for nicer visual output in case the prefix is empty, any preferences?

@carl-tud

carl-tud commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

considering to replace the function separator : with & or ! for nicer visual output in case the prefix is empty, any preferences?

I think the way you're doing it right now is fine. Perhaps I'd prefer

prefix (func@thread) # blah blah

I think this would make it a lot easier to tell apart log lines that don't have a prefix but a func or thread from those with a prefix/subsystem. Right now, you could confuse one line's prefix with the func or thread of another

# blah
prefix # blah
prefix (func) # blah
prefix (@thread) # blah
prefix (func@thread) # blah blah
(func@thread) # blah blah

@carl-tud carl-tud left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

my thoughts, summarised. not necessarily required to merge this PR but perhaps still worth considering

  1. Love this. Extremely helpful for unicoap logs
  2. Future work: enable logging based on prefix
  3. Future work: same stuff for log.h
  4. Would be nice to harmonise coloured logging with log.h, and to think about how the log level would be expressed visually
  5. Perhaps worth reconsidering the format, see above
  6. Can you make the prefix bold please
  7. Prompt Engineering Bro Max: would it be a lot of effort to let users change the colour of individual parts using env vars?
  8. Can we infer a default prefix from MODULE
  9. Multiple prefixes per file through some underlying macros that accept the prefix as an additional parameter?

Comment thread core/sched.c
Comment thread tests/core/debug/prefix_func.c
@mguetschow

Copy link
Copy Markdown
Contributor Author
2. Future work: enable logging based on prefix
3. Future work: same stuff for log.h
4. Would be nice to harmonise coloured logging with log.h, and to think about how the log level would be expressed visually

Agree those would be nice for the future. In general reconsidering log.h vs debug.h in some way.

5. Perhaps worth reconsidering the format, see above

Like your proposal, will adapt.

6. Can you make the prefix bold please

Can do.

7. Prompt Engineering Bro Max: would it be a lot of effort to let users change the colour of individual parts using env vars?

What do you mean with individual parts? prefix vs func vs thread? What's the use-case? I'd leave this for a potential follow-up in any case.

8. Can we infer a default prefix from MODULE

Potential Follow-up

9. Multiple prefixes per file through some underlying macros that accept the prefix as an additional parameter?

Good idea, will try how that works out.

@github-actions github-actions Bot added Platform: native Platform: This PR/issue effects the native platform Area: cpu Area: CPU/MCU ports labels Aug 19, 2026
Comment thread core/lib/include/debug.h Outdated
@carl-tud

carl-tud commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

What do you mean with individual parts? prefix vs func vs thread? What's the use-case? I'd leave this for a potential follow-up in any case.

As something for a follow up, perhaps folks want to set individual colors/styles for prefix, thread, func, time, and separator individually -- like a bash prompt. but these sort of kindergarten games we can do later I guess, if at all.

@mguetschow

Copy link
Copy Markdown
Contributor Author
5. Perhaps worth reconsidering the format, see above

Like your proposal, will adapt.

9. Multiple prefixes per file through some underlying macros that accept the prefix as an additional parameter?

Good idea, will try how that works out.

Those two are now done. I think this is ready for another round of review. I will rework the git history when we agree on a solution.

carl-tud and others added 6 commits August 25, 2026 18:48
backwards-compatible by not changing any behavior as long as DEBUG_PREFIX is unset or empty

set a prefix per file by defining DEBUG_PREFIX

enable prefixing every call to debug functions with the function name and/or the thread name via configuration options CONFIG_DEBUG_SHOW_FUNC and CONFIG_DEBUG_SHOW_FUNC
@github-actions github-actions Bot removed the Platform: native Platform: This PR/issue effects the native platform label Aug 25, 2026
@mguetschow

Copy link
Copy Markdown
Contributor Author

Squashed and rebased on top of #22621

Ready for final review?

@carl-tud

carl-tud commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

I was just thinking... either we add a config guard to the ansi style header or at every call site, so including debug.h, we require a check for a config macro that toggles ansi escape sequence support. I think there are valid reasons to turn off colour:

  • someone attaches to a serial port with basic means
  • and IDE does not support coloured output and renders the escape sequence verbatim
  • accessibility reasons

@mguetschow

Copy link
Copy Markdown
Contributor Author

was just thinking... either we add a config guard to the ansi style header or at every call site, so including debug.h, we require a check for a config macro that toggles ansi escape sequence support.

I am strongly in favor of the config guard in the ansi style header instead of the extra burden on the call site. But agree that a toggle makes sense.

@carl-tud

Copy link
Copy Markdown
Contributor

Let's smuggle the config guard in there as part of this PR? I mean as the first impl using ANSI styling Id argue it's justified

@carl-tud

carl-tud commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

I'd suggest CONFIG_ALLOW_ANSI_ESCAPE_SEQUENCES if we're going for sound and cursor movement and whatnot, or just CONFIG_ALLOW_STYLED_OUTPUT... unless there's a better term for stdout. What do other config macros call the stdout-like thing? Term?

@crasbe crasbe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I didn't look through all the changed files where the DEBUG macros were updated.

Comment thread core/lib/include/debug.h Outdated
Comment thread core/lib/include/debug.h
Comment thread core/lib/include/debug.h Outdated
Comment thread core/lib/include/debug.h
Comment thread core/lib/include/debug.h Outdated
Comment thread core/lib/include/debug.h Outdated
Comment thread core/lib/include/debug.h Outdated
Comment thread tests/core/debug/tests/01-run.py Outdated
Comment thread tests/core/debug/tests/01-run.py Outdated
Comment thread tests/core/debug/main.c
/* this would typically be set application-wide via Kconfig or make */
#define CONFIG_DEBUG_SHOW_THREAD 1

#define ENABLE_DEBUG 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we add something to stop Coccinelle complaining about ENABLE_DEBUG being set to 1? To avoid adding warnings to our static tests? 🤔

@carl-tud

carl-tud commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

CONFIG_STDIO_STYLING💇 maybe
because it's not just colour

Comment thread core/lib/include/debug.h Outdated
@mguetschow

Copy link
Copy Markdown
Contributor Author

CONFIG_STDIO_STYLING💇 maybe because it's not just colour

see 8a7ba3b

@crasbe crasbe added State: needs rebase State: The codebase was changed since the creation of the PR, making a rebase necessary and removed State: waiting for other PR State: The PR requires another PR to be merged first labels Aug 26, 2026
@carl-tud

carl-tud commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

took the liberty of changing debug logging and docs: 9041f0c. goal: make all of this more customisable.

  1. DEBUG_PUTS_ had some repetitions I got rid of

  2. Recently had the pleasure of needing to send logs over network. So I suggest letting people swap out the debug implementation. (simple #if !defined(...) || defined(DOXYGEN))

  3. Perhaps we want to let people change the file debug messages are printed to. the puts version already used fputs, but what about fprintf. Hence, there're are now two RIOT-provided debug implementations, and DEBUG_, DEBUG_PUTS_, etc just redirect. Added examples to docs detailing how to change file to stderr for example.
    a. __DEBUG_IMPL_FORMATTED for printf, fprintf-like functions accepting a format string and format args
    b. __DEBUG_IMPL_PIECEWISE for fputs-like functions accepting a single string

  4. Symbols are now in documentation group and properly divided into sections.

naming debatable.

Screenshot 2026-08-29 at 12 05 28

@mguetschow

Copy link
Copy Markdown
Contributor Author

@carl-tud while this indeed makes it more customisable, it seems a bit confusing as well with all those different macros: I wonder if we could get rid of DEBUG_ and friends, and just let people define their own CUSTOM_DEBUG function on top of __DEBUG_IMPL_FORMATTED? Or have a define akin to DEBUG_FUNCTION that sets the used function for the file?

Also, wouldn't it be the more likely usecase wanting to redirect debug logging from all files? Isn't it then a bit cumbersome to add a custom debug function to all files where ENABLE_DEBUG is 1? It feels a bit like this is exploding, should we maybe rather first merge here and then refine later? At least all of the proposed changes would not be source-breaking.

@carl-tud

carl-tud commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

I wonder if we could get rid of DEBUG_ and friends, and just let people define their own CUSTOM_DEBUG function on top of __DEBUG_IMPL_FORMATTED?

Hm, I would like to have two levels of indirection:

  • You may just want to set a custom prefix, but not hardcode the print function -- which may want to modify independent of the prefix.
  • You may want to change the print format itself or provide a completely different debug implementation. So I concluded it would be useful to provide our two __DEBUG_IMPL_FORMATTED and __DEBUG_IMPL_PIECEWISE as a swap-in modular implementations. (these we can take out of the public docs IMO)
    • these two implementation are also modular too in that they give users more control over the file printf/fprintf/fputs actually write to. in fact, you can even have a custom print function as part of your project.

Taken together, you can define a new DEBUG/DEBUG_PUTS macro, either to something completely different, or use the existing __DEBUG_IMPL_... we provide, but perhaps with a different print function and/or arguments to that print function, say for stderr.

The DEBUG_ name itself i kinda don't like myself, but there's got to be a way to get a debug macro with a different debug prefix, without hardcoding the print function and/or arguments to it per file --- which you would need to do if you're forced to resort to __DEBUG_IMPL_... immediately.

Also, wouldn't it be the more likely usecase wanting to redirect debug logging from all files? Isn't it then a bit cumbersome to add a custom debug function to all files where ENABLE_DEBUG is 1?

You can do that by putting #define DEBUG_(...) SEND_NETWORK_OR_OTHER_DEBUG_PRINT_FORMAT(__VA_ARGS_) in a custom_debug.h and then do CFLAGS += -include custom_debug.h.

It feels a bit like this is exploding, should we maybe rather first merge here and then refine later? At least all of the proposed changes would not be source-breaking.

We can but thought it would be nice to think debug.h through before merging given the 'refactored' claim.

And perhaps DEBUG_PREFIX should be called DEBUG_UNIT analogous to LOG_UNIT, or we just use the existing LOG_UNIT such that when people switch to log.h, no renaming must be done, or rather we don't have to provide mutual fallbacks for log.h and debug.h unit prefixes.


What should come in a separate PR is some harmonisation of LOG_DEBUG for log_color and DEBUG, and some way of customising the log unit just like DEBUG_ can. Did that here: 27ea4c4.

#define LOG_UNIT "this.test"
#include "log.h"

#define ENABLE_DEBUG 1
#include "debug.h"

LOG_ERROR(format, value, string);
LOG_WARNING(format, value, string);
LOG_INFO(format, value, string);
LOG_DEBUG(format, value, string);
DEBUG(format, value, string);
Screenshot 2026-08-31 at 19 31 35

Comment thread core/lib/include/debug.h
#define DEBUG_(prefix, ...) \
do { \
if (ENABLE_DEBUG && __debug_sufficient_stack(true)) { \
if (strlen(prefix) > 0) { \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This can be a sizeof instead of a strlen if we proceed to use static string literal concatenation anway

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Not Used AI was stated to not be used in this PR/Issue Area: core Area: RIOT kernel. Handle PRs marked with this with care! Area: cpu Area: CPU/MCU ports Area: sys Area: System Area: tests Area: tests and testing framework Area: timers Area: timer subsystems CI: no fast fail don't abort PR build after first error CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ARM Platform: This PR/issue effects ARM-based platforms Process: missing approvals Integration Process: PR needs more ACKS (handled by action) Process: needs >1 ACK Integration Process: This PR requires more than one ACK State: needs rebase State: The codebase was changed since the creation of the PR, making a rebase necessary Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants