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