summaryrefslogtreecommitdiffstats
path: root/server/src/log.cppm
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/log.cppm')
-rw-r--r--server/src/log.cppm128
1 files changed, 20 insertions, 108 deletions
diff --git a/server/src/log.cppm b/server/src/log.cppm
index 97552b6..dc8c2e1 100644
--- a/server/src/log.cppm
+++ b/server/src/log.cppm
@@ -1,11 +1,3 @@
1module;
2
3// Seems like ADL for std::quoted is broken with
4// import std;
5// Might be because the _Quoted_string object is defined in
6// std::__detail, which is not exported by the module.
7#include <iomanip>
8
9export module routemon:log; 1export module routemon:log;
10 2
11import std; 3import std;
@@ -19,35 +11,16 @@ export enum class level : std::uint8_t {
19 error, 11 error,
20}; 12};
21 13
22namespace {
23
24auto operator<<(std::ostream& os, level lvl) -> std::ostream&
25{
26 switch (lvl)
27 {
28 case level::debug:
29 os << "dbg";
30 break;
31 case level::info:
32 os << "inf";
33 break;
34 case level::warn:
35 os << "wrn";
36 break;
37 case level::error:
38 os << "err";
39 break;
40 }
41 return os;
42}
43
44} // namespace
45
46export class sink 14export class sink
47{ 15{
48 std::atomic<enum level> lvl_; 16 std::atomic<enum level> lvl_;
49 std::ostream& os_ = std::cout; 17 std::ostream& os_ = std::cout;
50 18
19 explicit sink(level lvl);
20
21 friend auto make_sink(level lvl) -> std::shared_ptr<sink>;
22
23public:
51 struct tmp_message 24 struct tmp_message
52 { 25 {
53 level lvl; 26 level lvl;
@@ -56,35 +29,13 @@ export class sink
56 std::map<std::string, std::string> const& attrs; 29 std::map<std::string, std::string> const& attrs;
57 }; 30 };
58 31
59 auto write(tmp_message msg) -> void 32 [[nodiscard]] auto level() const -> enum level;
60 { 33 auto set_level(enum level lvl) -> void;
61 auto sos = std::osyncstream{os_};
62 sos << "[" << msg.lvl;
63 if (!msg.component.empty())
64 sos << " " << msg.component;
65 sos << "] " << msg.txt;
66 for (auto const& [k, v] : msg.attrs)
67 {
68 sos << " " << k << "=" << std::quoted(v);
69 }
70 sos << '\n';
71 }
72
73 explicit sink(level lvl) : lvl_{lvl} {}
74
75 friend auto make_sink(level lvl) -> std::shared_ptr<sink>;
76 friend class logger;
77
78public:
79 [[nodiscard]] auto level() const -> enum level { return lvl_; }
80 34
81 auto set_level(enum level lvl) -> void { lvl_ = lvl; } 35 auto write(tmp_message msg) -> void;
82}; 36};
83 37
84export auto make_sink(level lvl) -> std::shared_ptr<sink> 38export auto make_sink(level lvl) -> std::shared_ptr<sink>;
85{
86 return std::shared_ptr<sink>{new sink{lvl}};
87}
88 39
89export class logger 40export class logger
90{ 41{
@@ -92,79 +43,40 @@ export class logger
92 std::string component_; 43 std::string component_;
93 std::map<std::string, std::string> attrs_; 44 std::map<std::string, std::string> attrs_;
94 45
95 template <log::level lvl> 46 auto log_at(log::level lvl, std::string_view fmt, std::format_args args)
96 auto log_at(std::string_view fmt, std::format_args args) -> logger& 47 -> logger&;
97 {
98 if (sink_->level() <= lvl)
99 sink_->write(
100 sink::tmp_message{
101 .lvl = lvl,
102 .component = component_,
103 .txt = std::vformat(fmt, args),
104 .attrs = attrs_,
105 });
106 return *this;
107 }
108 48
109public: 49public:
110 explicit logger(std::shared_ptr<sink> const& sink) : sink_{sink} 50 explicit logger(std::shared_ptr<sink> const& sink);
111 {
112 if (!sink)
113 {
114 throw std::invalid_argument{"logger sink may not be null"};
115 }
116 }
117
118 [[nodiscard]] auto sub(std::string_view component) const -> logger
119 {
120 auto l = *this;
121 if (l.component_.empty())
122 {
123 l.component_ = component;
124 }
125 else
126 {
127 l.component_ += ".";
128 l.component_ += component;
129 }
130 return l;
131 }
132
133 [[nodiscard]] auto with(std::string const& k, std::string&& v) const -> logger
134 {
135 auto l = *this;
136 l.attrs_[k] = std::move(v);
137 return l;
138 }
139 51
52 [[nodiscard]] auto sub(std::string_view component) const -> logger;
53 [[nodiscard]] auto with(std::string const& k, std::string&& v) const
54 -> logger;
140 [[nodiscard]] auto with(std::string const& k, std::string_view v) const 55 [[nodiscard]] auto with(std::string const& k, std::string_view v) const
141 -> logger 56 -> logger;
142 {
143 return with(k, std::string{v});
144 }
145 57
146 template <class... Args> 58 template <class... Args>
147 auto debug(std::format_string<Args...> fmt, Args&&... args) -> logger& 59 auto debug(std::format_string<Args...> fmt, Args&&... args) -> logger&
148 { 60 {
149 return log_at<level::debug>(fmt.get(), std::make_format_args(args...)); 61 return log_at(level::debug, fmt.get(), std::make_format_args(args...));
150 } 62 }
151 63
152 template <class... Args> 64 template <class... Args>
153 auto info(std::format_string<Args...> fmt, Args&&... args) -> logger& 65 auto info(std::format_string<Args...> fmt, Args&&... args) -> logger&
154 { 66 {
155 return log_at<level::info>(fmt.get(), std::make_format_args(args...)); 67 return log_at(level::info, fmt.get(), std::make_format_args(args...));
156 } 68 }
157 69
158 template <class... Args> 70 template <class... Args>
159 auto warn(std::format_string<Args...> fmt, Args&&... args) -> logger& 71 auto warn(std::format_string<Args...> fmt, Args&&... args) -> logger&
160 { 72 {
161 return log_at<level::warn>(fmt.get(), std::make_format_args(args...)); 73 return log_at(level::warn, fmt.get(), std::make_format_args(args...));
162 } 74 }
163 75
164 template <class... Args> 76 template <class... Args>
165 auto error(std::format_string<Args...> fmt, Args&&... args) -> logger& 77 auto error(std::format_string<Args...> fmt, Args&&... args) -> logger&
166 { 78 {
167 return log_at<level::error>(fmt.get(), std::make_format_args(args...)); 79 return log_at(level::error, fmt.get(), std::make_format_args(args...));
168 } 80 }
169}; 81};
170 82