]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/logger.cc
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.
36 #include "namespaces.hh"
38 thread_local
Logger::PerThread
Logger::t_perThread
;
42 /* Since the Logger can be called very early, we need to make sure
43 that the relevant parts are initialized no matter what, which is tricky
44 because we can't easily control the initialization order, especially with
46 t_perThread is thread_local, so it will be initialized when first accessed,
47 but we need to make sure that the object itself is initialized, and making
48 it a function-level static variable achieves that, because it will be
49 initialized the first time we enter this function at the very last.
51 static Logger
log("", LOG_DAEMON
);
55 void Logger::log(const string
& msg
, Urgency u
) noexcept
58 bool mustAccount(false);
60 if (u
<= consoleUrgency
) {
61 std::array
<char, 50> buffer
{};
68 if (strftime(buffer
.data(), buffer
.size(), "%b %d %H:%M:%S ", &tm
) == 0) {
83 severity
= "Critical";
106 static std::mutex mutex
;
107 std::lock_guard
<std::mutex
> lock(mutex
); // the C++-2011 spec says we need this, and OSX actually does
109 // To avoid issuing multiple syscalls, we write the complete line to clog with a single << call.
110 // For that we need a buffer allocated, we might want to use writev(2) one day to avoid that.
112 line
<< buffer
.data();
114 line
<< "msg=" << std::quoted(msg
) << " prio=" << std::quoted(severity
) << endl
;
119 clog
<< line
.str() << std::flush
;
124 if (u
<= d_loglevel
&& !d_disableSyslog
) {
125 syslog(u
, "%s", msg
.c_str());
134 S
.ringAccount("logmessages", msg
);
136 catch (const runtime_error
& e
) {
137 cerr
<< e
.what() << endl
;
143 void Logger::setLoglevel(Urgency u
)
148 void Logger::toConsole(Urgency u
)
157 openlog(name
.c_str(), flags
, d_facility
);
161 void Logger::setName(const string
& _name
)
167 Logger::Logger(string n
, int facility
) :
168 name(std::move(n
)), flags(LOG_PID
| LOG_NDELAY
), d_facility(facility
), d_loglevel(Logger::None
), consoleUrgency(Error
), opened(false), d_disableSyslog(false)
173 Logger
& Logger::operator<<(Urgency u
)
175 getPerThread().d_urgency
= u
;
179 Logger::PerThread
& Logger::getPerThread()
184 Logger
& Logger::operator<<(const string
& s
)
186 PerThread
& pt
= getPerThread();
187 pt
.d_output
.append(s
);
191 Logger
& Logger::operator<<(const char* s
)
197 Logger
& Logger::operator<<(ostream
& (&)(ostream
&))
199 PerThread
& pt
= getPerThread();
201 log(pt
.d_output
, pt
.d_urgency
);
207 Logger
& Logger::operator<<(const DNSName
& d
)
209 *this << d
.toLogString();
214 Logger
& Logger::operator<<(const ComboAddress
& ca
)
216 *this << ca
.toLogString();
220 void addTraceTS(const timeval
& start
, ostringstream
& str
)
222 const auto& content
= str
.str();
223 if (content
.empty() || content
.back() == '\n') {
225 gettimeofday(&time
, nullptr);
226 auto elapsed
= time
- start
;
227 auto diff
= elapsed
.tv_sec
* 1000000 + static_cast<time_t>(elapsed
.tv_usec
);