The logging tool
The context
The common and most basic practice to understand the behavior of a software program is to print human-readable information about the code execution.
This is easy to do because most programming languages can do it natively. For instance in the C language, you have the printf primitives that format and output strings into a given stream.
Although it is easy to log information about the execution of an application, there are several issues about such a basic approach when logging a lot of information:
- It becomes really difficult to analyze.
- In our robotic context, we use a serial communication over a RS-232 bus to retrieve those informations from the embedded targets to our computers. This is a performance issue as RS-232 transmissions are not really fast.
- It takes a lot of program memory to embed all the message sentences.
Our solution
A possible solution to cope with the previous issues is to use a message library that describe a mapping between the human-readable messages and a given unique identifier.
This way the embedded software only send the identifiers to log a message. The amount of transferred byte is reduced to an identifier, the data coming with the message and an optional checksum.
This approach minimize the needed resources (memory and execution time) but output non-human-readable data. So an external tool is needed to convert the logged data into human readable entries using the message library. Such a tool should also ease the analysis of the resulting log by providing message filtering.
Following are two screen captures of our tooling. One is the message description editor and the other is the log viewer:
Tutorial
We will follow a small tutorial to illustrate our Eclipse based solution.
The goal is to refactor the following basic "Hello World" application from the printf approach to our library based logging approach.
/* * main.c * * Created on: 23 nov. 2010 * Author: Gonzague Reydet */ #include "HAL.h" #include <stdio.h> void helloWorld(void) { int i; for(i = 0; i < 1000; i++) { printf("[VERBOSE] I said hello %d times\n", i); // TODO Replace this } } int main(void) { initHAL(); printf("[INFO] Device successfully initialized...\n"); // TODO Replace this helloWorld(); printf("[ERROR] Application terminated!\n"); // TODO Replace this while(1); return 0; }
We will show the use of our tooling through three steps:
1. Message definition
First we need to define the available messages into our library.
Click here to see the screencast.
2. Generate code & modify the application
Once we defined the library, we can generate a header file that will provide a set of macros to ease the logging from the application code.
Click here to see the screencast.
3. Log display and analysis
As we modified our application to send binary messages based on our library, let see how to view and manage the resulting log:
Click here to see the screencast.
Installation
- Open your Eclipse environment
- Import the update-site bookmark file into the Eclipse update-site manager. Click here to download the bookmark file (login is required).
- Select the Yumantech update-site (login is required).
- Install the log tooling.
FAQ
- How to work with multiple message description files?
On the log description editor, you can import other message description files onto the current one. To do go to "Log Description Editor > Load Resource...", then load the other log description file and link the loaded descriptions on the "Included description" field of the editor.
- How to avoid having duplicate message identifiers on the message description files?
By default when you create a new message, the identifier will be initialized with the highest identifier value present on the description file incremented by one. Problems can come when you start populating multiple description files and then import one on the other. The best practice to avoid this kind of issue is to define a range for id values of each description file.
For example, if you have a Mainboard.logDescription file that will import a Bios.logDescription file, you should set the id of the first mainboard's message at a value higher than the number of messages that will contain the bios description file.
You can also use the renumerate feature to recalculate all messages identifiers of the current description file starting to the given ID.
