You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
4.9 KiB
165 lines
4.9 KiB
/**
|
|
* @file l3pp.h
|
|
* @author Gereon Kremer <gereon.kremer@cs.rwth-aachen.de>
|
|
* @author Harold Bruintjes <h.bruintjes@cs.rwth-aachen.de>
|
|
*
|
|
* The lightweight logging library for C++.
|
|
*
|
|
* This logging facility is fairly generic and is used as a simple and
|
|
* header-only alternative to more advanced solutions like log4cplus or
|
|
* boost::log.
|
|
*
|
|
* The basic components are Sinks, Formatters and Loggers.
|
|
*
|
|
* A Sink represents a logging output like a terminal or a log file.
|
|
* This implementation provides a FileSink and a StreamSink, but the basic
|
|
* Sink class can be extended as necessary.
|
|
*
|
|
* A Formatter is associated with a Sink and produces the actual string that is
|
|
* sent to the Sink.
|
|
* Usually, it adds auxiliary information like the current time, LogLevel and
|
|
* source location to the string logged by the user.
|
|
* The Formatter implements a reasonable default behavior for simple logging,
|
|
* but it can be subclassed and modified as necessary.
|
|
*
|
|
* The Logger class finally plugs all these components together.
|
|
* Individual loggers can log to one or more sinks (inheritable) and are
|
|
* associated with an (inheritable) log level.
|
|
*
|
|
* Initial configuration may look like this:
|
|
* @code{.cpp}
|
|
* l3pp::Logger::initialize();
|
|
* l3pp::SinkPtr sink = l3pp::StreamSink::create(std::clog);
|
|
* l3pp::Logger::getRootLogger()->addSink(sink);
|
|
* l3pp::Logger::getRootLogger()->setLevel(l3pp::LogLevel::INFO);
|
|
* @endcode
|
|
*
|
|
* Macro facilitate the usage:
|
|
* <ul>
|
|
* <li>`L3PP_LOG_<LVL>(logger, msg)` produces a normal log message where
|
|
* logger should be string identifying the logger (or a LogPtr) and msg is the
|
|
* message to be logged.</li>
|
|
* </ul>
|
|
* Any message (`msg`) can be an arbitrary expression that one would
|
|
* stream to an `std::ostream` like `stream << (msg);`. The default formatter
|
|
* adds newlines.
|
|
* Manipulators are generally supported. However, for performance avoid std::endl
|
|
* and use '\n' directly.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <chrono>
|
|
#include <memory>
|
|
|
|
namespace l3pp {
|
|
|
|
/**
|
|
* Indicated which log messages should be forwarded to some sink.
|
|
*
|
|
* All messages which have a level that is equal or greater than the specified
|
|
* value will be forwarded.
|
|
*/
|
|
enum class LogLevel {
|
|
/// Log messages used for tracing the program flow in detail.
|
|
TRACE,
|
|
/// Log messages used for debugging.
|
|
DEBUG,
|
|
/// Log messages used for information.
|
|
INFO,
|
|
/// Log messages used to warn about an undesired state.
|
|
WARN,
|
|
/// Log messages used for errors that can be handled.
|
|
ERR,
|
|
/// Log messages used for errors that lead to program termination.
|
|
FATAL,
|
|
/// Log no messages.
|
|
OFF,
|
|
/// Parent level
|
|
INHERIT,
|
|
/// Default log level.
|
|
DEFAULT = WARN,
|
|
/// All log messages.
|
|
ALL = TRACE
|
|
};
|
|
|
|
/**
|
|
* Streaming operator for LogLevel.
|
|
* @param os Output stream.
|
|
* @param level LogLevel.
|
|
* @return os.
|
|
*/
|
|
inline std::ostream& operator<<(std::ostream& os, LogLevel level);
|
|
|
|
class Logger;
|
|
|
|
/**
|
|
* Contextual information for a new log entry, contains such this as location,
|
|
* log info (level, logger) and the time of the event.
|
|
* A context will be created automatically by using the macros
|
|
*/
|
|
struct EntryContext {
|
|
// Program location
|
|
const char* filename;
|
|
size_t line;
|
|
const char* funcname;
|
|
|
|
// Time of entry
|
|
std::chrono::system_clock::time_point timestamp;
|
|
|
|
// Log event info
|
|
Logger const* logger;
|
|
LogLevel level;
|
|
|
|
EntryContext(const char* filename, size_t line, const char* funcname) :
|
|
filename(filename), line(line), funcname(funcname),
|
|
timestamp(std::chrono::system_clock::now()), logger(nullptr),
|
|
level(LogLevel::OFF)
|
|
{
|
|
}
|
|
|
|
EntryContext() :
|
|
filename(""), line(0), funcname(""),
|
|
timestamp(std::chrono::system_clock::now()), logger(nullptr),
|
|
level(LogLevel::OFF)
|
|
{
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#include "formatter.h"
|
|
#include "sink.h"
|
|
#include "logger.h"
|
|
|
|
#include "impl/logging.h"
|
|
#include "impl/logger.h"
|
|
#include "impl/formatter.h"
|
|
#include "impl/sink.h"
|
|
|
|
#ifdef _MSC_VER
|
|
#define __func__ __FUNCTION__
|
|
#endif
|
|
|
|
/// Create a record info.
|
|
#define __L3PP_LOG_RECORD l3pp::EntryContext(__FILE__, __LINE__, __func__)
|
|
/// Basic logging macro.
|
|
#define __L3PP_LOG(level, channel, expr) do { \
|
|
auto L3PP_channel = ::l3pp::Logger::getLogger(channel); \
|
|
if (L3PP_channel->getLevel() <= level) { \
|
|
L3PP_channel->log(level, __L3PP_LOG_RECORD) << expr; \
|
|
} \
|
|
} while(false)
|
|
|
|
/// Log with level TRACE.
|
|
#define L3PP_LOG_TRACE(channel, expr) __L3PP_LOG(::l3pp::LogLevel::TRACE, channel, expr)
|
|
/// Log with level DEBUG.
|
|
#define L3PP_LOG_DEBUG(channel, expr) __L3PP_LOG(::l3pp::LogLevel::DEBUG, channel, expr)
|
|
/// Log with level INFO.
|
|
#define L3PP_LOG_INFO(channel, expr) __L3PP_LOG(::l3pp::LogLevel::INFO, channel, expr)
|
|
/// Log with level WARN.
|
|
#define L3PP_LOG_WARN(channel, expr) __L3PP_LOG(::l3pp::LogLevel::WARN, channel, expr)
|
|
/// Log with level ERROR.
|
|
#define L3PP_LOG_ERROR(channel, expr) __L3PP_LOG(::l3pp::LogLevel::ERR, channel, expr)
|
|
/// Log with level FATAL.
|
|
#define L3PP_LOG_FATAL(channel, expr) __L3PP_LOG(::l3pp::LogLevel::FATAL, channel, expr)
|