]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/logger.cc
rec: Wrap pthread_ objects
[thirdparty/pdns.git] / pdns / logger.cc
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 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <mutex>
27
28 #include "logger.hh"
29 #include "misc.hh"
30 #ifndef RECURSOR
31 #include "statbag.hh"
32 extern StatBag S;
33 #endif
34 #include "namespaces.hh"
35
36 thread_local Logger::PerThread Logger::t_perThread;
37
38 Logger& getLogger()
39 {
40 /* Since the Logger can be called very early, we need to make sure
41 that the relevant parts are initialized no matter what, which is tricky
42 because we can't easily control the initialization order, especially with
43 built-in backends.
44 t_perThread is thread_local, so it will be initialized when first accessed,
45 but we need to make sure that the object itself is initialized, and making
46 it a function-level static variable achieves that, because it will be
47 initialized the first time we enter this function at the very last.
48 */
49 static Logger log("", LOG_DAEMON);
50 return log;
51 }
52
53 void Logger::log(const string &msg, Urgency u)
54 {
55 #ifndef RECURSOR
56 bool mustAccount(false);
57 #endif
58 if(u<=consoleUrgency) {
59 char buffer[50] = "";
60 if (d_timestamps) {
61 struct tm tm;
62 time_t t;
63 time(&t);
64 localtime_r(&t, &tm);
65 strftime(buffer,sizeof(buffer),"%b %d %H:%M:%S ", &tm);
66 }
67
68 string prefix;
69 if (d_prefixed) {
70 switch(u) {
71 case All:
72 prefix = "[all] ";
73 break;
74 case Alert:
75 prefix = "[ALERT] ";
76 break;
77 case Critical:
78 prefix = "[CRITICAL] ";
79 break;
80 case Error:
81 prefix = "[ERROR] ";
82 break;
83 case Warning:
84 prefix = "[WARNING] ";
85 break;
86 case Notice:
87 prefix = "[NOTICE] ";
88 break;
89 case Info:
90 prefix = "[INFO] ";
91 break;
92 case Debug:
93 prefix = "[DEBUG] ";
94 break;
95 case None:
96 prefix = "[none] ";
97 break;
98 }
99 }
100
101 static std::mutex m;
102 std::lock_guard<std::mutex> l(m); // the C++-2011 spec says we need this, and OSX actually does
103 clog << string(buffer) + prefix + msg <<endl;
104 #ifndef RECURSOR
105 mustAccount=true;
106 #endif
107 }
108 if( u <= d_loglevel && !d_disableSyslog ) {
109 syslog(u,"%s",msg.c_str());
110 #ifndef RECURSOR
111 mustAccount=true;
112 #endif
113 }
114
115 #ifndef RECURSOR
116 if(mustAccount)
117 S.ringAccount("logmessages",msg);
118 #endif
119 }
120
121 void Logger::setLoglevel( Urgency u )
122 {
123 d_loglevel = u;
124 }
125
126
127 void Logger::toConsole(Urgency u)
128 {
129 consoleUrgency=u;
130 }
131
132 void Logger::open()
133 {
134 if(opened)
135 closelog();
136 openlog(name.c_str(),flags,d_facility);
137 opened=true;
138 }
139
140 void Logger::setName(const string &_name)
141 {
142 name=_name;
143 open();
144 }
145
146 Logger::Logger(const string &n, int facility) :
147 name(n), flags(LOG_PID|LOG_NDELAY), d_facility(facility), d_loglevel(Logger::None),
148 consoleUrgency(Error), opened(false), d_disableSyslog(false)
149 {
150 open();
151
152 }
153
154 Logger& Logger::operator<<(Urgency u)
155 {
156 getPerThread().d_urgency=u;
157 return *this;
158 }
159
160 Logger::PerThread& Logger::getPerThread()
161 {
162 return t_perThread;
163 }
164
165 Logger& Logger::operator<<(const string &s)
166 {
167 PerThread& pt = getPerThread();
168 pt.d_output.append(s);
169 return *this;
170 }
171
172 Logger& Logger::operator<<(const char *s)
173 {
174 *this<<string(s);
175 return *this;
176 }
177
178 Logger& Logger::operator<<(ostream & (&)(ostream &))
179 {
180 PerThread& pt = getPerThread();
181
182 log(pt.d_output, pt.d_urgency);
183 pt.d_output.clear();
184 pt.d_urgency=Info;
185 return *this;
186 }
187
188 Logger& Logger::operator<<(const DNSName &d)
189 {
190 *this<<d.toLogString();
191
192 return *this;
193 }
194
195 Logger& Logger::operator<<(const ComboAddress &ca)
196 {
197 *this<<ca.toLogString();
198 return *this;
199 }
200