|
|
/**
* @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)
|