Files
MuditaOS/module-utils/log/Logger.cpp
Mateusz Grzegorzek def5dbcfa9 [EGD-5908] Fix bug in Logger + add log unit test
Because `vsnprintf` return value means:
"
The number of characters that would have been
written if n had been sufficiently large,
not counting the terminating null character.
If an encoding error occurs, a negative number is returned.
"

`Logger` crashed when log msg was longer than LOGGER_BUFFER_SIZE.
Checking `vsnprintf` return value solves this issue.
2021-03-05 09:06:39 +01:00

134 lines
4.2 KiB
C++

// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "critical.hpp"
#include <fstream>
#include <gsl/gsl_util>
#include "Logger.hpp"
#include "macros.h"
namespace Log
{
std::map<std::string, logger_level> Logger::filtered = {{"ApplicationManager", logger_level::LOGINFO},
{"TS0710Worker", logger_level::LOGINFO},
{"ServiceCellular", logger_level::LOGINFO},
{"ServiceAntenna", logger_level::LOGINFO},
{"ServiceFota", logger_level::LOGINFO},
{"ServiceEink", logger_level::LOGINFO},
{"ServiceDB", logger_level::LOGINFO},
{CRIT_STR, logger_level::LOGTRACE},
{IRQ_STR, logger_level::LOGTRACE}};
const char *Logger::level_names[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
void Logger::enableColors(bool enable)
{
if (!lock()) {
return;
}
auto _ = gsl::finally([this] { unlock(); });
if (enable) {
logColors = &logColorsOn;
}
else {
logColors = &logColorsOff;
}
}
auto Logger::GetLogLevel(const std::string &name) -> logger_level
{
return filtered[name];
}
bool Logger::lock()
{
if (isIRQ()) {
bt = cpp_freertos::CriticalSection::EnterFromISR();
}
else {
return mutex.Lock();
}
return true;
}
void Logger::init()
{
#if LOG_USE_COLOR == 1
enableColors(true);
#else
enableColors(false);
#endif
}
auto Logger::log(Device device, const char *fmt, va_list args) -> int
{
if (!lock()) {
return -1;
}
auto _ = gsl::finally([this] { unlock(); });
loggerBufferCurrentPos = 0;
const auto sizeLeft = loggerBufferSizeLeft();
const auto result = vsnprintf(&loggerBuffer[loggerBufferCurrentPos], sizeLeft, fmt, args);
if (0 <= result) {
const auto numOfBytesAddedToBuffer = static_cast<size_t>(result);
loggerBufferCurrentPos += (numOfBytesAddedToBuffer < sizeLeft) ? numOfBytesAddedToBuffer : (sizeLeft - 1);
logToDevice(device, loggerBuffer, loggerBufferCurrentPos);
return loggerBufferCurrentPos;
}
return -1;
}
auto Logger::log(
logger_level level, const char *file, int line, const char *function, const char *fmt, va_list args) -> int
{
if (!filterLogs(level)) {
return -1;
}
if (!lock()) {
return -1;
}
auto _ = gsl::finally([this] { unlock(); });
loggerBufferCurrentPos = 0;
addLogHeader(level, file, line, function);
const auto sizeLeft = loggerBufferSizeLeft();
const auto result = vsnprintf(&loggerBuffer[loggerBufferCurrentPos], sizeLeft, fmt, args);
if (0 <= result) {
const auto numOfBytesAddedToBuffer = static_cast<size_t>(result);
loggerBufferCurrentPos += (numOfBytesAddedToBuffer < sizeLeft) ? numOfBytesAddedToBuffer : (sizeLeft - 1);
loggerBufferCurrentPos += snprintf(&loggerBuffer[loggerBufferCurrentPos], loggerBufferSizeLeft(), "\n");
logToDevice(Device::DEFAULT, loggerBuffer, loggerBufferCurrentPos);
return loggerBufferCurrentPos;
}
return -1;
}
auto Logger::logAssert(const char *fmt, va_list args) -> int
{
if (!lock()) {
return -1;
}
auto _ = gsl::finally([this] { unlock(); });
logToDevice(fmt, args);
return loggerBufferCurrentPos;
}
void Logger::unlock()
{
if (isIRQ()) {
cpp_freertos::CriticalSection::ExitFromISR(bt);
}
else {
mutex.Unlock();
}
}
}; // namespace Log