Approach of a "logger" for Serial

Anyone knows the problem that you want to see "debug" on your serial console when testing out code. But Serial also slows your code!

I want to creat my own "serial logger" library and want to ask for ideas how to do this.

My idea would call functions like this:

log.print(var, level);
log.println(var,level);

log.println("this is a debug", LOG_INFO);
log.println("this is trace", LOG_TRACE);

I could define several levels (INFO, WARN, ERROR, DEBUG,TRACE. use a function declaration to select the level.

My biggest problems are:
1.) How can i make a function that works like Serial.print, with any variable? in Serial.print it doesnt matter if a uint8_t, uint32_t or string gets supplied?
2.) How can i completely disable the serial functions without compiler errors? i wanna do not init the Serial if a variable like "LOG = false". But usually if you put inits into a if the compiler gives you errors.

Thanks for your help.

I think you can do

#define log Serial

...R

sgt_johnny:
Serial also slows your code!

Not a lot, but how do you think your library can fix that?

This is what I use for some of my more advanced libraries. It uses macros and preprocessor directives, so it adds no runtime overhead when debugging is disabled.

By using a syntax similar to the C++ ostream functions, it works on the Arduino, as well as on my normal computer. This means that I can use exactly the same code for development, debugging and testing on my computer, as the actual code for the Arduino.

It uses templates to overload the << operator.

This file is included in all of my source files. Just comment out the second line to disable debugging.

Debug.h

---



```
#ifndef DEBUG
#define DEBUG_OUT Serial // Comment out this line to disable debugging

#ifdef DEBUG_OUT
#pragma message "Debugging enabled"
#ifndef ARDUINO
#undef DEBUG_OUT
#define DEBUG_OUT std::cout
#endif
#endif

#ifdef DEBUG_OUT
#define DEBUGcolor=#000000[/color] do { [/color]
 DEBUG_OUT << x; [/color]
} while color=#000000

#else
#define DEBUGcolor=#000000

#endif

#endif
```

|

This file is included in all files that use << to write to an output stream:

StreamPrinter.h


---



```
#ifndef StreamPrinter_h
#define StreamPrinter_h

#ifdef ARDUINO
#include <Arduino.h>
typedef Print &manipulator(Print &);

Print &endl(Print &printer) {
 printer.printlncolor=#000000[/color];
 printer.flushcolor=#000000[/color];
 return printer;
}

template <class T> inline Print &operator<<(Print &printer, const T printable) {
 printer.printcolor=#000000[/color];
 return printer;
}

template <> inline Print &operator<<(Print &printer, manipulator pf) {
 return pfcolor=#000000[/color];
}

#else // #ifndef ARDUINO

#include <iostream>
using std::endl;

#endif

#endif // StreamPrinter_h
```

|

This would be my main Arduino file:

debug.ino

---



```
#include "Debug.h"
#include "StreamPrinter.h"

void setupcolor=#000000[/color] {
 Serial.begincolor=#000000[/color];
 while color=#000000[/color];
}

void loopcolor=#000000[/color] {
 DEBUG("Hello, World!" << endl);
 DEBUG("This is a test" << ' ' << 1 << 2 << 3 << endl);
 delaycolor=#000000[/color];
}
```

|

This is a file that can be compiled using desktop g++, for example unit tests for your library:

debug.cpp

---



```
// g++ -Wall -std=c++11 -o debug debug.cpp

#ifndef ARDUINO

#include "Debug.h"
#include "StreamPrinter.h"

int maincolor=#000000[/color] {
 DEBUG("Hello, World!" << endl);
 DEBUG("This is a test" << ' ' << 1 << 2 << 3 << endl);
 return 0;
}

#endif
```

|

Pieter

You can indeed use preprocessor directives but even if you don't and just use a (const) variable to enable disable debugging the optimizer is smart enough to leave it out most of the time :slight_smile:

septillion:
Not a lot, but how do you think your library can fix that?

Alot! For example, if i print variables from loop for debug, the code will be the same slow as in productive version, since productive version has no serial port, but thinks there is one, if i comment out the serial the code is slower.

If the log library checks if debug is enabled, it will just return and do nothing if debug is disabled

By the way, you can add a global debug setting by editing your boards.txt file. For example, for the UNO (the lines I changed are in black):

boards.txt

---



```
menu.debug=Debug Output

##############################################################

uno.name=Arduino/Genuino Uno

uno.vid.0=0x2341
uno.pid.0=0x0043
uno.vid.1=0x2341
uno.pid.1=0x0001
uno.vid.2=0x2A03
uno.pid.2=0x0043
uno.vid.3=0x2341
uno.pid.3=0x0243

uno.upload.tool=avrdude
uno.upload.protocol=arduino
uno.upload.maximum_size=32256
uno.upload.maximum_data_size=2048
uno.upload.speed=115200

uno.bootloader.tool=avrdude
uno.bootloader.low_fuses=0xFF
uno.bootloader.high_fuses=0xDE
uno.bootloader.extended_fuses=0xFD
uno.bootloader.unlock_bits=0x3F
uno.bootloader.lock_bits=0x0F
uno.bootloader.file=optiboot/optiboot_atmega328.hex

uno.build.mcu=atmega328p
uno.build.f_cpu=16000000L
uno.build.board=AVR_UNO
uno.build.core=arduino
uno.build.variant=standard

# DEBUG OUTPUT
uno.menu.debug.None=None
uno.menu.debug.None.build.debug_output=
uno.menu.debug.Serial=Serial
uno.menu.debug.Serial.build.debug_output=-DDEBUG_OUT=Serial

uno.build.extra_flags={build.debug_output}
```

|

This will add a menu option in the Tools menu of the IDE to select the debug output (if any).

This can be very useful, in my opinion, so I wonder why it's not standard (like with the ESP8266 core, for example).

I threw together a small "library" that allows you to use debug-statements as above, and that can print things like the filename, line number and function name of where it is in your code.

Enjoy!