UTrace

Log and Trace for Embedded System

UTrace is a log and trace system for embedded Linux/Unix based system.

It started initially with the idea of using postprocessing to add the strings in the messages (logs or traces) to reduce the application binary size. With time, additional features like file transfer and syslog client was integrated.

How does it work?

The system is composed of a system daemon utraced which collects all binary data via a dedicated pipe. Currently there is only one pipe in which all clients dump messages, but the concept can be extended to use multile pipes or Unix domain sockets for IPC. External applications can use client libraries and API to log and trace using this system. Currently only C based projects are supported, but this can be extended. Tools are provided to generate the decoders at build time for applications. For each application an unique application id has to be provided (resolved at system build). All tools and parts come with manual pages. The concept can be ported on non-POSIX systems including RTOS.

Highlights

    • Based on binary decoders with tools to generate and transform decoders

    • Data serialization based on memory packing (alignment) per frame, each frame splited in the same amount of packets (build time configurable)

    • A binary trace entry is stored in a packet and the transfer is done once the frame is filled or explicitly flashed

    • File transfer support to the trace output

    • Data serialization for data flow out from the target

    • A simple syslog or text file monitor

Application integration

  1. Each application should define the message entries in an utracedefs.h file which shall be included in all units that use UTrace API for log and trace:

/* Application identification data */

#define UTRACEAPPID 0x01

#define UTRACEAPPNAME "utracetest"


/* Hash IDs go here */

enum {

THREAD_START = 1, THREAD_END, THREAD_LOOP_TID, THREAD_LOOP_DAT, UTRACEENTRYEND

};


/* Hash enties description goes into this table */

#ifdef UTRACEGEN

utentry_t utraceentries[UTRACEENTRYEND] = {

{ THREAD_START, UTRACEAPPID, "Test thread loop starts", "It markes the start of for loop for this test thread", UTRACEAPPNAME },

{ THREAD_END, UTRACEAPPID, "Test thread loop ends", "It markes the end of for loop for this test thread", UTRACEAPPNAME },

{ THREAD_LOOP_TID, UTRACEAPPID, "New loop for thread ID", " ", UTRACEAPPNAME },

{ THREAD_LOOP_DAT, UTRACEAPPID, "User data for current loop", "It is incremented with each loop", UTRACEAPPNAME },

{ UTRACEENTRYEND, UTRACEAPPID, "End message", "This message will not be used for decoding", UTRACEAPPNAME } };

#endif /* UTRACEGEN */

  1. Application can use the trace entry IDs with the trace API:

static void *

tracemsg(void *threadid)

{

...

utrace_add_info(THREAD_START, &tid, sizeof(tid), true);

for (i = 0; i < g_cntloop; i++)

{

...


utrace_add_info(THREAD_LOOP_TID, &tid, sizeof(tid), true);

usleep(g_cntusec);


utrace_add_info(THREAD_LOOP_DAT, &dat, sizeof(dat), true);

usleep(g_cntusec);

}

utrace_add_info(THREAD_END, &tid, sizeof(tid), true);

...

}


int

main(int argc, char *argv[])

{

...

utrace_init(UTRACEAPPID, (uint32_t)getpid());

utrace_settime_cb(&mytime);

utrace_open();

utrace_print("Program start threads");

....

/* start threads */

...

utrace_print("Program end");


utrace_close();

utrace_free();

...

}

Decoders

Decoders can be generated with utracegen tool with utracedefs.h as input:

$ utracegen -f ../application/src/utracedefs.h

The service daemon

The service which collects the traces is utraced and it needs as argument at least the output directory where to save the binary file. It has the option to limit the size of the output or to split the output in multiple files:

$ utraced --output ~/Work/utrace_output

Decoder tools and monitor

A decoder, utracedec and a live monitor application utracemon are provided with the UTrace system:

$ utracemon -a localhost -l ~/Work/utrace_decoders/decoders.list

UTRACEDEC version: v0.1

[ COUNT][TIMESTAMP ][APPID:INSTANCE][PAYLOAD ] APP NAME -> HEADLINE

[00000000][ 10:45:36 2020-01-31 ][fffe:000158e6][000000000000000000000000] utraced -> External monitor connected

[00000001][ 10:46:50 2020-01-31 ][fffd:00015bf2][TEXT ] utrace -> This is a message string example

[00000002][ 10:47:42 2020-01-31 ][fffd:00015c50][TEXT ] utrace -> A binary trace message follows

[00000003][ 10:48:35 2020-01-31 ][fffd:00015cb7][00000000000000000008a992] utrace -> ID 0462

[00000004][ 10:49:31 2020-01-31 ][fffd:00015d15][TEXT ] utrace -> A file transfer to traces will start

[00000005][ 10:49:49 2020-01-31 ][fffe:000041a7][FILE_TRANSFER_START ] FILE -> decoders.list;115

[00000006][ 10:49:49 2020-01-31 ][fffe:000041a7][FILE_TRANSFER_DATA ] FILE -> 572f363538303933712f73726573552f...

[00000007][ 10:49:49 2020-01-31 ][fffe:000041a7][FILE_TRANSFER_END ] FILE -> 115;0

[00000008][ 10:54:03 2020-01-31 ][fffe:000158e6][000000000000000000000000] utraced -> Terminate