MaCh3  2.4.2
Reference Guide
Macros | Functions
MaCh3Logger.h File Reference

MaCh3 Logging utilities built on top of SPDLOG. More...

#include <iostream>
#include <sstream>
#include <functional>
#include <string>
#include <exception>
#include "Manager/Core.h"
#include "spdlog/spdlog.h"
Include dependency graph for MaCh3Logger.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define MACH3LOG_TRACE   SPDLOG_TRACE
 
#define MACH3LOG_DEBUG   SPDLOG_DEBUG
 
#define MACH3LOG_INFO   SPDLOG_INFO
 
#define MACH3LOG_WARN   SPDLOG_WARN
 
#define MACH3LOG_ERROR   SPDLOG_ERROR
 
#define MACH3LOG_CRITICAL   SPDLOG_CRITICAL
 
#define MACH3LOG_OFF   SPDLOG_OFF
 

Functions

spdlog::level::level_enum get_default_log_level ()
 KS: Map string macro to spdlog::level enum. More...
 
void SetMaCh3LoggerFormat ()
 Set messaging format of the logger. More...
 
template<typename Func , typename LogFunc , typename... Args>
void LoggerPrint (const std::string &LibName, LogFunc logFunction, Func &&func, Args &&... args)
 KS: This is bit convoluted but this is to allow redirecting cout and errors from external library into MaCh3 logger format. More...
 

Detailed Description

MaCh3 Logging utilities built on top of SPDLOG.

KS: MaCh3 uses SPDLOG as its core logging backend, and this file serves as a wrapper around it. The MaCh3 logging system uses compile-time log level definitions to control which log statements are compiled. This ensures that, in default builds, MACH3LOG_DEBUG and lower levels are completely removed at compile time for maximal performance.

The available compile-time log level definitions can be found here.

Note
You can read more about SPDLOG formatting, levels, and configuration on the official SPDLOG wiki.
Author
Kamil Skwarczynski

Definition in file MaCh3Logger.h.

Macro Definition Documentation

◆ MACH3LOG_CRITICAL

#define MACH3LOG_CRITICAL   SPDLOG_CRITICAL

Definition at line 38 of file MaCh3Logger.h.

◆ MACH3LOG_DEBUG

#define MACH3LOG_DEBUG   SPDLOG_DEBUG

Definition at line 34 of file MaCh3Logger.h.

◆ MACH3LOG_ERROR

#define MACH3LOG_ERROR   SPDLOG_ERROR

Definition at line 37 of file MaCh3Logger.h.

◆ MACH3LOG_INFO

#define MACH3LOG_INFO   SPDLOG_INFO

Definition at line 35 of file MaCh3Logger.h.

◆ MACH3LOG_OFF

#define MACH3LOG_OFF   SPDLOG_OFF

Definition at line 39 of file MaCh3Logger.h.

◆ MACH3LOG_TRACE

#define MACH3LOG_TRACE   SPDLOG_TRACE

Definition at line 33 of file MaCh3Logger.h.

◆ MACH3LOG_WARN

#define MACH3LOG_WARN   SPDLOG_WARN

Definition at line 36 of file MaCh3Logger.h.

Function Documentation

◆ get_default_log_level()

spdlog::level::level_enum get_default_log_level ( )
inline

KS: Map string macro to spdlog::level enum.

Todo:
make constexpr with c++17

Definition at line 43 of file MaCh3Logger.h.

43  {
44  #ifdef SPDLOG_ACTIVE_LEVEL
45  switch (SPDLOG_ACTIVE_LEVEL) {
46  case SPDLOG_LEVEL_TRACE: return spdlog::level::trace;
47  case SPDLOG_LEVEL_DEBUG: return spdlog::level::debug;
48  case SPDLOG_LEVEL_INFO: return spdlog::level::info;
49  case SPDLOG_LEVEL_WARN: return spdlog::level::warn;
50  case SPDLOG_LEVEL_ERROR: return spdlog::level::err;
51  case SPDLOG_LEVEL_CRITICAL: return spdlog::level::critical;
52  case SPDLOG_LEVEL_OFF: return spdlog::level::off;
53  default: throw std::runtime_error("Unknown SPDLOG_ACTIVE_LEVEL");
54  }
55  #else
56  throw std::runtime_error("SPDLOG_ACTIVE_LEVEL is not defined");
57  #endif
58 }

◆ LoggerPrint()

template<typename Func , typename LogFunc , typename... Args>
void LoggerPrint ( const std::string &  LibName,
LogFunc  logFunction,
Func &&  func,
Args &&...  args 
)

KS: This is bit convoluted but this is to allow redirecting cout and errors from external library into MaCh3 logger format.

Template Parameters
FuncThe type of the function to be called, which outputs to stdout and stderr.
LogFuncThe type of the logging function, typically a lambda that formats and logs messages.
ArgsThe types of the arguments to be passed to func.
Parameters
LibNameThe name of the library or component from which the log message originates.
logFunctionThe lambda function responsible for formatting and logging messages. It should accept a single const std::string& parameter.
funcThe function to be called, whose output needs to be captured and logged.
argsThe arguments to be passed to func.
void ExampleFunc(int x, const std::string& str) {
std::cout << "Output from exampleFunc: " << x << ", " << str << "\n";
std::cerr << "Error from exampleFunc: " << x << ", " << str << "\n";
}
int main() {
LoggerPrint("ExampleLib", [](const std::string& message) { MACH3LOG_INFO("{}", message); },
static_cast<void(*)(int, const std::string&)>(ExampleFunc), 666, "Number of the BEAST");
return 0;
}
int main(int argc, char *argv[])
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35
void LoggerPrint(const std::string &LibName, LogFunc logFunction, Func &&func, Args &&... args)
KS: This is bit convoluted but this is to allow redirecting cout and errors from external library int...
Definition: MaCh3Logger.h:100
Note
second argument is lambda fucniton whih convers mach3 so template works, it is bit faff... This approach allows seamless integration of func into an existing logging mechanism without modifying func itself

Definition at line 100 of file MaCh3Logger.h.

101 {
102  // Create a stringstream to capture the output
103  std::stringstream sss_cout;
104  std::stringstream sss_cerr;
105 
106  // Save the original stream buffers
107  std::streambuf* coutBuf = nullptr;
108  std::streambuf* cerrBuf = nullptr;
109 
110  // This should be rare but in case buffers no longer exist ignore
111  if (std::cout.rdbuf() && std::cerr.rdbuf()) {
112  coutBuf = std::cout.rdbuf(); // Save original cout buffer
113  cerrBuf = std::cerr.rdbuf(); // Save original cerr buffer
114 
115  // Redirect std::cout and std::cerr to the stringstream buffer
116  std::cout.rdbuf(sss_cout.rdbuf());
117  std::cerr.rdbuf(sss_cerr.rdbuf());
118  }
119 
120  try {
121  // Call the provided function
122  func(std::forward<Args>(args)...);
123 
124  // Restore the original stream buffers
125  if (coutBuf) std::cout.rdbuf(coutBuf);
126  if (cerrBuf) std::cerr.rdbuf(cerrBuf);
127 
128  std::string line;
129  while (std::getline(sss_cout, line))
130  {
131  auto formatted_message = fmt::format("[{}] {}", LibName, line);
132  logFunction(formatted_message);
133  }
134  while (std::getline(sss_cerr, line))
135  {
136  auto formatted_message = fmt::format("[{}] {}", LibName, line);
137  logFunction(formatted_message);
138  }
139  } catch (std::runtime_error &err) {
140  // Restore the original buffers in case of an exception
141  std::cout.rdbuf(coutBuf);
142  std::cerr.rdbuf(cerrBuf);
143 
144  std::cout << "\nConsole cout output:" << std::endl;
145  std::cout << sss_cout.rdbuf()->str() << std::endl;
146 
147  std::cout << "\nConsole cerr output:" << std::endl;
148  std::cout << sss_cerr.rdbuf()->str() << std::endl;
149  throw;
150  }
151 }

◆ SetMaCh3LoggerFormat()

void SetMaCh3LoggerFormat ( )
inline

Set messaging format of the logger.

Definition at line 61 of file MaCh3Logger.h.

62 {
63  //KS: %H for hour, %M for minute, %S for second, [%s:%#] for class and line
64  //For documentation see https://github.com/gabime/spdlog/wiki/3.-Custom-formatting
65  #ifdef DEBUG
66  //spdlog::set_pattern("[%H:%M:%S][%s:%#][%^%l%$] %v");
67  spdlog::set_pattern("[%s:%#][%^%l%$] %v");
68  #else
69  //spdlog::set_pattern("[%H:%M:%S][%s][%^%l%$] %v");
70  spdlog::set_pattern("[%s][%^%l%$] %v");
71  #endif
72 
73  spdlog::set_level(get_default_log_level());
74 }
spdlog::level::level_enum get_default_log_level()
KS: Map string macro to spdlog::level enum.
Definition: MaCh3Logger.h:43