385 lines
9.7 KiB
C++
385 lines
9.7 KiB
C++
/*
|
|
_ ___ ___ _ _ ___ _ _ ___ _ ___ ___
|
|
/_\ | _ \ \| | | |_ _| \| |/ _ \| | / _ \ / __|
|
|
/ _ \| / |) | |_| || || .` | (_) | |_| (_) | (_ |
|
|
/_/ \_\_|_\___/ \___/|___|_|\_|\___/|____\___/ \___|
|
|
|
|
Log library for Arduino
|
|
version 1.1.1
|
|
https://github.com/thijse/Arduino-Log
|
|
|
|
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
|
|
|
*/
|
|
#pragma once
|
|
#include <inttypes.h>
|
|
#include <stdarg.h>
|
|
|
|
// Non standard: Arduino.h also chosen if ARDUINO is not defined. To facilitate use in non-Arduino test environments
|
|
#if ARDUINO < 100
|
|
#include "WProgram.h"
|
|
#else
|
|
#include "Arduino.h"
|
|
#endif
|
|
|
|
// PGM stubs to facilitate use in non-Arduino test environments
|
|
#ifndef PGM_P
|
|
#define PGM_P const char *
|
|
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
|
#define PSTR(str) (str)
|
|
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
|
|
#endif
|
|
typedef void (*printfunction)(Print*, int);
|
|
|
|
|
|
// *************************************************************************
|
|
// Uncomment line below to fully disable logging, and reduce project size
|
|
// ************************************************************************
|
|
//#define DISABLE_LOGGING
|
|
|
|
#define LOG_LEVEL_SILENT 0
|
|
#define LOG_LEVEL_FATAL 1
|
|
#define LOG_LEVEL_ERROR 2
|
|
#define LOG_LEVEL_WARNING 3
|
|
#define LOG_LEVEL_INFO 4
|
|
#define LOG_LEVEL_NOTICE 4
|
|
#define LOG_LEVEL_TRACE 5
|
|
#define LOG_LEVEL_VERBOSE 6
|
|
|
|
#define CR "\n"
|
|
#define LF "\r"
|
|
#define NL "\n\r"
|
|
#define LOGGING_VERSION 1_0_4
|
|
|
|
/**
|
|
* ArduinoLog is a minimalistic framework to help the programmer output log statements to an output of choice,
|
|
* fashioned after extensive logging libraries such as log4cpp ,log4j and log4net. In case of problems with an
|
|
* application, it is helpful to enable logging so that the problem can be located. ArduinoLog is designed so
|
|
* that log statements can remain in the code with minimal performance cost. In order to facilitate this the
|
|
* loglevel can be adjusted, and (if your code is completely tested) all logging code can be compiled out.
|
|
*
|
|
* ---- Wildcards
|
|
*
|
|
* %s display as string (char*)
|
|
* %S display as string from flash memory (__FlashStringHelper* or char[] PROGMEM)
|
|
* %c display as single character
|
|
* %C display as single character or as hexadecimal value (prefixed by `0x`) if not a printable character
|
|
* %d display as integer value
|
|
* %l display as long value
|
|
* %u display as unsigned long value
|
|
* %x display as hexadecimal value
|
|
* %X display as hexadecimal value prefixed by `0x` and leading zeros
|
|
* %b display as binary number
|
|
* %B display as binary number, prefixed by `0b`
|
|
* %t display as boolean value "t" or "f"
|
|
* %T display as boolean value "true" or "false"
|
|
* %D,%F display as double value
|
|
* %p display a printable object
|
|
*
|
|
* ---- Loglevels
|
|
*
|
|
* 0 - LOG_LEVEL_SILENT no output
|
|
* 1 - LOG_LEVEL_FATAL fatal errors
|
|
* 2 - LOG_LEVEL_ERROR all errors
|
|
* 3 - LOG_LEVEL_WARNING errors and warnings
|
|
* 4 - LOG_LEVEL_INFO errors, warnings and notices
|
|
* 4 - LOG_LEVEL_NOTICE Same as INFO, kept for backward compatibility
|
|
* 5 - LOG_LEVEL_TRACE errors, warnings, notices, traces
|
|
* 6 - LOG_LEVEL_VERBOSE all
|
|
*/
|
|
|
|
class Logging
|
|
{
|
|
public:
|
|
/**
|
|
* default Constructor
|
|
*/
|
|
Logging()
|
|
#ifndef DISABLE_LOGGING
|
|
: _level(LOG_LEVEL_SILENT),
|
|
_showLevel(true),
|
|
_logOutput(NULL)
|
|
#endif
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* Initializing, must be called as first. Note that if you use
|
|
* this variant of Init, you need to initialize the baud rate
|
|
* yourself, if printer happens to be a serial port.
|
|
*
|
|
* \param level - logging levels <= this will be logged.
|
|
* \param printer - place that logging output will be sent to.
|
|
* \return void
|
|
*
|
|
*/
|
|
void begin(int level, Print *output, bool showLevel = true);
|
|
|
|
/**
|
|
* Set the log level.
|
|
*
|
|
* \param level - The new log level.
|
|
* \return void
|
|
*/
|
|
void setLevel(int level);
|
|
|
|
/**
|
|
* Get the log level.
|
|
*
|
|
* \return The current log level.
|
|
*/
|
|
int getLevel() const;
|
|
|
|
/**
|
|
* Set whether to show the log level.
|
|
*
|
|
* \param showLevel - true if the log level should be shown for each log
|
|
* false otherwise.
|
|
* \return void
|
|
*/
|
|
void setShowLevel(bool showLevel);
|
|
|
|
/**
|
|
* Get whether the log level is shown during logging
|
|
*
|
|
* \return true if the log level is be shown for each log
|
|
* false otherwise.
|
|
*/
|
|
bool getShowLevel() const;
|
|
|
|
/**
|
|
* Sets a function to be called before each log command.
|
|
*
|
|
* \param f - The function to be called
|
|
* \return void
|
|
*/
|
|
void setPrefix(printfunction f);
|
|
|
|
/**
|
|
* clears prefix.
|
|
*
|
|
* \return void
|
|
*/
|
|
void clearPrefix();
|
|
|
|
/**
|
|
* Sets a function to be called after each log command.
|
|
*
|
|
* \param f - The function to be called
|
|
* \return void
|
|
*/
|
|
void setSuffix(printfunction f);
|
|
|
|
/**
|
|
* clears suffix.
|
|
*
|
|
* \return void
|
|
*/
|
|
void clearSuffix();
|
|
|
|
/**
|
|
* Output a fatal error message. Output message contains
|
|
* F: followed by original message
|
|
* Fatal error messages are printed out at
|
|
* loglevels >= LOG_LEVEL_FATAL
|
|
*
|
|
* \param msg format string to output
|
|
* \param ... any number of variables
|
|
* \return void
|
|
*/
|
|
template <class T, typename... Args> void fatal(T msg, Args... args){
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_FATAL, false, msg, args...);
|
|
#endif
|
|
}
|
|
|
|
template <class T, typename... Args> void fatalln(T msg, Args... args){
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_FATAL, true, msg, args...);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Output an error message. Output message contains
|
|
* E: followed by original message
|
|
* Error messages are printed out at
|
|
* loglevels >= LOG_LEVEL_ERROR
|
|
*
|
|
* \param msg format string to output
|
|
* \param ... any number of variables
|
|
* \return void
|
|
*/
|
|
template <class T, typename... Args> void error(T msg, Args... args){
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_ERROR, false, msg, args...);
|
|
#endif
|
|
}
|
|
|
|
template <class T, typename... Args> void errorln(T msg, Args... args){
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_ERROR, true, msg, args...);
|
|
#endif
|
|
}
|
|
/**
|
|
* Output a warning message. Output message contains
|
|
* W: followed by original message
|
|
* Warning messages are printed out at
|
|
* loglevels >= LOG_LEVEL_WARNING
|
|
*
|
|
* \param msg format string to output
|
|
* \param ... any number of variables
|
|
* \return void
|
|
*/
|
|
template <class T, typename... Args> void warning(T msg, Args...args){
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_WARNING, false, msg, args...);
|
|
#endif
|
|
}
|
|
|
|
template <class T, typename... Args> void warningln(T msg, Args...args){
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_WARNING, true, msg, args...);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Output a notice message. Output message contains
|
|
* N: followed by original message
|
|
* Notice messages are printed out at
|
|
* loglevels >= LOG_LEVEL_NOTICE
|
|
*
|
|
* \param msg format string to output
|
|
* \param ... any number of variables
|
|
* \return void
|
|
*/
|
|
template <class T, typename... Args> void notice(T msg, Args...args){
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_NOTICE, false, msg, args...);
|
|
#endif
|
|
}
|
|
|
|
template <class T, typename... Args> void noticeln(T msg, Args...args){
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_NOTICE, true, msg, args...);
|
|
#endif
|
|
}
|
|
|
|
template <class T, typename... Args> void info(T msg, Args...args) {
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_INFO, false, msg, args...);
|
|
#endif
|
|
}
|
|
|
|
template <class T, typename... Args> void infoln(T msg, Args...args) {
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_INFO, true, msg, args...);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Output a trace message. Output message contains
|
|
* N: followed by original message
|
|
* Trace messages are printed out at
|
|
* loglevels >= LOG_LEVEL_TRACE
|
|
*
|
|
* \param msg format string to output
|
|
* \param ... any number of variables
|
|
* \return void
|
|
*/
|
|
template <class T, typename... Args> void trace(T msg, Args... args){
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_TRACE, false, msg, args...);
|
|
#endif
|
|
}
|
|
|
|
template <class T, typename... Args> void traceln(T msg, Args... args){
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_TRACE, true, msg, args...);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Output a verbose message. Output message contains
|
|
* V: followed by original message
|
|
* Debug messages are printed out at
|
|
* loglevels >= LOG_LEVEL_VERBOSE
|
|
*
|
|
* \param msg format string to output
|
|
* \param ... any number of variables
|
|
* \return void
|
|
*/
|
|
template <class T, typename... Args> void verbose(T msg, Args... args){
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_VERBOSE, false, msg, args...);
|
|
#endif
|
|
}
|
|
|
|
template <class T, typename... Args> void verboseln(T msg, Args... args){
|
|
#ifndef DISABLE_LOGGING
|
|
printLevel(LOG_LEVEL_VERBOSE, true, msg, args...);
|
|
#endif
|
|
}
|
|
|
|
private:
|
|
void print(const char *format, va_list args);
|
|
|
|
void print(const __FlashStringHelper *format, va_list args);
|
|
|
|
void print(const Printable& obj, va_list args)
|
|
{
|
|
_logOutput->print(obj);
|
|
}
|
|
|
|
void printFormat(const char format, va_list *args);
|
|
|
|
template <class T> void printLevel(int level, bool cr, T msg, ...)
|
|
{
|
|
#ifndef DISABLE_LOGGING
|
|
if (level > _level)
|
|
{
|
|
return;
|
|
}
|
|
if (level < LOG_LEVEL_SILENT)
|
|
{
|
|
level = LOG_LEVEL_SILENT;
|
|
}
|
|
|
|
|
|
if (_prefix != NULL)
|
|
{
|
|
_prefix(_logOutput, level);
|
|
}
|
|
|
|
if (_showLevel) {
|
|
static const char levels[] = "FEWITV";
|
|
_logOutput->print(levels[level - 1]);
|
|
_logOutput->print(": ");
|
|
}
|
|
|
|
va_list args;
|
|
va_start(args, msg);
|
|
print(msg, args);
|
|
|
|
if(_suffix != NULL)
|
|
{
|
|
_suffix(_logOutput, level);
|
|
}
|
|
if (cr)
|
|
{
|
|
_logOutput->print(CR);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifndef DISABLE_LOGGING
|
|
int _level;
|
|
bool _showLevel;
|
|
Print* _logOutput;
|
|
|
|
printfunction _prefix = NULL;
|
|
printfunction _suffix = NULL;
|
|
#endif
|
|
};
|
|
|
|
extern Logging Log; |