2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
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.
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.
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.
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.
32 #include "namespaces.hh"
36 //! The Logger class can be used to log messages in various ways.
40 Logger(string, int facility = LOG_DAEMON); //!< pass the identification you wish to appear in the log
42 //! The urgency of a log message
49 Warning = LOG_WARNING,
57 \param msg Message you wish to log
58 \param u Urgency of the message you wish to log
60 void log(const string& msg, Urgency u = Notice) noexcept;
62 void setFacility(int f)
66 } //!< Choose logging facility
71 } //!< set a syslog flag
72 void setName(const string&);
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);
78 void disableSyslog(bool d)
83 void setTimestamps(bool t)
88 void setPrefixed(bool p)
94 void toFile(const string& filename);
100 } //!< zero the flags
101 /** Use this to stream to your log, like this:
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)
108 Logger& operator<<(const char* s);
109 Logger& operator<<(const string& s); //!< log a string
110 Logger& operator<<(const DNSName&);
111 Logger& operator<<(const ComboAddress&); //!< log an address
112 Logger& operator<<(Urgency); //!< set the urgency, << style
114 Logger& operator<<(const QType& qtype)
116 *this << qtype.toString();
120 Logger& operator<<(const QClass& qclass)
122 *this << qclass.toString();
126 // Using const & since otherwise SyncRes:: values induce (illegal) copies
127 template <typename T>
128 Logger& operator<<(const T& i)
136 Logger& operator<<(std::ostream& (&)(std::ostream&)); //!< this is to recognise the endl, and to commit the log
147 PerThread& getPerThread();
150 static thread_local PerThread t_perThread;
155 Urgency consoleUrgency;
157 bool d_disableSyslog;
158 bool d_timestamps{true};
159 bool d_prefixed{false}; // this used to prefix the loglevel, but now causes formatting like structured logging
164 #define g_log getLogger()
169 #define DLOG(x) ((void)0)
172 // The types below are used by rec, which can log to g_log (general logging) or a string stream
173 // (trace-regexp). We pass an OptLog object to the code that should not know anything about this
174 // That code should then log using VLOG
180 // variant cannot hold references directly, use a wrapper
181 std::variant<std::reference_wrapper<Logger>, std::reference_wrapper<ostringstream>> v;
184 using OptLog = std::optional<LogVariant>;
186 void addTraceTS(const timeval& start, ostringstream& str);
188 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
189 #define VLOG(log, x) \
191 if (std::holds_alternative<std::reference_wrapper<Logger>>((log)->v)) { \
192 /* NOLINTNEXTLINE(bugprone-macro-parentheses) */ \
193 std::get<std::reference_wrapper<Logger>>((log)->v).get() << Logger::Warning << (log)->prefix << x; \
195 else if (std::holds_alternative<std::reference_wrapper<ostringstream>>((log)->v)) { \
196 addTraceTS((log)->start, std::get<std::reference_wrapper<ostringstream>>((log)->v).get()); \
197 /* NOLINTNEXTLINE(bugprone-macro-parentheses) */ \
198 std::get<std::reference_wrapper<ostringstream>>((log)->v).get() << (log)->prefix << x; \
202 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
203 #define VLOG_NO_PREFIX(log, x) \
205 if (std::holds_alternative<std::reference_wrapper<Logger>>((log)->v)) { \
206 /* NOLINTNEXTLINE(bugprone-macro-parentheses) */ \
207 std::get<std::reference_wrapper<Logger>>((log)->v).get() << Logger::Warning << x; \
209 else if (std::holds_alternative<std::reference_wrapper<ostringstream>>((log)->v)) { \
210 addTraceTS((log)->start, std::get<std::reference_wrapper<ostringstream>>((log)->v).get()); \
211 /* NOLINTNEXTLINE(bugprone-macro-parentheses) */ \
212 std::get<std::reference_wrapper<ostringstream>>((log)->v).get() << x; \