Adds ASCII log option needed by portudino (#4443)

* Adds ASCII logs useful to portudino

Activates ASCII log option when stdout is not a terminal.  This is
generally the right thing to do; if not, the behavior can be
overridden in config.yaml using AsciiLogs under Logging.  The result
is reasonable system logs for portudino when running under systemd or
the like.

Signed-off-by: Christopher Hoover <ch@murgatroid.com>
This commit is contained in:
Christopher Hoover 2024-08-15 17:09:06 -07:00 committed by GitHub
parent d398419aef
commit 85176756ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 76 additions and 23 deletions

View File

@ -145,6 +145,7 @@ Input:
Logging: Logging:
LogLevel: info # debug, info, warn, error LogLevel: info # debug, info, warn, error
# TraceFile: /var/log/meshtasticd.json # TraceFile: /var/log/meshtasticd.json
# AsciiLogs: true # default if not specified is !isatty() on stdout
Webserver: Webserver:
# Port: 443 # Port for Webserver & Webservices # Port: 443 # Port for Webserver & Webservices
@ -152,4 +153,4 @@ Webserver:
General: General:
MaxNodes: 200 MaxNodes: 200
MaxMessageQueue: 100 MaxMessageQueue: 100

View File

@ -26,6 +26,10 @@ SOFTWARE.*/
#include "DebugConfiguration.h" #include "DebugConfiguration.h"
#ifdef ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h"
#endif
/// A C wrapper for LOG_DEBUG that can be used from arduino C libs that don't know about C++ or meshtastic /// A C wrapper for LOG_DEBUG that can be used from arduino C libs that don't know about C++ or meshtastic
extern "C" void logLegacy(const char *level, const char *fmt, ...) extern "C" void logLegacy(const char *level, const char *fmt, ...)
{ {
@ -139,6 +143,11 @@ bool Syslog::vlogf(uint16_t pri, const char *appName, const char *fmt, va_list a
inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *message) inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *message)
{ {
int result; int result;
#ifdef ARCH_PORTDUINO
bool utf = !settingsMap[ascii_logs];
#else
bool utf = true;
#endif
if (!this->_enabled) if (!this->_enabled)
return false; return false;
@ -169,7 +178,12 @@ inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *mess
this->_client->print(this->_deviceHostname); this->_client->print(this->_deviceHostname);
this->_client->print(' '); this->_client->print(' ');
this->_client->print(appName); this->_client->print(appName);
this->_client->print(F(" - - - \xEF\xBB\xBF")); this->_client->print(F(" - - - "));
if (utf) {
this->_client->print(F("\xEF\xBB\xBF"));
} else {
this->_client->print(F(" "));
}
this->_client->print(F("[")); this->_client->print(F("["));
this->_client->print(int(millis() / 1000)); this->_client->print(int(millis() / 1000));
this->_client->print(F("]: ")); this->_client->print(F("]: "));

View File

@ -55,6 +55,12 @@ size_t RedirectablePrint::vprintf(const char *logLevel, const char *format, va_l
static char printBuf[160]; static char printBuf[160];
#endif #endif
#ifdef ARCH_PORTDUINO
bool color = !settingsMap[ascii_logs];
#else
bool color = true;
#endif
va_copy(copy, arg); va_copy(copy, arg);
size_t len = vsnprintf(printBuf, sizeof(printBuf), format, copy); size_t len = vsnprintf(printBuf, sizeof(printBuf), format, copy);
va_end(copy); va_end(copy);
@ -70,7 +76,7 @@ size_t RedirectablePrint::vprintf(const char *logLevel, const char *format, va_l
if (!std::isprint(static_cast<unsigned char>(printBuf[f])) && printBuf[f] != '\n') if (!std::isprint(static_cast<unsigned char>(printBuf[f])) && printBuf[f] != '\n')
printBuf[f] = '#'; printBuf[f] = '#';
} }
if (logLevel != nullptr) { if (color && logLevel != nullptr) {
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
Print::write("\u001b[34m", 6); Print::write("\u001b[34m", 6);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0) if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
@ -81,7 +87,9 @@ size_t RedirectablePrint::vprintf(const char *logLevel, const char *format, va_l
Print::write("\u001b[31m", 6); Print::write("\u001b[31m", 6);
} }
len = Print::write(printBuf, len); len = Print::write(printBuf, len);
Print::write("\u001b[0m", 5); if (color && logLevel != nullptr) {
Print::write("\u001b[0m", 5);
}
return len; return len;
} }
@ -91,19 +99,27 @@ void RedirectablePrint::log_to_serial(const char *logLevel, const char *format,
// Cope with 0 len format strings, but look for new line terminator // Cope with 0 len format strings, but look for new line terminator
bool hasNewline = *format && format[strlen(format) - 1] == '\n'; bool hasNewline = *format && format[strlen(format) - 1] == '\n';
#ifdef ARCH_PORTDUINO
bool color = !settingsMap[ascii_logs];
#else
bool color = true;
#endif
// If we are the first message on a report, include the header // If we are the first message on a report, include the header
if (!isContinuationMessage) { if (!isContinuationMessage) {
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) if (color) {
Print::write("\u001b[34m", 6); if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0) Print::write("\u001b[34m", 6);
Print::write("\u001b[32m", 6); if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0) Print::write("\u001b[32m", 6);
Print::write("\u001b[33m", 6); if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0)
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0) Print::write("\u001b[33m", 6);
Print::write("\u001b[31m", 6); if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0)
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0) Print::write("\u001b[31m", 6);
Print::write("\u001b[35m", 6); if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0)
Print::write("\u001b[35m", 6);
}
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // display local time on logfile uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // display local time on logfile
if (rtc_sec > 0) { if (rtc_sec > 0) {
long hms = rtc_sec % SEC_PER_DAY; long hms = rtc_sec % SEC_PER_DAY;
@ -117,17 +133,33 @@ void RedirectablePrint::log_to_serial(const char *logLevel, const char *format,
int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN; int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
#ifdef ARCH_PORTDUINO #ifdef ARCH_PORTDUINO
::printf("%s \u001b[0m| %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000); ::printf("%s ", logLevel);
if (color) {
::printf("\u001b[0m");
}
::printf("| %02d:%02d:%02d %u ", hour, min, sec, millis() / 1000);
#else #else
printf("%s \u001b[0m| %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000); printf("%s ", logLevel);
if (color) {
printf("\u001b[0m");
}
printf("| %02d:%02d:%02d %u ", hour, min, sec, millis() / 1000);
#endif #endif
} else } else {
#ifdef ARCH_PORTDUINO #ifdef ARCH_PORTDUINO
::printf("%s \u001b[0m| ??:??:?? %u ", logLevel, millis() / 1000); ::printf("%s ", logLevel);
if (color) {
::printf("\u001b[0m");
}
::printf("| ??:??:?? %u ", millis() / 1000);
#else #else
printf("%s \u001b[0m| ??:??:?? %u ", logLevel, millis() / 1000); printf("%s ", logLevel);
if (color) {
printf("\u001b[0m");
}
printf("| ??:??:?? %u ", millis() / 1000);
#endif #endif
}
auto thread = concurrency::OSThread::currentThread; auto thread = concurrency::OSThread::currentThread;
if (thread) { if (thread) {
print("["); print("[");
@ -350,4 +382,4 @@ std::string RedirectablePrint::mt_sprintf(const std::string fmt_str, ...)
break; break;
} }
return std::string(formatted.get()); return std::string(formatted.get());
} }

View File

@ -99,6 +99,7 @@ void portduinoSetup()
settingsStrings[spidev] = ""; settingsStrings[spidev] = "";
settingsStrings[displayspidev] = ""; settingsStrings[displayspidev] = "";
settingsMap[spiSpeed] = 2000000; settingsMap[spiSpeed] = 2000000;
settingsMap[ascii_logs] = !isatty(1);
YAML::Node yamlConfig; YAML::Node yamlConfig;
@ -152,6 +153,10 @@ void portduinoSetup()
settingsMap[logoutputlevel] = level_error; settingsMap[logoutputlevel] = level_error;
} }
settingsStrings[traceFilename] = yamlConfig["Logging"]["TraceFile"].as<std::string>(""); settingsStrings[traceFilename] = yamlConfig["Logging"]["TraceFile"].as<std::string>("");
if (yamlConfig["Logging"]["AsciiLogs"]) {
// Default is !isatty(1) but can be set explicitly in config.yaml
settingsMap[ascii_logs] = yamlConfig["Logging"]["AsciiLogs"].as<bool>();
}
} }
if (yamlConfig["Lora"]) { if (yamlConfig["Lora"]) {
settingsMap[use_sx1262] = false; settingsMap[use_sx1262] = false;

View File

@ -53,7 +53,8 @@ enum configNames {
webserverport, webserverport,
webserverrootpath, webserverrootpath,
maxtophone, maxtophone,
maxnodes maxnodes,
ascii_logs
}; };
enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9488, hx8357d }; enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9488, hx8357d };
enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 }; enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 };
@ -62,4 +63,4 @@ enum { level_error, level_warn, level_info, level_debug, level_trace };
extern std::map<configNames, int> settingsMap; extern std::map<configNames, int> settingsMap;
extern std::map<configNames, std::string> settingsStrings; extern std::map<configNames, std::string> settingsStrings;
extern std::ofstream traceFile; extern std::ofstream traceFile;
int initGPIOPin(int pinNum, std::string gpioChipname); int initGPIOPin(int pinNum, std::string gpioChipname);