Coverage Report

Created: 2026-03-07 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}