Coverage Report

Created: 2025-06-13 06:28

/src/pdns/pdns/logger.hh
Line
Count
Source (jump to first uncovered line)
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
#pragma once
23
24
#include <string>
25
#include <ctime>
26
#include <iostream>
27
#include <optional>
28
#include <sstream>
29
#include <variant>
30
#include <syslog.h>
31
32
#include "namespaces.hh"
33
#include "dnsname.hh"
34
#include "iputils.hh"
35
36
//! The Logger class can be used to log messages in various ways.
37
class Logger
38
{
39
public:
40
  Logger(string, int facility = LOG_DAEMON); //!< pass the identification you wish to appear in the log
41
42
  //! The urgency of a log message
43
  enum Urgency
44
  {
45
    All = 32767,
46
    Alert = LOG_ALERT,
47
    Critical = LOG_CRIT,
48
    Error = LOG_ERR,
49
    Warning = LOG_WARNING,
50
    Notice = LOG_NOTICE,
51
    Info = LOG_INFO,
52
    Debug = LOG_DEBUG,
53
    None = -1
54
  };
55
56
  /** Log a message.
57
      \param msg Message you wish to log
58
      \param u Urgency of the message you wish to log
59
  */
60
  void log(const string& msg, Urgency u = Notice) noexcept;
61
62
  void setFacility(int f)
63
0
  {
64
0
    d_facility = f;
65
0
    open();
66
0
  } //!< Choose logging facility
67
  void setFlag(int f)
68
0
  {
69
0
    flags |= f;
70
0
    open();
71
0
  } //!< set a syslog flag
72
  void setName(const string&);
73
74
  //! set lower limit of urgency needed for console display. Messages of this urgency, and higher, will be displayed
75
  void toConsole(Urgency);
76
  void setLoglevel(Urgency);
77
78
  void disableSyslog(bool d)
79
0
  {
80
0
    d_disableSyslog = d;
81
0
  }
82
83
  void setTimestamps(bool t)
84
0
  {
85
0
    d_timestamps = t;
86
0
  }
87
88
  void setPrefixed(bool p)
89
0
  {
90
0
    d_prefixed = p;
91
0
  }
92
93
  //! Log to a file.
94
  void toFile(const string& filename);
95
96
  void resetFlags()
97
0
  {
98
0
    flags = 0;
99
0
    open();
100
0
  } //!< zero the flags
101
  /** Use this to stream to your log, like this:
102
      \code
103
      g_log<<"This is an informational message"<<endl; // logged at default loglevel (Info)
104
      g_log<<Logger::Warning<<"Out of diskspace"<<endl; // Logged as a warning
105
      g_log<<"This is an informational message"<<endl; // logged AGAIN at default loglevel (Info)
106
      \endcode
107
  */
108
  Logger& operator<<(const char* s);
109
  Logger& operator<<(const string& s); //!< log a string
110
  Logger& operator<<(const DNSName&);
111
#if defined(PDNS_AUTH)
112
  Logger& operator<<(const ZoneName&);
113
#endif
114
  Logger& operator<<(const ComboAddress&); //!< log an address
115
  Logger& operator<<(const SockaddrWrapper&); //!< log an address
116
  Logger& operator<<(Urgency); //!< set the urgency, << style
117
118
  Logger& operator<<(const QType& qtype)
119
0
  {
120
0
    *this << qtype.toString();
121
0
    return *this;
122
0
  }
123
124
  Logger& operator<<(const QClass& qclass)
125
0
  {
126
0
    *this << qclass.toString();
127
0
    return *this;
128
0
  }
129
130
  // Using const & since otherwise SyncRes:: values induce (illegal) copies
131
  template <typename T>
132
  Logger& operator<<(const T& i)
133
0
  {
134
0
    ostringstream tmp;
135
0
    tmp << i;
136
0
    *this << tmp.str();
137
0
    return *this;
138
0
  }
139
140
  Logger& operator<<(std::ostream& (&)(std::ostream&)); //!< this is to recognise the endl, and to commit the log
141
142
private:
143
  struct PerThread
144
  {
145
    string d_output;
146
    Urgency d_urgency{Info};
147
  };
148
  PerThread& getPerThread();
149
  void open();
150
151
  static thread_local PerThread t_perThread;
152
  string name;
153
  int flags;
154
  int d_facility;
155
  Urgency d_loglevel{Logger::None};
156
  Urgency consoleUrgency{Error};
157
  bool opened{false};
158
  bool d_disableSyslog{false};
159
  bool d_timestamps{true};
160
  bool d_prefixed{false}; // this used to prefix the loglevel, but now causes formatting like structured logging
161
};
162
163
Logger& getLogger();
164
165
#define g_log getLogger()
166
167
#ifdef VERBOSELOG
168
#define DLOG(x) x
169
#else
170
#define DLOG(x) ((void)0)
171
#endif
172
173
// The types below are used by rec, which can log to g_log (general logging) or a string stream
174
// (trace-regexp). We pass an OptLog object to the code that should not know anything about this
175
// That code should then log using VLOG
176
177
struct LogVariant
178
{
179
  string prefix;
180
  timeval start;
181
  // variant cannot hold references directly, use a wrapper
182
  std::variant<std::reference_wrapper<Logger>, std::reference_wrapper<ostringstream>> v;
183
};
184
185
using OptLog = std::optional<LogVariant>;
186
187
void addTraceTS(const timeval& start, ostringstream& str);
188
189
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
190
#define VLOG(log, x)                                                                                     \
191
  if (log) {                                                                                             \
192
    if (std::holds_alternative<std::reference_wrapper<Logger>>((log)->v)) {                              \
193
      /* NOLINTNEXTLINE(bugprone-macro-parentheses) */                                                   \
194
      std::get<std::reference_wrapper<Logger>>((log)->v).get() << Logger::Warning << (log)->prefix << x; \
195
    }                                                                                                    \
196
    else if (std::holds_alternative<std::reference_wrapper<ostringstream>>((log)->v)) {                  \
197
      addTraceTS((log)->start, std::get<std::reference_wrapper<ostringstream>>((log)->v).get());         \
198
      /* NOLINTNEXTLINE(bugprone-macro-parentheses) */                                                   \
199
      std::get<std::reference_wrapper<ostringstream>>((log)->v).get() << (log)->prefix << x;             \
200
    }                                                                                                    \
201
  }
202
203
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
204
#define VLOG_NO_PREFIX(log, x)                                                                   \
205
  if (log) {                                                                                     \
206
    if (std::holds_alternative<std::reference_wrapper<Logger>>((log)->v)) {                      \
207
      /* NOLINTNEXTLINE(bugprone-macro-parentheses) */                                           \
208
      std::get<std::reference_wrapper<Logger>>((log)->v).get() << Logger::Warning << x;          \
209
    }                                                                                            \
210
    else if (std::holds_alternative<std::reference_wrapper<ostringstream>>((log)->v)) {          \
211
      addTraceTS((log)->start, std::get<std::reference_wrapper<ostringstream>>((log)->v).get()); \
212
      /* NOLINTNEXTLINE(bugprone-macro-parentheses) */                                           \
213
      std::get<std::reference_wrapper<ostringstream>>((log)->v).get() << x;                      \
214
    }                                                                                            \
215
  }