From 47c823ac611c54ae8ce3af2da40f9db0ec9b9195 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli (think)" Date: Thu, 13 Sep 2012 22:42:47 +0200 Subject: crc-dabmod: much cleaner logging implementation --- src/Log.h | 83 ++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 30 deletions(-) (limited to 'src/Log.h') diff --git a/src/Log.h b/src/Log.h index 617293f..fb1d2f6 100644 --- a/src/Log.h +++ b/src/Log.h @@ -30,14 +30,14 @@ # include "config.h" #endif -#include +#include #include -#include #include +#include +#include #include #include - -#include +#include #include "porting.h" @@ -46,12 +46,14 @@ enum log_level_t {debug = 0, info, warn, error, alert, emerg}; +/** Abstract class all backends must inherit from */ class LogBackend { public: - virtual void log(log_level_t level, const char* fmt, ...) = 0; + virtual void log(log_level_t level, std::string message) = 0; virtual std::string get_name() = 0; }; +/** A Logging backend for Syslog */ class LogToSyslog : public LogBackend { public: LogToSyslog() { @@ -63,8 +65,7 @@ class LogToSyslog : public LogBackend { closelog(); } - void log(log_level_t level, const char* fmt, ...) { - va_list arg_ptr; + void log(log_level_t level, std::string message) { int syslog_level = LOG_EMERG; switch (level) { @@ -76,9 +77,7 @@ class LogToSyslog : public LogBackend { case emerg: syslog_level = LOG_EMERG; break; } - va_start(arg_ptr, fmt); - syslog(level, fmt, arg_ptr); - va_end(arg_ptr); + syslog(level, SYSLOG_IDENT " %s", message.c_str()); } std::string get_name() { return name; }; @@ -91,55 +90,79 @@ class LogToFile : public LogBackend { public: LogToFile(std::string filename) { name = "FILE"; - log_filename = filename; - log_stream.open(filename.c_str(), std::ios::out | std::ios::app); - if (!log_stream.is_open()) { + log_file = fopen(filename.c_str(), "a"); + if (log_file == NULL) { throw new std::runtime_error("Cannot open log file !"); } } ~LogToFile() { - if (log_stream.is_open()) { - log_stream.close(); + if (log_file != NULL) { + fclose(log_file); } } - void log(log_level_t level, const char* fmt, ...) { - va_list arg_ptr; - char message[200]; + void log(log_level_t level, std::string message) { const char* log_level_text[] = {"DEBUG", "INFO", "WARN", "ERROR", "ALERT", "EMERG"}; - - va_start(arg_ptr, fmt); - snprintf(message, 200, fmt, arg_ptr); - log_stream << "CRC-DABMOD: " << log_level_text[(size_t)level] << ": " << message << std::endl; - log_stream.flush(); - va_end(arg_ptr); + + // fprintf is thread-safe + fprintf(log_file, "CRC-DABMOD: %s: %s\n", log_level_text[(size_t)level], message.c_str()); + fflush(log_file); } std::string get_name() { return name; }; private: std::string name; - std::string log_filename; - std::ofstream log_stream; + FILE* log_file; }; +class LogLine; + class Logger { public: Logger(); void register_backend(LogBackend* backend); - void log(log_level_t level, std::string message) { operator()(level, "%s", message.c_str()); } - void log(log_level_t level, const char* fmt, ...); - - void operator()(log_level_t level, const char* fmt, ...); + /* The LogLevel will call this when a line is complete */ + void log(log_level_t level, std::string message); + /* Return a LogLine for the given level */ + LogLine level(log_level_t level); + private: std::list backends; }; +// Accumulate a line of logs, using same syntax as stringstream +class LogLine { + public: + LogLine(const LogLine& logline); + LogLine(Logger* logger, log_level_t level) : + logger_(logger) + { + level_ = level; + } + + template + LogLine& operator<<(T s) { + os << s; + return *this; + } + + ~LogLine() + { + logger_->log(level_, os.str()); + } + + private: + std::ostringstream os; + log_level_t level_; + Logger* logger_; +}; + #endif -- cgit v1.2.3