Skip to content

Commit

Permalink
COutputLogger: save log files including silented messages
Browse files Browse the repository at this point in the history
  • Loading branch information
jlblancoc committed Dec 7, 2020
1 parent cadb14e commit 9193ee1
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 63 deletions.
2 changes: 2 additions & 0 deletions doc/source/doxygen-docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
- New method mrpt::gui::CGlCanvasBase::CamaraParams::FromCamera()
- \ref mrpt_math_grp
- Added missing method for consistent API across pose classes: mrpt::math::TPose3D::operator+()
- \ref mrpt_system_grp
- mrpt::system::COutputLogger::writeLogToFile() will now save *all* messages despite the runtime log verbosity level.
- BUG FIXES:
- Fix error rendering an opengl scene with mrpt::opengl::CCamera objects in it.
- rawlog-edit silently ignored when more than one operation was requested.
Expand Down
45 changes: 27 additions & 18 deletions libs/system/include/mrpt/system/COutputLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@

#include <mrpt/core/Clock.h>
#include <mrpt/system/CTicTac.h>
#include <mrpt/system/os.h> // for console color constants
#include <mrpt/system/os.h> // for console color constants
#include <mrpt/typemeta/TEnumType.h>

#include <array>
#include <deque>
#include <functional>
#include <iosfwd>
#include <memory>
#include <mutex>
#include <optional>
#include <sstream>
#include <string>
#include <string_view>
Expand Down Expand Up @@ -97,13 +100,16 @@ using output_logger_callback_t = std::function<void(
*
* Default logging level is LVL_INFO.
*
* User may receive callbacks whenever a message is displayed to console by
* using
* logRegisterCallback(). If for some reason the callbacks are not needed any
* more,
* use logDeregisterCallback() to stop receiving calls. This mechanism is useful
* in case of showing the messages to a GUI, transmiting them to a remote
* machine, etc.
* User may receive callbacks whenever a message is *displayed to console* by
* using logRegisterCallback(). If for some reason the callbacks are not needed
* any more, use logDeregisterCallback() to stop receiving calls. This mechanism
* is useful in case of showing the messages to a GUI, transmiting them to a
* remote machine, etc.
*
* Note that only those messages whose "importance level" will be printed and
* sent to user callbacks. However, *all* messages will be stored and saved to a
* file with writeLogToFile() despite the current filter, if
* `logging_enable_keep_record` is set to `true` (Default=`false`).
*
* \note By default every logged message is going to be dumped to the standard
* output as well (if VerbosityLevel > m_min_verbosity_level). Unset \b
Expand Down Expand Up @@ -143,17 +149,18 @@ class COutputLogger
* a_logger.setLoggerName("logger_name");
* \endcode
*/
COutputLogger(std::string_view name);
/** Default class constructor. Name of the logger is initialized to "logStr"
*/
COutputLogger();
COutputLogger(std::string_view name) : m_logger_name(name) {}

/** Default constructor */
COutputLogger() = default;

/** virtual dtor (so we can derive classes from this one) */
virtual ~COutputLogger();

/** \brief Main method to add the specified message string to the logger.
* \sa logCond, logFmt */
void logStr(const VerbosityLevel level, std::string_view msg_str)
const; // renamed from log() to avoid conflict with math ::log()
const; // renamed from log() to avoid conflict with math ::log()

/** \brief Alternative logging method, which mimics the printf behavior.
*
Expand All @@ -171,7 +178,7 @@ class COutputLogger
* \sa logStr, logCond
*/
void logFmt(const VerbosityLevel level, const char* fmt, ...) const
MRPT_printf_format_check(3, 4); // arg 1=this
MRPT_printf_format_check(3, 4); // arg 1=this

/** \brief Log the given message only if the condition is satisfied.
*
Expand Down Expand Up @@ -220,7 +227,8 @@ class COutputLogger
*
* \sa dumpToConsole, getAsString
*/
void writeLogToFile(const std::string* fname_in = nullptr) const;
void writeLogToFile(
const std::optional<std::string> fname_in = std::nullopt) const;
/** \brief Dump the current contents of the COutputLogger instance in the
* terminal window.
*
Expand Down Expand Up @@ -307,9 +315,10 @@ class COutputLogger
std::string generateStringFromFormat(
std::string_view fmt, va_list argp) const;

std::string m_logger_name;
mutable std::deque<TMsg>
m_history; // deque is better than vector to avoid memory reallocs
std::string m_logger_name = "COutputLogger";
// deque is better than vector to avoid memory reallocs
mutable std::deque<TMsg> m_history;
std::shared_ptr<std::mutex> m_historyMtx = std::make_shared<std::mutex>();

std::deque<output_logger_callback_t> m_listCallbacks;
};
Expand Down
79 changes: 34 additions & 45 deletions libs/system/src/COutputLogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,21 @@
| Released under BSD License. See: https://www.mrpt.org/License |
+------------------------------------------------------------------------+ */

#include "system-precomp.h" // Precompiled headers

#include <mrpt/core/exceptions.h>
#include <mrpt/core/lock_helper.h>
#include <mrpt/system/COutputLogger.h>
#include <mrpt/system/datetime.h>
#include <cstdarg> // for logFmt
#include <mrpt/system/filesystem.h>

#include <cstdarg> // for logFmt
#include <cstdio>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>

#include "system-precomp.h" // Precompiled headers

#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN
#include <windows.h> // OutputDebugString() for MSVC
Expand All @@ -38,9 +41,9 @@ using namespace std;
static std::array<mrpt::system::TConsoleColor, NUMBER_OF_VERBOSITY_LEVELS>
logging_levels_to_colors = {
CONCOL_BLUE, // LVL_DEBUG
CONCOL_NORMAL, // LVL_INFO
CONCOL_NORMAL, // LVL_INFO
CONCOL_GREEN, // LVL_WARN
CONCOL_RED // LVL_ERROR
CONCOL_RED // LVL_ERROR
};

std::array<mrpt::system::TConsoleColor, NUMBER_OF_VERBOSITY_LEVELS>&
Expand All @@ -54,38 +57,35 @@ static std::array<std::string, NUMBER_OF_VERBOSITY_LEVELS>
"DEBUG", // LVL_DEBUG
"INFO ", // LVL_INFO
"WARN ", // LVL_WARN
"ERROR" // LVL_ERROR
"ERROR" // LVL_ERROR
};
std::array<std::string, NUMBER_OF_VERBOSITY_LEVELS>&
COutputLogger::logging_levels_to_names()
{
return ::logging_levels_to_names;
}

COutputLogger::COutputLogger(std::string_view name)
{
this->loggerReset();
m_logger_name = name;
}
COutputLogger::COutputLogger() { this->loggerReset(); }
COutputLogger::~COutputLogger() = default;

void COutputLogger::logStr(
const VerbosityLevel level, std::string_view msg_str) const
{
if (level < m_min_verbosity_level) return;

// initialize a TMsg object
TMsg msg(level, msg_str, *this);
if (logging_enable_keep_record) m_history.push_back(msg);
if (logging_enable_keep_record)
{
auto lck = mrpt::lockHelper(*m_historyMtx);
m_history.push_back(msg);
}

if (logging_enable_console_output)
if (level >= m_min_verbosity_level && logging_enable_console_output)
{
msg.dumpToConsole();
}

// User callbacks:
for (const auto& c : m_listCallbacks)
c(msg.body, msg.level, msg.name, msg.timestamp);
// User callbacks:
for (const auto& c : m_listCallbacks)
c(msg.body, msg.level, msg.name, msg.timestamp);
}
}

void COutputLogger::logFmt(
Expand Down Expand Up @@ -151,6 +151,7 @@ void COutputLogger::setVerbosityLevel(const VerbosityLevel level)
void COutputLogger::getLogAsString(std::string& fname) const
{
fname.clear();
auto lck = mrpt::lockHelper(*m_historyMtx);
for (const auto& h : m_history) fname += h.getAsString();
}
std::string COutputLogger::getLogAsString() const
Expand All @@ -159,23 +160,20 @@ std::string COutputLogger::getLogAsString() const
this->getLogAsString(str);
return str;
}
void COutputLogger::writeLogToFile(
const std::string* fname_in /* = nullptr */) const
void COutputLogger::writeLogToFile(const std::optional<string> fname_in) const
{
using namespace std::string_literals;

// determine the filename - open it
std::string fname;
if (fname_in)
{
fname = *fname_in;
}
else
{
fname = m_logger_name + ".log";
}
std::string fname =
fname_in.has_value()
? fname_in.value()
: mrpt::system::fileNameStripInvalidChars(m_logger_name) + ".log"s;

std::ofstream f(fname);
ASSERTMSG_(
f.is_open(), mrpt::format(
"[%s:] Could not open external file: %s",
"[%s] Could not open external file: %s",
m_logger_name.c_str(), fname.c_str()));

std::string hist_str;
Expand All @@ -186,11 +184,13 @@ void COutputLogger::writeLogToFile(

void COutputLogger::dumpLogToConsole() const
{
auto lck = mrpt::lockHelper(*m_historyMtx);
for (const auto& h : m_history) h.dumpToConsole();
}

std::string COutputLogger::getLoggerLastMsg() const
{
auto lck = mrpt::lockHelper(*m_historyMtx);
TMsg last_msg = m_history.back();
return last_msg.getAsString();
}
Expand All @@ -200,18 +200,7 @@ void COutputLogger::getLoggerLastMsg(std::string& msg_str) const
msg_str = this->getLoggerLastMsg();
}

void COutputLogger::loggerReset()
{
m_logger_name = "log"; // just the default name

m_history.clear();
logging_enable_console_output = true;
logging_enable_keep_record = false;

// set the minimum logging level allowed for printing. By default its
// LVL_INFO
m_min_verbosity_level = LVL_INFO;
}
void COutputLogger::loggerReset() { *this = COutputLogger(); }

// TMsg Struct
// ////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -254,7 +243,7 @@ void COutputLogger::TMsg::dumpToConsole() const
{
const std::string str = getAsString();

const bool dump_to_cerr = (level == LVL_ERROR); // LVL_ERROR alternatively
const bool dump_to_cerr = (level == LVL_ERROR); // LVL_ERROR alternatively
// dumped to stderr instead
// of stdout

Expand Down

0 comments on commit 9193ee1

Please sign in to comment.