-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlog.h
119 lines (90 loc) · 2.49 KB
/
log.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#pragma once
#include <filesystem>
#include <fstream>
#include <functional>
#include <mutex>
#include <thread>
#include <optional>
#include <sstream>
#include <string_view>
namespace dechamps_cpplog {
class LogSink {
public:
virtual void Write(std::string_view) = 0;
};
class PreambleLogSink final : public LogSink {
public:
PreambleLogSink(LogSink& backend);
void Write(const std::string_view str) override { backend.Write(str); }
private:
LogSink& backend;
};
class StreamLogSink final : public LogSink {
public:
StreamLogSink(std::ostream& stream) : stream(stream) {}
void Write(const std::string_view str) override { stream << str << std::endl; }
private:
std::ostream& stream;
};
class FileLogSink final : public LogSink {
public:
struct Options final {
uintmax_t maxSizeBytes = 1 * 1024 * 1024 * 1024;
uintmax_t sizeCheckPeriodBytes = std::max<uintmax_t>(maxSizeBytes / 10, 1);
};
FileLogSink(std::filesystem::path path, Options options = {});
~FileLogSink();
void Write(const std::string_view str) override;
private:
void CheckSize();
const std::filesystem::path path;
Options options;
std::ofstream stream;
StreamLogSink stream_sink{ stream };
uintmax_t bytesRemainingUntilSizeCheck = (std::numeric_limits<uintmax_t>::max)();
};
class ThreadSafeLogSink final : public LogSink {
public:
ThreadSafeLogSink(LogSink& backend) : backend(backend) {}
void Write(std::string_view) override;
private:
std::mutex mutex;
LogSink& backend;
};
class AsyncLogSink final : public LogSink {
public:
AsyncLogSink(LogSink& backend) : backend(backend), thread([&] { RunThread(); }) {}
~AsyncLogSink();
void Write(std::string_view) override;
private:
void RunThread();
LogSink& backend;
std::mutex mutex;
std::condition_variable stateChanged;
std::vector<std::string> queue;
bool shutdown = false;
std::thread thread;
};
class Logger final
{
public:
struct Options final {
bool prependTime = true;
bool prependProcessId = true;
bool prependThreadId = true;
};
explicit Logger(LogSink* sink, const Options& options = {});
~Logger();
template <typename T> friend Logger&& operator<<(Logger&& lhs, T&& rhs) {
if (lhs.enabledState.has_value()) lhs.enabledState->stream << std::forward<T>(rhs);
return std::move(lhs);
}
private:
struct EnabledState {
explicit EnabledState(LogSink& sink) : sink(sink) {}
LogSink& sink;
std::stringstream stream;
};
std::optional<EnabledState> enabledState;
};
}