2016-02-29 20:00:38 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include <mutex>
|
2016-04-13 20:37:39 +00:00
|
|
|
#include "tools.h"
|
2016-04-09 20:07:25 +00:00
|
|
|
#include "Timed.h"
|
2016-04-14 20:14:20 +00:00
|
|
|
#include "EnumConverter.h"
|
2016-02-29 20:00:38 +00:00
|
|
|
|
2016-04-13 20:37:39 +00:00
|
|
|
namespace logging {
|
2016-02-29 20:00:38 +00:00
|
|
|
|
2016-04-13 20:37:39 +00:00
|
|
|
enum class Level {
|
|
|
|
Trace,
|
|
|
|
Debug,
|
|
|
|
Info,
|
|
|
|
Warn,
|
|
|
|
Error,
|
|
|
|
Fatal,
|
|
|
|
EndSentinel
|
|
|
|
};
|
2016-02-29 20:00:38 +00:00
|
|
|
|
2016-04-14 20:14:20 +00:00
|
|
|
class LevelConverter : public EnumConverter<Level> {
|
|
|
|
public:
|
|
|
|
static LevelConverter& get();
|
|
|
|
protected:
|
|
|
|
std::string getTypeName() override;
|
|
|
|
member_data getMemberData() override;
|
|
|
|
};
|
2016-04-13 20:37:39 +00:00
|
|
|
|
2016-04-14 20:14:20 +00:00
|
|
|
std::ostream& operator<<(std::ostream& stream, Level value);
|
2016-04-13 20:37:39 +00:00
|
|
|
|
2016-04-14 20:14:20 +00:00
|
|
|
std::istream& operator>>(std::istream& stream, Level& value);
|
2016-04-13 20:37:39 +00:00
|
|
|
|
|
|
|
struct Entry {
|
|
|
|
Entry(Level level, const std::string& message);
|
|
|
|
|
|
|
|
time_t timestamp;
|
|
|
|
Level level;
|
|
|
|
std::string message;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Formatter {
|
|
|
|
public:
|
|
|
|
virtual ~Formatter() = default;
|
|
|
|
virtual std::string format(const Entry& entry) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class SimpleConsoleFormatter : public Formatter {
|
|
|
|
public:
|
|
|
|
std::string format(const Entry& entry) override;
|
|
|
|
};
|
|
|
|
|
|
|
|
class SimpleFileFormatter : public Formatter {
|
|
|
|
public:
|
|
|
|
std::string format(const Entry& entry) override;
|
|
|
|
private:
|
|
|
|
SimpleConsoleFormatter consoleFormatter;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Sink {
|
|
|
|
public:
|
|
|
|
virtual ~Sink() = default;
|
|
|
|
virtual void receive(const Entry& entry) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class LevelFilter : public Sink {
|
|
|
|
public:
|
|
|
|
LevelFilter(std::shared_ptr<Sink> innerSink, Level minLevel);
|
|
|
|
void receive(const Entry& entry) override;
|
|
|
|
private:
|
|
|
|
std::shared_ptr<Sink> innerSink;
|
|
|
|
Level minLevel;
|
|
|
|
};
|
|
|
|
|
|
|
|
class StreamSink : public Sink {
|
|
|
|
public:
|
|
|
|
StreamSink(std::shared_ptr<std::ostream> stream, std::shared_ptr<Formatter> formatter);
|
|
|
|
void receive(const Entry& entry) override;
|
|
|
|
private:
|
|
|
|
std::shared_ptr<std::ostream> stream;
|
|
|
|
std::shared_ptr<Formatter> formatter;
|
|
|
|
};
|
|
|
|
|
|
|
|
class StdErrSink : public StreamSink {
|
|
|
|
public:
|
|
|
|
explicit StdErrSink(std::shared_ptr<Formatter> formatter);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PausableSink : public Sink {
|
|
|
|
public:
|
|
|
|
explicit PausableSink(std::shared_ptr<Sink> innerSink);
|
|
|
|
void receive(const Entry& entry) override;
|
|
|
|
void pause();
|
|
|
|
void resume();
|
|
|
|
private:
|
|
|
|
std::shared_ptr<Sink> innerSink;
|
|
|
|
std::vector<Entry> buffer;
|
|
|
|
std::mutex mutex;
|
|
|
|
bool isPaused = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
void addSink(std::shared_ptr<Sink> sink);
|
|
|
|
|
|
|
|
void log(Level level, const std::string& message);
|
|
|
|
|
|
|
|
template <typename... Args>
|
|
|
|
void logFormat(Level level, fmt::CStringRef format, const Args&... args) {
|
|
|
|
log(level, fmt::format(format, args...));
|
|
|
|
}
|
|
|
|
|
|
|
|
#define LOG_WITH_LEVEL(levelName, levelEnum) \
|
|
|
|
inline void levelName(const std::string& message) { \
|
|
|
|
log(Level::levelEnum, message); \
|
|
|
|
} \
|
|
|
|
template <typename... Args> \
|
|
|
|
void levelName ## Format(fmt::CStringRef format, const Args&... args) { \
|
|
|
|
logFormat(Level::levelEnum, format, args...); \
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG_WITH_LEVEL(trace, Trace)
|
|
|
|
LOG_WITH_LEVEL(debug, Debug)
|
|
|
|
LOG_WITH_LEVEL(info, Info)
|
|
|
|
LOG_WITH_LEVEL(warn, Warn)
|
|
|
|
LOG_WITH_LEVEL(error, Error)
|
|
|
|
LOG_WITH_LEVEL(fatal, Fatal)
|
|
|
|
|
|
|
|
template<typename TValue>
|
|
|
|
void logTimedEvent(const std::string& eventName, const Timed<TValue> timedValue) {
|
2016-04-19 17:30:38 +00:00
|
|
|
debugFormat("##{0}[{1}-{2}]: {3}",
|
2016-04-13 20:37:39 +00:00
|
|
|
eventName, formatDuration(timedValue.getStart()), formatDuration(timedValue.getEnd()), timedValue.getValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename TValue>
|
|
|
|
void logTimedEvent(const std::string& eventName, const TimeRange& timeRange, const TValue& value) {
|
|
|
|
logTimedEvent(eventName, Timed<TValue>(timeRange, value));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename TValue>
|
|
|
|
void logTimedEvent(const std::string& eventName, centiseconds start, centiseconds end, const TValue& value) {
|
|
|
|
logTimedEvent(eventName, Timed<TValue>(start, end, value));
|
|
|
|
}
|
2016-04-09 20:07:25 +00:00
|
|
|
}
|