Log using multiple print callbacks

This commit is contained in:
fvanroie 2020-03-29 03:04:20 +02:00
parent 6f4b72d429
commit 35f371b306
4 changed files with 219 additions and 102 deletions

View File

@ -31,12 +31,29 @@ SOFTWARE.
#include "ArduinoLog.h"
void Logging::begin(int level, Print * logOutput, bool showLevel)
void Logging::begin(int level, bool showLevel)
{
#ifndef DISABLE_LOGGING
setLevel(level);
setShowLevel(showLevel);
_logOutput = logOutput;
#endif
}
void Logging::registerOutput(uint8_t slot, Print * logOutput, int level, bool showLevel)
{
#ifndef DISABLE_LOGGING
setLevel(level);
setShowLevel(showLevel);
if(slot >= 3) return;
_logOutput[slot] = logOutput;
#endif
}
void Logging::unregisterOutput(uint8_t slot)
{
#ifndef DISABLE_LOGGING
if(slot >= 3) return;
_logOutput[slot] = NULL;
#endif
}
@ -94,7 +111,7 @@ void Logging::print(Print * logOutput, const __FlashStringHelper * format, va_li
for(; c != 0; c = pgm_read_byte(p++)) {
if(c == '%') {
c = pgm_read_byte(p++);
printFormat(logOutput, c, &args);
printFormat(logOutput, c, (va_list *)&args);
} else {
logOutput->print(c);
}
@ -108,7 +125,7 @@ void Logging::print(Print * logOutput, const char * format, va_list args)
for(; *format != 0; ++format) {
if(*format == '%') {
++format;
printFormat(logOutput, *format, &args);
printFormat(logOutput, *format, (va_list *)&args);
} else {
//_logOutput->print(*format);
logOutput->print(*format);

View File

@ -22,7 +22,7 @@ Licensed under the MIT License <http://opensource.org/licenses/MIT>.
#include "WProgram.h"
#endif
#include "StringStream.h"
typedef void (*printfunction)(int level, Print *, String &);
typedef void (*printfunction)(int level, Print *);
//#include <stdint.h>
//#include <stddef.h>
@ -85,7 +85,7 @@ class Logging {
*/
Logging()
#ifndef DISABLE_LOGGING
: _level(LOG_LEVEL_SILENT), _showLevel(true), _logOutput(NULL)
: _level(LOG_LEVEL_SILENT), _showLevel(true)
#endif
{}
@ -99,7 +99,26 @@ class Logging {
* \return void
*
*/
void begin(int level, Print * output, bool showLevel = true);
void begin(int level, bool showLevel = true);
/**
* Register up to 3 printers to a certain slot
*
* \param slot - index of the printer to register.
* \param printer - place that logging output will be sent to.
* \return void
*
*/
void registerOutput(uint8_t slot, Print * logOutput, int level, bool showLevel);
/**
* Unregister the printer in a certain slot
*
* \param slot - index of the printer to register.
* \return void
*
*/
void unregisterOutput(uint8_t slot);
/**
* Set the log level.
@ -265,37 +284,29 @@ class Logging {
return;
}
String debugOutput((char *)0);
StringStream debugStream((String &)debugOutput);
debugOutput.reserve(4 * 128);
for(uint8_t i = 0; i < 3; i++) {
if(_logOutput[i] == NULL) continue;
if(_prefix != NULL) {
_prefix(level, &debugStream, debugOutput);
if(_prefix != NULL) {
_prefix(level, _logOutput[i]);
}
va_list args;
va_start(args, msg);
print(_logOutput[i], msg, args);
if(_suffix != NULL) {
_suffix(level, _logOutput[i]);
}
}
if(_showLevel) {
static const char levels[] = "FEWNTV";
debugStream.print(levels[level - 1]);
debugStream.print(": ");
}
va_list args;
va_start(args, msg);
print(&debugStream, msg, args);
if(_suffix != NULL) {
_suffix(level, &debugStream, debugOutput);
}
//_logOutput->print(debugOutput);
debugOutput.clear();
#endif
}
#ifndef DISABLE_LOGGING
int _level;
bool _showLevel;
Print * _logOutput;
Print * _logOutput[3];
printfunction _prefix = NULL;
printfunction _suffix = NULL;

View File

@ -73,6 +73,7 @@ bool debugSerialStarted = false;
#define TERM_COLOR_GRAY "\e[37m"
#define TERM_COLOR_RED "\e[91m"
#define TERM_COLOR_GREEN "\e[92m"
#define TERM_COLOR_ORANGE "\e[38;5;214m"
#define TERM_COLOR_YELLOW "\e[93m"
#define TERM_COLOR_BLUE "\e[94m"
#define TERM_COLOR_MAGENTA "\e[35m"
@ -191,7 +192,7 @@ void syslogSend(uint8_t priority, const char * debugText)
void debugSetup(JsonObject settings)
{
debugSetConfig(settings);
// debugSetConfig(settings);
#if HASP_USE_SYSLOG != 0
syslog = new Syslog(syslogClient, debugSyslogProtocol == 0 ? SYSLOG_PROTO_IETF : SYSLOG_PROTO_BSD);
@ -257,76 +258,121 @@ bool debugSetConfig(const JsonObject & settings)
return changed;
}
static void printTimestamp(int level, Print * _logOutput, String & debugOutput)
/*
void debugSendOuput(const char * buffer)
{
char buffer[128];
/* Print Current Time */
time_t rawtime;
struct tm * timeinfo;
// if(!time(nullptr)) return;
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(buffer, sizeof(buffer), ("[%b %d %H:%M:%S."), timeinfo);
if(debugSerialStarted) {
if(debugAnsiCodes) Serial.print(TERM_COLOR_CYAN);
Serial.print(buffer);
}
if(debugAnsiCodes) telnetPrint(TERM_COLOR_CYAN);
telnetPrint(buffer);
/* Print Memory Info */
snprintf(buffer, sizeof(buffer), PSTR("%8.3fs] %5u/%5u %2u | "), float(millis()) / 1000, halGetMaxFreeBlock(),
ESP.getFreeHeap(), halGetHeapFragmentation());
if(debugSerialStarted) {
if(debugAnsiCodes) Serial.print(buffer);
}
telnetPrint(buffer);
#if LV_MEM_CUSTOM == 0
/* lv_mem_monitor_t mem_mon;
lv_mem_monitor(&mem_mon);
debugTimeText += F("| ");
debugTimeText += mem_mon.used_pct;
debugTimeText += F("% ");
debugTimeText += mem_mon.free_biggest_size;
debugTimeText += F("b/");
debugTimeText += mem_mon.free_size;
debugTimeText += F("b ");
debugTimeText += (mem_mon.total_size - mem_mon.free_size);
debugTimeText += F("b | ");*/
#endif
switch(level) {
case LOG_LEVEL_FATAL:
case LOG_LEVEL_ERROR:
strcpy(buffer, TERM_COLOR_RED);
break;
case LOG_LEVEL_WARNING:
strcpy(buffer, TERM_COLOR_YELLOW);
break;
case LOG_LEVEL_NOTICE:
strcpy(buffer, TERM_COLOR_WHITE);
break;
case LOG_LEVEL_VERBOSE:
strcpy(buffer, TERM_COLOR_CYAN);
break;
case LOG_LEVEL_TRACE:
strcpy(buffer, TERM_COLOR_GRAY);
break;
default:
strcpy(buffer, TERM_COLOR_RESET);
}
if(debugSerialStarted) {
if(debugAnsiCodes) Serial.print(buffer);
}
if(debugSerialStarted) Serial.print(buffer);
telnetPrint(buffer);
}
static void printNewline(int level, Print * _logOutput, String & debugOutput)
void debugSendOuput(const __FlashStringHelper * txt)
{
if(debugSerialStarted) Serial.print(txt);
telnetPrint(txt);
}
*/
inline void debugSendAnsiCode(char * buffer, Print * _logOutput)
{
if(debugAnsiCodes) _logOutput->print(buffer);
}
static void debugPrintTimestamp(int level, Print * _logOutput)
{ /* Print Current Time */
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
debugSendAnsiCode(TERM_COLOR_CYAN, _logOutput);
// strftime(buffer, sizeof(buffer), ("[%b %d %H:%M:%S."), timeinfo);
// strftime(buffer, sizeof(buffer), ("[%H:%M:%S."), timeinfo);
if(timeinfo->tm_year >= 2020) {
char buffer[64];
strftime(buffer, sizeof(buffer), PSTR("[%b %d %H:%M:%S."), timeinfo); // Literal String
_logOutput->print(buffer);
_logOutput->printf(PSTR("%03u]"), millis() % 1000);
} else {
_logOutput->printf(PSTR("[%20.3f]"), (float)millis() / 1000);
}
}
static void debugPrintHaspMemory(int level, Print * _logOutput)
{
size_t maxfree = halGetMaxFreeBlock();
uint32_t totalfree = ESP.getFreeHeap();
uint8_t frag = halGetHeapFragmentation();
/* Print HASP Memory Info */
if(debugAnsiCodes) {
if(maxfree > (1024u * 5) && (totalfree > 1024u * 6) && (frag <= 10))
debugSendAnsiCode(TERM_COLOR_GREEN, _logOutput);
else if(maxfree > (1024u * 3) && (totalfree > 1024u * 5) && (frag <= 20))
debugSendAnsiCode(TERM_COLOR_ORANGE, _logOutput);
else
debugSendAnsiCode(TERM_COLOR_RED, _logOutput);
}
_logOutput->printf(PSTR("[%5u/%5u %2u] "), maxfree, totalfree, frag);
}
#if LV_MEM_CUSTOM == 0
static void debugPrintLvglMemory(int level, Print * _logOutput)
{
lv_mem_monitor_t mem_mon;
lv_mem_monitor(&mem_mon);
/* Print LVGL Memory Info */
if(debugAnsiCodes) {
if(mem_mon.free_biggest_size > (1024u * 2) && (mem_mon.free_size > 1024u * 2.5) && (mem_mon.frag_pct <= 10))
debugSendAnsiCode(TERM_COLOR_GREEN, _logOutput);
else if(mem_mon.free_biggest_size > (1024u * 1) && (mem_mon.free_size > 1024u * 1.5) &&
(mem_mon.frag_pct <= 25))
debugSendAnsiCode(TERM_COLOR_ORANGE, _logOutput);
else
debugSendAnsiCode(TERM_COLOR_RED, _logOutput);
}
_logOutput->printf(PSTR("[%5u/%5u %2u] "), mem_mon.free_biggest_size, mem_mon.free_size, mem_mon.frag_pct);
}
#endif
static void debugPrintPriority(int level, Print * _logOutput)
{
switch(level) {
case LOG_LEVEL_FATAL:
case LOG_LEVEL_ERROR:
debugSendAnsiCode(TERM_COLOR_RED, _logOutput);
break;
case LOG_LEVEL_WARNING:
debugSendAnsiCode(TERM_COLOR_YELLOW, _logOutput);
break;
case LOG_LEVEL_NOTICE:
debugSendAnsiCode(TERM_COLOR_WHITE, _logOutput);
break;
case LOG_LEVEL_VERBOSE:
debugSendAnsiCode(TERM_COLOR_CYAN, _logOutput);
break;
case LOG_LEVEL_TRACE:
debugSendAnsiCode(TERM_COLOR_GRAY, _logOutput);
break;
default:
debugSendAnsiCode(TERM_COLOR_RESET, _logOutput);
}
}
void debugPrintPrefix(int level, Print * _logOutput)
{
debugPrintTimestamp(level, _logOutput);
debugPrintHaspMemory(level, _logOutput);
#if LV_MEM_CUSTOM == 0
debugPrintLvglMemory(level, _logOutput);
#endif
debugPrintPriority(level, _logOutput);
}
void debugPrintSuffix(int level, Print * _logOutput)
{
/*
if(debugSerialStarted) {
Serial.print(debugOutput);
if(debugAnsiCodes) Serial.print(TERM_COLOR_RESET);
@ -334,37 +380,74 @@ static void printNewline(int level, Print * _logOutput, String & debugOutput)
if(debugAnsiCodes) Serial.print(TERM_COLOR_MAGENTA);
}
telnetPrint(debugOutput.c_str());
telnetPrint(debugOutput);
if(debugAnsiCodes) telnetPrint(TERM_COLOR_RESET);
telnetPrint("\r\n");
if(debugAnsiCodes) telnetPrint(TERM_COLOR_MAGENTA);
*/
syslogSend(level, debugOutput.c_str());
if(debugAnsiCodes)
_logOutput->println(TERM_COLOR_RESET);
else
_logOutput->println();
if(debugAnsiCodes) _logOutput->print(TERM_COLOR_MAGENTA);
// syslogSend(level, debugOutput);
}
void debugPreSetup(JsonObject settings)
{
// Link stream to debugOutput
// debugOutput.reserve(512);
Log.begin(LOG_LEVEL_VERBOSE, &Serial, true);
Log.setPrefix(printTimestamp); // Uncomment to get timestamps as prefix
Log.setSuffix(printNewline); // Uncomment to get newline as suffix
Log.begin(LOG_LEVEL_VERBOSE, true);
Log.setPrefix(debugPrintPrefix); // Uncomment to get timestamps as prefix
Log.setSuffix(debugPrintSuffix); // Uncomment to get newline as suffix
uint16_t baudrate = settings[FPSTR(F_CONFIG_BAUD)].as<uint16_t>();
if(baudrate > 0) {
Serial.begin(baudrate * 10); /* prepare for possible serial debug */
delay(10);
debugSerialStarted = true;
Log.registerOutput(0, &Serial, LOG_LEVEL_VERBOSE, true);
Log.trace(F("Serial started at %u baud"), baudrate * 10);
}
// Serial.begin(74880); /* prepare for possible serial debug */
// Serial.begin(115200);
}
#if LV_USE_LOG != 0
void debugLvgl(lv_log_level_t level, const char * file, uint32_t line, const char * funcname, const char * descr)
{
switch(level) {
case LV_LOG_LEVEL_TRACE:
Log.trace(descr);
// debugPrintPrefix(LOG_LEVEL_TRACE, NULL);
break;
case LV_LOG_LEVEL_WARN:
Log.warning(descr);
// debugPrintPrefix(LOG_LEVEL_WARNING, NULL);
break;
case LV_LOG_LEVEL_ERROR:
Log.error(descr);
// debugPrintPrefix(LOG_LEVEL_ERROR, NULL);
break;
default:
Log.notice(descr);
// debugPrintPrefix(LOG_LEVEL_WARNING, NULL);
}
/*
debugSendOuput(F("LVGL: "));
debugSendOuput(descr);
debugSendOuput(F("\r\n"));
syslogSend(level, descr);*/
}
#endif
void debugLoop()
{}
void printLocalTime()
/*void printLocalTime()
{
char buffer[128];
time_t rawtime;
@ -400,7 +483,7 @@ void printLocalTime()
}
}
#endif
}
}*/
void debugEverySecond()
{

View File

@ -2,6 +2,7 @@
#define HASP_DEBUG_H
#include "ArduinoJson.h"
#include "lvgl.h"
String debugHaspHeader(void);
@ -20,4 +21,9 @@ void syslogSend(uint8_t log, const char * debugText);
bool debugGetConfig(const JsonObject & settings);
bool debugSetConfig(const JsonObject & settings);
// void debugPrintPrefix(int level, Print * _logOutput);
// void debugPrintSuffix(int level, Print * _logOutput);
// void debugSendOuput(const char * buffer);
void debugLvgl(lv_log_level_t level, const char * file, uint32_t line, const char * funcname, const char * descr);
#endif