defmt icon indicating copy to clipboard operation
defmt copied to clipboard

decoder: add Frame::fragments() and Frame::display_fragments()

Open darkwater opened this issue 6 months ago • 4 comments

One cool possibility with defmt is a log viewer that can do more than just display static text, eg. change number representations on the fly. These two methods should make doing something like that a bit easier.

Copying from the docs I put on display_fragments():


Returns an iterator over the fragments of the message contained in this log frame.

Collecting this into a String will yield the same result as Self::display_message, but this iterator will yield interpolated fragments on their own. For example, the log:

defmt::info!("foo = {}, bar = {}", 1, 2);

Will yield the following strings:

vec!["foo = ", "1", ", bar = ", "2"]

Note that nested fragments will not yield separately:

defmt::info!("foo = {}", Foo { bar: 1 });

Will yield:

vec!["foo = ", "Foo { bar: 1 }"]

This iterator yields the same fragments as Self::fragments, so you can zip them together to get both representations.


This is quite limited in that it doesn't go into nested fragments, but could already enable some limited extra functionality with minimal effort.

Haven't tested on an actual project yet, intend to do that tomorrow.

darkwater avatar May 14 '25 18:05 darkwater

Oh, forgot to mention, yes I tested this by making a prototype structured logging forwarder, where you can:

defmt::info!("something happened action={}", "foo bar");

and it'll parse "action" as a key, and "foo bar" as a value, sort of escaping the value.

darkwater avatar May 24 '25 20:05 darkwater

Thank you for your proposed changes. I had a quick look and they seem OK to me, but I've asked my colleagues for a second opinion.

jonathanpallant avatar May 27 '25 14:05 jonathanpallant

A couple more observations on a second pass, but I checked the diff in detail with a better diff tool, and most of the 'changed' code is unchanged - it's just de-indented, slightly reformatted thanks to the extra width it now has, and a reference can be dropped because the new function is passed a reference. Functionally it appears to do the same thing as before.

jonathanpallant avatar May 28 '25 09:05 jonathanpallant

I just noticed that DisplayFragments and it's already existing neighbours eg. DisplayMessage aren't actually public, since mod frame isn't public. These types are returned by public methods on Frame, so would it be helpful to expose these types?

darkwater avatar Jun 06 '25 09:06 darkwater

I tried to make use of this in defmt-print, so it could print JSON containing an array of fragments rather than a single string, but ran into issues in how defmt-print actually uses the 'log' crate and so it's not very easy to print fragments. I think that crate needs some re-architecting.

Do you have an example of where you found this API useful?

jonathanpallant avatar Jul 11 '25 14:07 jonathanpallant

I'm currently using it for what I mentioned above:

defmt::info!("something happened action={}", "foo bar");

hooks into my structured logging, where action=foo bar is added as a structured field.

Another use case I'm thinking about is using defmt as a transport for a sort of memory inspection tool, eg.:

defmt::debug!("!buffer uart_rx {=[u8]}", &uart_rx_buf);

My toolchain could then pick up those messages and show buffer contents separately from logs. I already have a prototype that does something similar that currently just parses the [12, ab] strings.

darkwater avatar Jul 18 '25 11:07 darkwater

What tool did you use to collect and render the defmt logs?

jonathanpallant avatar Jul 18 '25 12:07 jonathanpallant

I’m using defmt-decoder directly in a bespoke toolchain for a closed source project, as well as on a server component to store logs in production.

darkwater avatar Jul 18 '25 15:07 darkwater

Fixed it

darkwater avatar Aug 29 '25 09:08 darkwater

Fixed CHANGELOG. If CI doesn't work, it just needs a rebase.

jonathanpallant avatar Nov 03 '25 16:11 jonathanpallant

I rebased and tried to push to your fork, @darkwater, but it said I didn't have permission.

jonathanpallant avatar Nov 05 '25 15:11 jonathanpallant

image

That is strange?

darkwater avatar Nov 05 '25 15:11 darkwater

Ah, no, I was holding it wrong.

jonathanpallant avatar Nov 05 '25 16:11 jonathanpallant