/** * @file l3pp.h * @author Gereon Kremer * @author Harold Bruintjes * * 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: * * 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 #include 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)