diff options
| author | Rutger Broekhoff | 2026-08-29 12:01:42 +0200 |
|---|---|---|
| committer | Rutger Broekhoff | 2026-08-29 12:01:42 +0200 |
| commit | 52b3cd46c76fd4be18aeb8422a08a073484b9fad (patch) | |
| tree | b4f23957c096e6bce5369bb94a4e8e23de71761a /server/src/log.cppm | |
| parent | 35878b76049b9c3e752480e9f298b7e2da6fdf1f (diff) | |
| download | routemon-52b3cd46c76fd4be18aeb8422a08a073484b9fad.tar.gz routemon-52b3cd46c76fd4be18aeb8422a08a073484b9fad.zip | |
More module implementation partition units
Diffstat (limited to 'server/src/log.cppm')
| -rw-r--r-- | server/src/log.cppm | 128 |
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 @@ | |||
| 1 | module; | ||
| 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 | |||
| 9 | export module routemon:log; | 1 | export module routemon:log; |
| 10 | 2 | ||
| 11 | import std; | 3 | import std; |
| @@ -19,35 +11,16 @@ export enum class level : std::uint8_t { | |||
| 19 | error, | 11 | error, |
| 20 | }; | 12 | }; |
| 21 | 13 | ||
| 22 | namespace { | ||
| 23 | |||
| 24 | auto 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 | |||
| 46 | export class sink | 14 | export 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 | |||
| 23 | public: | ||
| 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 | |||
| 78 | public: | ||
| 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 | ||
| 84 | export auto make_sink(level lvl) -> std::shared_ptr<sink> | 38 | export auto make_sink(level lvl) -> std::shared_ptr<sink>; |
| 85 | { | ||
| 86 | return std::shared_ptr<sink>{new sink{lvl}}; | ||
| 87 | } | ||
| 88 | 39 | ||
| 89 | export class logger | 40 | export 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 | ||
| 109 | public: | 49 | public: |
| 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 | ||