58 lines
2.0 KiB
C++
58 lines
2.0 KiB
C++
#pragma once
|
|
|
|
#include <ostream>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
namespace fgc {
|
|
|
|
enum class LogLevel { Trace = 0, Debug, Info, Warn, Error, Off };
|
|
|
|
// Minimal leveled, thread-safe logger. Each log line is assembled in a
|
|
// per-statement buffer and written atomically under a shared mutex, so lines
|
|
// from different threads never interleave. Level filtering is global.
|
|
//
|
|
// Usage: LOG_INFO << "starting, rate=" << rate;
|
|
// Lines at Warn/Error go to stderr; everything else to stdout.
|
|
class Logger {
|
|
public:
|
|
static void setLevel(LogLevel level);
|
|
static LogLevel level();
|
|
static bool enabled(LogLevel level);
|
|
|
|
// Parse "trace"|"debug"|"info"|"warn"|"error"|"off" (case-insensitive).
|
|
// Returns false (and leaves the level unchanged) on an unknown string.
|
|
static bool setLevelFromString(const std::string& s);
|
|
};
|
|
|
|
// RAII helper that buffers one log line and flushes it on commit().
|
|
// Designed to be driven by the LOG_* macros' for-loop guard.
|
|
class LogStream {
|
|
public:
|
|
explicit LogStream(LogLevel level);
|
|
bool pending() const { return enabled_ && !done_; }
|
|
void commit();
|
|
std::ostream& stream() { return buffer_; }
|
|
|
|
private:
|
|
LogLevel level_;
|
|
bool enabled_;
|
|
bool done_ = false;
|
|
std::ostringstream buffer_;
|
|
};
|
|
|
|
} // namespace fgc
|
|
|
|
// Brace-safe: the whole macro is a single for-statement, so it composes
|
|
// correctly inside if/else without dangling-else hazards, and the message
|
|
// expression is never evaluated when the level is disabled.
|
|
#define FGC_LOG_AT(level) \
|
|
for (::fgc::LogStream _fgc_ls(level); _fgc_ls.pending(); _fgc_ls.commit()) \
|
|
_fgc_ls.stream()
|
|
|
|
#define LOG_TRACE FGC_LOG_AT(::fgc::LogLevel::Trace)
|
|
#define LOG_DEBUG FGC_LOG_AT(::fgc::LogLevel::Debug)
|
|
#define LOG_INFO FGC_LOG_AT(::fgc::LogLevel::Info)
|
|
#define LOG_WARN FGC_LOG_AT(::fgc::LogLevel::Warn)
|
|
#define LOG_ERROR FGC_LOG_AT(::fgc::LogLevel::Error)
|