diff options
| author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-09-23 20:09:39 +0200 | 
|---|---|---|
| committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2019-09-23 20:09:39 +0200 | 
| commit | 09e514732788d821189c59ddc58e70355ba1a3cb (patch) | |
| tree | d7adc353859aa7f796bda0b4be12421f69779e73 /lib/Log.h | |
| parent | 56ad3cdd13e4c0078329ede5781bae4fcaeed569 (diff) | |
| download | ODR-SourceCompanion-09e514732788d821189c59ddc58e70355ba1a3cb.tar.gz ODR-SourceCompanion-09e514732788d821189c59ddc58e70355ba1a3cb.tar.bz2 ODR-SourceCompanion-09e514732788d821189c59ddc58e70355ba1a3cb.zip | |
Add code from common repository
Diffstat (limited to 'lib/Log.h')
| -rw-r--r-- | lib/Log.h | 200 | 
1 files changed, 200 insertions, 0 deletions
| diff --git a/lib/Log.h b/lib/Log.h new file mode 100644 index 0000000..f20e698 --- /dev/null +++ b/lib/Log.h @@ -0,0 +1,200 @@ +/* +   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +   Her Majesty the Queen in Right of Canada (Communications Research +   Center Canada) + +   Copyright (C) 2018 +   Matthias P. Braendli, matthias.braendli@mpb.li + +    http://www.opendigitalradio.org + */ +/* +   This file is part of the ODR-mmbTools. + +   This program is free software: you can redistribute it and/or modify +   it under the terms of the GNU General Public License as +   published by the Free Software Foundation, either version 3 of the +   License, or (at your option) any later version. + +   This program is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#ifdef HAVE_CONFIG_H +#   include "config.h" +#endif + +#include <syslog.h> +#include <cstdarg> +#include <cstdio> +#include <fstream> +#include <sstream> +#include <iostream> +#include <list> +#include <stdexcept> +#include <string> +#include <map> +#include <mutex> +#include <memory> +#include <thread> +#include "ThreadsafeQueue.h" + +#define SYSLOG_IDENT PACKAGE_NAME +#define SYSLOG_FACILITY LOG_LOCAL0 + +enum log_level_t {debug = 0, info, warn, error, alert, emerg, trace, discard}; + +static const std::string levels_as_str[] = +    { "     ", "     ", "WARN ", "ERROR", "ALERT", "EMERG", "TRACE", "-----"} ; + +/** Abstract class all backends must inherit from */ +class LogBackend { +    public: +        virtual ~LogBackend() {}; +        virtual void log(log_level_t level, const std::string& message) = 0; +        virtual std::string get_name() const = 0; +}; + +/** A Logging backend for Syslog */ +class LogToSyslog : public LogBackend { +    public: +        LogToSyslog() : name("SYSLOG") { +            openlog(SYSLOG_IDENT, LOG_PID, SYSLOG_FACILITY); +        } + +        virtual ~LogToSyslog() { +            closelog(); +        } + +        void log(log_level_t level, const std::string& message); + +        std::string get_name() const { return name; } + +    private: +        const std::string name; + +        LogToSyslog(const LogToSyslog& other) = delete; +        const LogToSyslog& operator=(const LogToSyslog& other) = delete; +}; + +class LogToFile : public LogBackend { +    public: +        LogToFile(const std::string& filename); +        void log(log_level_t level, const std::string& message); +        std::string get_name() const { return name; } + +    private: +        const std::string name; + +        struct FILEDeleter{ void operator()(FILE* fd){ if(fd) fclose(fd);}}; +        std::unique_ptr<FILE, FILEDeleter> log_file; + +        LogToFile(const LogToFile& other) = delete; +        const LogToFile& operator=(const LogToFile& other) = delete; +}; + +class LogTracer : public LogBackend { +    public: +        LogTracer(const std::string& filename); +        void log(log_level_t level, const std::string& message); +        std::string get_name() const { return name; } +    private: +        std::string name; +        uint64_t m_trace_micros_startup = 0; + +        struct FILEDeleter{ void operator()(FILE* fd){ if(fd) fclose(fd);}}; +        std::unique_ptr<FILE, FILEDeleter> m_trace_file; + +        LogTracer(const LogTracer& other) = delete; +        const LogTracer& operator=(const LogTracer& other) = delete; +}; + +class LogLine; + +struct log_message_t { +    log_message_t(log_level_t _level, std::string&& _message) : +        level(_level), +        message(move(_message)) {} + +    log_message_t() : +        level(debug), +        message("") {} + +    log_level_t level; +    std::string message; +}; + +class Logger { +    public: +        Logger(); +        Logger(const Logger& other) = delete; +        const Logger& operator=(const Logger& other) = delete; +        ~Logger(); + +        void register_backend(std::shared_ptr<LogBackend> backend); + +        /* Log the message to all backends */ +        void log(log_level_t level, const char* fmt, ...); + +        void logstr(log_level_t level, std::string&& message); + +        /* All logging IO is done in another thread */ +        void io_process(void); + +        /* Return a LogLine for the given level +         * so that you can write etiLog.level(info) << "stuff = " << 21 */ +        LogLine level(log_level_t level); + +    private: +        std::list<std::shared_ptr<LogBackend> > backends; + +        ThreadsafeQueue<log_message_t> m_message_queue; +        std::thread m_io_thread; +        std::mutex m_backend_mutex; +}; + +/* etiLog is a singleton used in all parts of the program to output log messages. + * It is constructed in Globals.cpp */ +extern Logger etiLog; + +// Accumulate a line of logs, using same syntax as stringstream +// The line is logged when the LogLine gets destroyed +class LogLine { +    public: +        LogLine(const LogLine& logline); +        const LogLine& operator=(const LogLine& other) = delete; +        LogLine(Logger* logger, log_level_t level) : +            logger_(logger) +        { +            level_ = level; +        } + +        // Push the new element into the stringstream +        template <typename T> +        LogLine& operator<<(T s) { +            if (level_ != discard) { +                os << s; +            } +            return *this; +        } + +        ~LogLine() +        { +            if (level_ != discard) { +                logger_->logstr(level_, os.str()); +            } +        } + +    private: +        std::ostringstream os; +        log_level_t level_; +        Logger* logger_; +}; + | 
