Skip to content
Define log model -> Generate C++ API -> Use on AVR / STM32 / x86
Branch: master
Clone or download
svkapustin Move set-up of logger API generation to function
- Added target guards for boltalog-templates, boltalog-autogen in
Latest commit b9233ff May 16, 2019


Project's requirements:

  • Define a log event model of some application
  • Auto-generate C++ interface for logging
  • Support AVR / STM32 / x86 platforms


  • Improve program robustness through strongly-typed interface
  • Derive log analysis tools from the model
  • Documentat program's behaviour using event description
  • Reduce bugs through pre-defined interface/implementation templates
  • Reduce typing of similiar code

Table of Contents


The following are top-level dependencies. Depending on target platform additional tools may be required.
(See Example, stm32/CMakeLists.txt, avr/CMakeLists.txt)


Example log model and code generation is included as part of unit testing. Cmake build instructions are specified in test/CMakeLists.txt.


Event model is specified using JSON format:

'namespace': [ 'test', 'log' ],
'events': [
    'id':'4', 'name':'event4', 'level':'TRACE', 'doc':'Event4 description',
    'params': [
      { 'name':'u8', 'type':'uint8_t', 'doc':'u8 description' },
      { 'name':'d64', 'type':'int64_t' },
      { 'name':'u16', 'type':'uint16_t' },
      { 'name':'d32', 'type':'int32_t' },
      { 'name':'u32', 'type':'uint32_t' },
      { 'name':'d16', 'type':'int16_t' },
      { 'name':'u64', 'type':'uint64_t' },
      { 'name':'d8', 'type':'int8_t' },
      { 'name':'dbl', 'type':'double', 'doc':'dbl description' },
      { 'name':'str', 'type':'string', 'doc':'string description' },
      { 'name':'hx', 'type':'hex', 'doc':'hex description' },
      { 'name':'hx2', 'type':'hex' }

Array values from namespace are used to create a C++ namespace for the generated code. Array events contains event definitions. Each event is described using the following elements:

  • id - numeric event ID
  • name - event name that is used as part of API call, e.g. onEvent4(...)
  • level - default event log level. Levels range from TRACE to CRITICAL
  • doc - event or parameter description. These are added as comments to the code
  • params - the array contains parameter specifications. It may be empty. Each parameter is specified using:
    • name - parameter name
    • type - parameter type (signed/unsgined integers, double, string, hex binary representation)
    • doc - parameter description

Generated Code

By default, code generator produces three files:


The header file starts with a preample (header guard, platform-specific includes, namespace):

#ifndef _test_log_Logger_hpp_
#define _test_log_Logger_hpp_

#if defined(x86)
#include <memory>
namespace spdlog
class logger;
#elif defined(avr)
class HardwareSerial;
#endif // defined(x86)

Next follow event macros that first filter an event per its log level, and then invoke actual logging function implementation:

 * Event4 description
 * @param u8 u8 decription
 * ...
#define event4(u8, d64, u16, d32, u32, d16, u64, d8, dbl, str, str_size, hx, hx_size, hx2, hx2_size) \
  if (test::log::Logger::instance()->filter(4)) { \
    test::log::Logger::instance()->event4Impl( \
      u8,d64,u16,d32,u32,d16,u64,d8,dbl,str, str_size,hx, hx_size,hx2, hx2_size); \

The rest of the header contains remaining declarations:

class Logger {
  int event4Impl(...);


The file implementats functions declared in the header:

int Logger::event4Impl(...)
  int cx = snprintf(...);
  return log(cx, levels_[4], buff);

Generated C++ code outputs logs using CSV format, for example:


The python script prepends parameter name (defined in the model) to each field:

event4, u8:8, d64:64, u16:16, d32:32, u32:32, d16:16, u64:64, d8:8, dbl:8.800000, str:text, hx:74:65, hx2:74:65:78

Program Code

An example of program code that uses the generated API is provided in logger_test.cpp. Excerpt:

#include "logger.hpp"

TEST_F(LoggerTest, Output)
  event4(8, 64, 16, 32, 32, 16, 64, 8, 8.8, "text", 4, "text", 2, "text", 3);


Consider supporting our projects by contributing to their development. Learn more at

You can’t perform that action at this time.