/src/pdns/pdns/dnsdistdist/logr.hh
Line | Count | Source |
1 | | /* |
2 | | * This file is part of PowerDNS or dnsdist. |
3 | | * Copyright -- PowerDNS.COM B.V. and its contributors |
4 | | * |
5 | | * This program is free software; you can redistribute it and/or modify |
6 | | * it under the terms of version 2 of the GNU General Public License as |
7 | | * published by the Free Software Foundation. |
8 | | * |
9 | | * In addition, for the avoidance of any doubt, permission is granted to |
10 | | * link this program with OpenSSL and to (re)distribute the binaries |
11 | | * produced as the result of such linking. |
12 | | * |
13 | | * This program is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU General Public License |
19 | | * along with this program; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
21 | | */ |
22 | | |
23 | | #pragma once |
24 | | |
25 | | #include <array> |
26 | | #include <cstdint> |
27 | | #include <string> |
28 | | #include <memory> |
29 | | #include <map> |
30 | | |
31 | | // Minimal logging API based on https://github.com/go-logr/logr |
32 | | |
33 | | namespace Logr |
34 | | { |
35 | | struct Loggable |
36 | | { |
37 | 0 | Loggable() = default; |
38 | | Loggable(const Loggable&) = delete; |
39 | | Loggable(Loggable&&) = delete; |
40 | | Loggable& operator=(const Loggable&) = delete; |
41 | | Loggable& operator=(Loggable&&) = delete; |
42 | 0 | virtual ~Loggable() = default; |
43 | | [[nodiscard]] virtual std::string to_string() const = 0; |
44 | | }; |
45 | | |
46 | | // In addition to level which specifies the amount of detail and is |
47 | | // structured so that a derived logger always has a higher level |
48 | | // than its parent we also have a priority/urgency field that maps |
49 | | // to the same field of the old logger which in turns has a direct |
50 | | // mapping to syslog priority. This is done to make it easier to |
51 | | // move step by step to structured logging. We consider both level |
52 | | // and priority to select which messages are logged, and a backend |
53 | | // can further use priority to pass to syslog. |
54 | | |
55 | | enum Priority : uint8_t |
56 | | { |
57 | | Absent = 0, |
58 | | Alert = 1, |
59 | | Critical = 2, |
60 | | Error = 3, |
61 | | Warning = 4, |
62 | | Notice = 5, |
63 | | Info = 6, |
64 | | Debug = 7 |
65 | | }; |
66 | | |
67 | | class Logger |
68 | | { |
69 | | public: |
70 | 0 | Logger() = default; |
71 | | Logger(const Logger&) = delete; |
72 | | Logger(Logger&&) = delete; |
73 | | Logger& operator=(const Logger&) = delete; |
74 | | Logger& operator=(Logger&&) = delete; |
75 | 0 | virtual ~Logger() = default; |
76 | | |
77 | | // Enabled tests whether this Logger is enabled. For example, commandline |
78 | | // flags might be used to set the logging verbosity and disable some info |
79 | | // logs. |
80 | | [[nodiscard]] virtual bool enabled(Priority) const = 0; |
81 | | |
82 | | static std::string toString(Priority arg) |
83 | 0 | { |
84 | 0 | const std::array<std::string, 8> names = {"Absent", "Alert", "Critical", "Error", "Warning", "Notice", "Info", "Debug"}; |
85 | 0 | auto prio = static_cast<unsigned int>(arg); |
86 | 0 | if (prio >= names.size()) { |
87 | 0 | return "?"; |
88 | 0 | } |
89 | 0 | return names.at(prio); |
90 | 0 | } |
91 | | // Info logs a non-error message with the given key/value pairs as context. |
92 | | // |
93 | | // The msg argument should be used to add some constant description to |
94 | | // the log line. The key/value pairs can then be used to add additional |
95 | | // variable information. The key/value pairs should alternate string |
96 | | // keys and arbitrary values. |
97 | | virtual void info(const std::string& msg) const = 0; |
98 | | virtual void info(Logr::Priority, const std::string& msg) const = 0; |
99 | | |
100 | | template <typename... Args> |
101 | | void info(const std::string& msg, const std::string& key, const Loggable& value, const Args&... args) const |
102 | | { |
103 | | auto logger = this->withValues(key, value, args...); |
104 | | logger->info(msg); |
105 | | } |
106 | | |
107 | | template <typename... Args> |
108 | | void info(Priority prio, const std::string& msg, const std::string& key, const Loggable& value, const Args&... args) const |
109 | | { |
110 | | auto logger = this->withValues(key, value, args...); |
111 | | logger->info(prio, msg); |
112 | | } |
113 | | |
114 | | // Error logs an error, with the given message and key/value pairs as context. |
115 | | // It functions similarly to calling Info with the "error" named value, but may |
116 | | // have unique behavior, and should be preferred for logging errors (see the |
117 | | // package documentations for more information). |
118 | | // |
119 | | // The msg field should be used to add context to any underlying error, |
120 | | // while the err field should be used to attach the actual error that |
121 | | // triggered this log line, if present. |
122 | | virtual void error(const std::string& err, const std::string& msg) const = 0; |
123 | | virtual void error(int err, const std::string& msg) const = 0; |
124 | | virtual void error(Logr::Priority, const std::string& err, const std::string& msg) const = 0; |
125 | | virtual void error(Logr::Priority, int err, const std::string& msg) const = 0; |
126 | | |
127 | | template <typename... Args> |
128 | | void error(const std::string& err, const std::string& msg, const std::string& key, const Loggable& value, const Args&... args) const |
129 | | { |
130 | | auto logger = this->withValues(key, value, args...); |
131 | | logger->error(Logr::Absent, err, msg); |
132 | | } |
133 | | |
134 | | template <typename... Args> |
135 | | void error(int err, const std::string& msg, const std::string& key, const Loggable& value, const Args&... args) const |
136 | | { |
137 | | auto logger = this->withValues(key, value, args...); |
138 | | logger->error(Logr::Absent, err, msg); |
139 | | } |
140 | | |
141 | | template <typename... Args> |
142 | | void error(Priority prio, const std::string& err, const std::string& msg, const std::string& key, const Loggable& value, const Args&... args) const |
143 | | { |
144 | | auto logger = this->withValues(key, value, args...); |
145 | | logger->error(prio, err, msg); |
146 | | } |
147 | | |
148 | | template <typename... Args> |
149 | | void error(Priority prio, int err, const std::string& msg, const std::string& key, const Loggable& value, const Args&... args) const |
150 | | { |
151 | | auto logger = this->withValues(key, value, args...); |
152 | | logger->error(prio, err, msg); |
153 | | } |
154 | | |
155 | | // V returns an Logger value for a specific verbosity level, relative to |
156 | | // this Logger. In other words, V values are additive. V higher verbosity |
157 | | // level means a log message is less important. It's illegal to pass a log |
158 | | // level less than zero. |
159 | | [[nodiscard]] virtual std::shared_ptr<Logger> v(size_t level) const = 0; |
160 | | |
161 | | template <typename... Args> |
162 | | std::shared_ptr<Logger> withValues(const std::string& key, const Loggable& value, const Args&... args) const |
163 | 0 | { |
164 | 0 | std::map<std::string, std::string> map = {}; |
165 | 0 | this->mapArguments(map, key, value, args...); |
166 | 0 | return this->withValues(map); |
167 | 0 | } Unexecuted instantiation: std::__1::shared_ptr<Logr::Logger> Logr::Logger::withValues<>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&) const Unexecuted instantiation: std::__1::shared_ptr<Logr::Logger> Logr::Logger::withValues<char [13], Logging::Loggable<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, char [16], Logging::Loggable<ComboAddress> >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&, char const (&) [13], Logging::Loggable<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, char const (&) [16], Logging::Loggable<ComboAddress> const&) const Unexecuted instantiation: std::__1::shared_ptr<Logr::Logger> Logr::Logger::withValues<char [18], Logging::Loggable<unsigned long> >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&, char const (&) [18], Logging::Loggable<unsigned long> const&) const Unexecuted instantiation: std::__1::shared_ptr<Logr::Logger> Logr::Logger::withValues<char [18], Logging::Loggable<unsigned short>, char [19], Logging::Loggable<unsigned short>, char [15], Logging::Loggable<ComboAddress>, char [20], Logging::Loggable<ComboAddress>, char [6], Logging::Loggable<dnsdist::Protocol>, char [16], Logging::Loggable<unsigned short>, char [19], Logging::Loggable<unsigned short> >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&, char const (&) [18], Logging::Loggable<unsigned short> const&, char const (&) [19], Logging::Loggable<unsigned short> const&, char const (&) [15], Logging::Loggable<ComboAddress> const&, char const (&) [20], Logging::Loggable<ComboAddress> const&, char const (&) [6], Logging::Loggable<dnsdist::Protocol> const&, char const (&) [16], Logging::Loggable<unsigned short> const&, char const (&) [19], Logging::Loggable<unsigned short> const&) const |
168 | | |
169 | | // WithValues adds some key-value pairs of context to a logger. |
170 | | // See Info for documentation on how key/value pairs work. |
171 | | [[nodiscard]] virtual std::shared_ptr<Logger> withValues(const std::map<std::string, std::string>& values) const = 0; |
172 | | |
173 | | // WithName adds a new element to the logger's name. |
174 | | // Successive calls with WithName continue to append |
175 | | // suffixes to the logger's name. It's strongly recommended |
176 | | // that name segments contain only letters, digits, and hyphens |
177 | | // (see the package documentation for more information). |
178 | | [[nodiscard]] virtual std::shared_ptr<Logger> withName(const std::string& name) const = 0; |
179 | | |
180 | | private: |
181 | | template <typename... Args> |
182 | | void mapArguments(std::map<std::string, std::string>& map, const std::string& key, const Loggable& value, const Args&... args) const |
183 | 0 | { |
184 | 0 | map.emplace(key, value.to_string()); |
185 | 0 | mapArguments(map, args...); |
186 | 0 | } Unexecuted instantiation: void Logr::Logger::mapArguments<>(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&) const Unexecuted instantiation: void Logr::Logger::mapArguments<char [13], Logging::Loggable<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, char [16], Logging::Loggable<ComboAddress> >(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&, char const (&) [13], Logging::Loggable<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&, char const (&) [16], Logging::Loggable<ComboAddress> const&) const Unexecuted instantiation: void Logr::Logger::mapArguments<char [16], Logging::Loggable<ComboAddress> >(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&, char const (&) [16], Logging::Loggable<ComboAddress> const&) const Unexecuted instantiation: void Logr::Logger::mapArguments<char [18], Logging::Loggable<unsigned long> >(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&, char const (&) [18], Logging::Loggable<unsigned long> const&) const Unexecuted instantiation: void Logr::Logger::mapArguments<char [18], Logging::Loggable<unsigned short>, char [19], Logging::Loggable<unsigned short>, char [15], Logging::Loggable<ComboAddress>, char [20], Logging::Loggable<ComboAddress>, char [6], Logging::Loggable<dnsdist::Protocol>, char [16], Logging::Loggable<unsigned short>, char [19], Logging::Loggable<unsigned short> >(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&, char const (&) [18], Logging::Loggable<unsigned short> const&, char const (&) [19], Logging::Loggable<unsigned short> const&, char const (&) [15], Logging::Loggable<ComboAddress> const&, char const (&) [20], Logging::Loggable<ComboAddress> const&, char const (&) [6], Logging::Loggable<dnsdist::Protocol> const&, char const (&) [16], Logging::Loggable<unsigned short> const&, char const (&) [19], Logging::Loggable<unsigned short> const&) const Unexecuted instantiation: void Logr::Logger::mapArguments<char [19], Logging::Loggable<unsigned short>, char [15], Logging::Loggable<ComboAddress>, char [20], Logging::Loggable<ComboAddress>, char [6], Logging::Loggable<dnsdist::Protocol>, char [16], Logging::Loggable<unsigned short>, char [19], Logging::Loggable<unsigned short> >(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&, char const (&) [19], Logging::Loggable<unsigned short> const&, char const (&) [15], Logging::Loggable<ComboAddress> const&, char const (&) [20], Logging::Loggable<ComboAddress> const&, char const (&) [6], Logging::Loggable<dnsdist::Protocol> const&, char const (&) [16], Logging::Loggable<unsigned short> const&, char const (&) [19], Logging::Loggable<unsigned short> const&) const Unexecuted instantiation: void Logr::Logger::mapArguments<char [15], Logging::Loggable<ComboAddress>, char [20], Logging::Loggable<ComboAddress>, char [6], Logging::Loggable<dnsdist::Protocol>, char [16], Logging::Loggable<unsigned short>, char [19], Logging::Loggable<unsigned short> >(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&, char const (&) [15], Logging::Loggable<ComboAddress> const&, char const (&) [20], Logging::Loggable<ComboAddress> const&, char const (&) [6], Logging::Loggable<dnsdist::Protocol> const&, char const (&) [16], Logging::Loggable<unsigned short> const&, char const (&) [19], Logging::Loggable<unsigned short> const&) const Unexecuted instantiation: void Logr::Logger::mapArguments<char [20], Logging::Loggable<ComboAddress>, char [6], Logging::Loggable<dnsdist::Protocol>, char [16], Logging::Loggable<unsigned short>, char [19], Logging::Loggable<unsigned short> >(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&, char const (&) [20], Logging::Loggable<ComboAddress> const&, char const (&) [6], Logging::Loggable<dnsdist::Protocol> const&, char const (&) [16], Logging::Loggable<unsigned short> const&, char const (&) [19], Logging::Loggable<unsigned short> const&) const Unexecuted instantiation: void Logr::Logger::mapArguments<char [6], Logging::Loggable<dnsdist::Protocol>, char [16], Logging::Loggable<unsigned short>, char [19], Logging::Loggable<unsigned short> >(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&, char const (&) [6], Logging::Loggable<dnsdist::Protocol> const&, char const (&) [16], Logging::Loggable<unsigned short> const&, char const (&) [19], Logging::Loggable<unsigned short> const&) const Unexecuted instantiation: void Logr::Logger::mapArguments<char [16], Logging::Loggable<unsigned short>, char [19], Logging::Loggable<unsigned short> >(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&, char const (&) [16], Logging::Loggable<unsigned short> const&, char const (&) [19], Logging::Loggable<unsigned short> const&) const Unexecuted instantiation: void Logr::Logger::mapArguments<char [19], Logging::Loggable<unsigned short> >(std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, Logr::Loggable const&, char const (&) [19], Logging::Loggable<unsigned short> const&) const |
187 | | |
188 | 0 | void mapArguments(std::map<std::string, std::string>& /* map */) const {} |
189 | | }; |
190 | | |
191 | | using log_t = const std::shared_ptr<Logger>&; |
192 | | } |