158 lines
3.8 KiB
C++
158 lines
3.8 KiB
C++
#pragma once
|
|
|
|
#include <atomic>
|
|
#include <functional> // std::function
|
|
#include <sstream> // std::stringstream (buffer for log entries)
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#ifndef LOG_USEMUTEX
|
|
#define LOG_USEMUTEX 0
|
|
#endif
|
|
|
|
#ifndef LOG_ENABLEQT
|
|
#define LOG_ENABLEQT 0
|
|
#endif
|
|
|
|
#if LOG_ENABLEQT == 1
|
|
#include <QMessageLogContext>
|
|
#include <QDebug>
|
|
#endif
|
|
|
|
#if LOG_ENABLEQT == 1
|
|
template<typename T>
|
|
QDebug operator<<(QDebug dbg, const T& str) {
|
|
std::ostringstream stream;
|
|
stream << str;
|
|
QString conv = QString::fromStdString(stream.str());
|
|
QDebugStateSaver saver(dbg);
|
|
dbg << conv;
|
|
return dbg;
|
|
}
|
|
|
|
/*
|
|
// string specialisation, not allowed, because multiple definitions of the same operator are not allowed
|
|
template<>
|
|
QDebug operator<<(QDebug dbg, const std::string& str) {
|
|
QDebugStateSaver saver(dbg);
|
|
QString conv = QString::fromStdString(str);
|
|
dbg << conv;
|
|
return dbg;
|
|
}
|
|
*/
|
|
#endif
|
|
|
|
namespace Log {
|
|
enum class Level { off = 0, fatal, error, warn, note, info, debug, trace };
|
|
|
|
#if LOG_ENABLEQT == 1
|
|
void qtMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message);
|
|
#endif
|
|
|
|
// set up the logger with a ConsoleOutput
|
|
void init();
|
|
// close all output streams
|
|
void stop();
|
|
|
|
void addLogfile(const std::string& filename, Level max, bool truncate = false);
|
|
void addLogfile(const std::string& filename, Level min, Level max, bool truncate = false);
|
|
|
|
void setConsoleLogLevel(Level lvl);
|
|
void setColoredOutput(bool enabled);
|
|
|
|
// Log entry that can be formed with various mixed data types
|
|
// by concatenation with the << operator
|
|
// Inspired from https://stackoverflow.com/a/8337882
|
|
class Entry {
|
|
private:
|
|
std::stringstream ss;
|
|
const Level lvl;
|
|
#if LOG_ENABLEQT == 1
|
|
const QMessageLogContext* context = nullptr;
|
|
Entry(Level lvl, const QMessageLogContext&);
|
|
friend void qtMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message);
|
|
#endif
|
|
|
|
void addMetadataHeader();
|
|
|
|
public:
|
|
explicit Entry(Level lvl);
|
|
Entry(const Entry&) = delete;
|
|
Entry& operator=(const Entry&) = delete;
|
|
Entry(Entry&&) = default;
|
|
Entry& operator=(Entry&&) = default;
|
|
~Entry();
|
|
|
|
Level getLevel() const {
|
|
return lvl;
|
|
}
|
|
|
|
#if LOG_ENABLEQT == 1
|
|
constexpr const QMessageLogContext* getContext() const {
|
|
return context;
|
|
}
|
|
#endif
|
|
|
|
using MetaFunction = std::function<std::ostream&(std::ostream&, const Entry&)>;
|
|
|
|
template <typename T> Entry& operator<<(T&& msg) {
|
|
ss << std::forward<T>(msg);
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
// class to automatically stop the logger on destruction
|
|
class Deleter {
|
|
public:
|
|
Deleter();
|
|
~Deleter();
|
|
private:
|
|
static std::atomic<uint32_t> refCount;
|
|
};
|
|
|
|
extern std::vector<Entry::MetaFunction> entryMetaFunctions;
|
|
|
|
std::ostream& defaultEntryMetaTime(std::ostream&, const Entry&);
|
|
std::ostream& defaultEntryMetaLevel(std::ostream&, const Entry&);
|
|
|
|
// custom io-manip
|
|
// FileSize is a iomanip to convert a filesize (fs) into a human readable format
|
|
class FileSize {
|
|
public:
|
|
explicit FileSize(uint64_t fs) : fs(fs) {}
|
|
FileSize(const FileSize&) = delete;
|
|
FileSize& operator=(const FileSize&) = delete;
|
|
operator std::string() const;
|
|
private:
|
|
uint64_t fs;
|
|
friend std::ostream& operator<<(std::ostream& str, const FileSize& fs);
|
|
};
|
|
|
|
struct PrintErrno {};
|
|
|
|
extern const PrintErrno err;
|
|
|
|
std::ostream& operator<<(std::ostream& str, const PrintErrno&);
|
|
|
|
std::ostream& operator<<(std::ostream& str, const FileSize& fs);
|
|
|
|
// copy Level values in Log namespace
|
|
constexpr Level off = Level::off;
|
|
constexpr Level fatal = Level::fatal;
|
|
constexpr Level error = Level::error;
|
|
constexpr Level warn = Level::warn;
|
|
constexpr Level note = Level::note;
|
|
constexpr Level info = Level::info;
|
|
constexpr Level debug = Level::debug;
|
|
constexpr Level trace = Level::trace;
|
|
|
|
// create Log lines (Entry objects) on using operator<< on Level values
|
|
template <typename T>
|
|
Entry operator<<(const Level lvl, T&& msg) {
|
|
Entry e{lvl};
|
|
e << std::forward<T>(msg);
|
|
return e;
|
|
}
|
|
|
|
} // namespace Log
|