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