1 /*
2 Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include <ndb_global.h>
26
27 #include "Logger.hpp"
28
29 #include <LogHandler.hpp>
30 #include <ConsoleLogHandler.hpp>
31 #include <FileLogHandler.hpp>
32 #include "LogHandlerList.hpp"
33
34 #ifdef _WIN32
35 #include "EventLogHandler.hpp"
36 #else
37 #include <SysLogHandler.hpp>
38 #endif
39
40 #include <portlib/ndb_localtime.h>
41
42 const char* Logger::LoggerLevelNames[] = { "ON ",
43 "DEBUG ",
44 "INFO ",
45 "WARNING ",
46 "ERROR ",
47 "CRITICAL",
48 "ALERT ",
49 "ALL "
50 };
Logger()51 Logger::Logger() :
52 m_pCategory("Logger"),
53 m_pConsoleHandler(NULL),
54 m_pFileHandler(NULL),
55 m_pSyslogHandler(NULL)
56 {
57 m_pHandlerList = new LogHandlerList();
58 m_mutex= NdbMutex_Create();
59 m_handler_mutex= NdbMutex_Create();
60 disable(LL_ALL);
61 enable(LL_ON);
62 enable(LL_INFO);
63 }
64
~Logger()65 Logger::~Logger()
66 {
67 removeAllHandlers();
68 delete m_pHandlerList;
69 NdbMutex_Destroy(m_handler_mutex);
70 NdbMutex_Destroy(m_mutex);
71 }
72
73 void
setCategory(const char * pCategory)74 Logger::setCategory(const char* pCategory)
75 {
76 Guard g(m_mutex);
77 m_pCategory = pCategory;
78 }
79
80 bool
createConsoleHandler(NdbOut & out)81 Logger::createConsoleHandler(NdbOut &out)
82 {
83 Guard g(m_handler_mutex);
84
85 if (m_pConsoleHandler)
86 return true; // Ok, already exist
87
88 LogHandler* log_handler = new ConsoleLogHandler(out);
89 if (!log_handler)
90 return false;
91
92 if (!addHandler(log_handler))
93 {
94 delete log_handler;
95 return false;
96 }
97
98 m_pConsoleHandler = log_handler;
99 return true;
100 }
101
102 void
removeConsoleHandler()103 Logger::removeConsoleHandler()
104 {
105 Guard g(m_handler_mutex);
106 if (removeHandler(m_pConsoleHandler))
107 {
108 m_pConsoleHandler = NULL;
109 }
110 }
111
112 bool
createEventLogHandler(const char * source_name)113 Logger::createEventLogHandler(const char* source_name)
114 {
115 #ifdef _WIN32
116 Guard g(m_handler_mutex);
117
118 LogHandler* log_handler = new EventLogHandler(source_name);
119 if (!log_handler)
120 return false;
121
122 if (!addHandler(log_handler))
123 {
124 delete log_handler;
125 return false;
126 }
127
128 return true;
129 #else
130 return false;
131 #endif
132 }
133
134 bool
createFileHandler(char * filename)135 Logger::createFileHandler(char*filename)
136 {
137 Guard g(m_handler_mutex);
138
139 if (m_pFileHandler)
140 return true; // Ok, already exist
141
142 LogHandler* log_handler = new FileLogHandler(filename);
143 if (!log_handler)
144 return false;
145
146 if (!addHandler(log_handler))
147 {
148 delete log_handler;
149 return false;
150 }
151
152 m_pFileHandler = log_handler;
153 return true;
154 }
155
156 void
removeFileHandler()157 Logger::removeFileHandler()
158 {
159 Guard g(m_handler_mutex);
160 if (removeHandler(m_pFileHandler))
161 {
162 m_pFileHandler = NULL;
163 }
164 }
165
166 bool
createSyslogHandler()167 Logger::createSyslogHandler()
168 {
169 #ifdef _WIN32
170 return false;
171 #else
172 Guard g(m_handler_mutex);
173
174 if (m_pSyslogHandler)
175 return true; // Ok, already exist
176
177 LogHandler* log_handler = new SysLogHandler();
178 if (!log_handler)
179 return false;
180
181 if (!addHandler(log_handler))
182 {
183 delete log_handler;
184 return false;
185 }
186
187 m_pSyslogHandler = log_handler;
188 return true;
189 #endif
190 }
191
192 void
removeSyslogHandler()193 Logger::removeSyslogHandler()
194 {
195 Guard g(m_handler_mutex);
196 if (removeHandler(m_pSyslogHandler))
197 {
198 m_pSyslogHandler = NULL;
199 }
200 }
201
202 bool
addHandler(LogHandler * pHandler)203 Logger::addHandler(LogHandler* pHandler)
204 {
205 Guard g(m_mutex);
206 assert(pHandler != NULL);
207
208 if (!pHandler->is_open() &&
209 !pHandler->open())
210 {
211 // Failed to open
212 return false;
213 }
214
215 if (!m_pHandlerList->add(pHandler))
216 return false;
217
218 return true;
219 }
220
221
222 bool
removeHandler(LogHandler * pHandler)223 Logger::removeHandler(LogHandler* pHandler)
224 {
225 Guard g(m_mutex);
226 int rc = false;
227 if (pHandler != NULL)
228 {
229 if (pHandler == m_pConsoleHandler)
230 m_pConsoleHandler= NULL;
231 if (pHandler == m_pFileHandler)
232 m_pFileHandler= NULL;
233 if (pHandler == m_pSyslogHandler)
234 m_pSyslogHandler= NULL;
235
236 rc = m_pHandlerList->remove(pHandler);
237 }
238
239 return rc;
240 }
241
242 void
removeAllHandlers()243 Logger::removeAllHandlers()
244 {
245 Guard g(m_mutex);
246 m_pHandlerList->removeAll();
247
248 m_pConsoleHandler= NULL;
249 m_pFileHandler= NULL;
250 m_pSyslogHandler= NULL;
251 }
252
253 bool
isEnable(LoggerLevel logLevel) const254 Logger::isEnable(LoggerLevel logLevel) const
255 {
256 Guard g(m_mutex);
257 if (logLevel == LL_ALL)
258 {
259 for (unsigned i = 1; i < MAX_LOG_LEVELS; i++)
260 if (!m_logLevels[i])
261 return false;
262 return true;
263 }
264 return m_logLevels[logLevel];
265 }
266
267 void
enable(LoggerLevel logLevel)268 Logger::enable(LoggerLevel logLevel)
269 {
270 Guard g(m_mutex);
271 if (logLevel == LL_ALL)
272 {
273 for (unsigned i = 0; i < MAX_LOG_LEVELS; i++)
274 {
275 m_logLevels[i] = true;
276 }
277 }
278 else
279 {
280 m_logLevels[logLevel] = true;
281 }
282 }
283
284 void
enable(LoggerLevel fromLogLevel,LoggerLevel toLogLevel)285 Logger::enable(LoggerLevel fromLogLevel, LoggerLevel toLogLevel)
286 {
287 Guard g(m_mutex);
288 if (fromLogLevel > toLogLevel)
289 {
290 LoggerLevel tmp = toLogLevel;
291 toLogLevel = fromLogLevel;
292 fromLogLevel = tmp;
293 }
294
295 for (int i = fromLogLevel; i <= toLogLevel; i++)
296 {
297 m_logLevels[i] = true;
298 }
299 }
300
301 void
disable(LoggerLevel logLevel)302 Logger::disable(LoggerLevel logLevel)
303 {
304 Guard g(m_mutex);
305 if (logLevel == LL_ALL)
306 {
307 for (unsigned i = 0; i < MAX_LOG_LEVELS; i++)
308 {
309 m_logLevels[i] = false;
310 }
311 }
312 else
313 {
314 m_logLevels[logLevel] = false;
315 }
316 }
317
318 void
alert(const char * pMsg,...) const319 Logger::alert(const char* pMsg, ...) const
320 {
321 va_list ap;
322 va_start(ap, pMsg);
323 log(LL_ALERT, pMsg, ap);
324 va_end(ap);
325 }
326
327 void
critical(const char * pMsg,...) const328 Logger::critical(const char* pMsg, ...) const
329 {
330 va_list ap;
331 va_start(ap, pMsg);
332 log(LL_CRITICAL, pMsg, ap);
333 va_end(ap);
334 }
335 void
error(const char * pMsg,...) const336 Logger::error(const char* pMsg, ...) const
337 {
338 va_list ap;
339 va_start(ap, pMsg);
340 log(LL_ERROR, pMsg, ap);
341 va_end(ap);
342 }
343 void
warning(const char * pMsg,...) const344 Logger::warning(const char* pMsg, ...) const
345 {
346 va_list ap;
347 va_start(ap, pMsg);
348 log(LL_WARNING, pMsg, ap);
349 va_end(ap);
350 }
351
352 void
info(const char * pMsg,...) const353 Logger::info(const char* pMsg, ...) const
354 {
355 va_list ap;
356 va_start(ap, pMsg);
357 log(LL_INFO, pMsg, ap);
358 va_end(ap);
359 }
360
361 void
debug(const char * pMsg,...) const362 Logger::debug(const char* pMsg, ...) const
363 {
364 va_list ap;
365 va_start(ap, pMsg);
366 log(LL_DEBUG, pMsg, ap);
367 va_end(ap);
368 }
369
370 void
log(LoggerLevel logLevel,const char * pMsg,va_list ap) const371 Logger::log(LoggerLevel logLevel, const char* pMsg, va_list ap) const
372 {
373 Guard g(m_mutex);
374 if (m_logLevels[LL_ON] && m_logLevels[logLevel])
375 {
376 char buf[MAX_LOG_MESSAGE_SIZE];
377 BaseString::vsnprintf(buf, sizeof(buf), pMsg, ap);
378 LogHandler* pHandler = NULL;
379 while ( (pHandler = m_pHandlerList->next()) != NULL)
380 {
381 pHandler->append(m_pCategory, logLevel, buf);
382 }
383 }
384 }
385
setRepeatFrequency(unsigned val)386 void Logger::setRepeatFrequency(unsigned val)
387 {
388 LogHandler* pHandler;
389 while ((pHandler = m_pHandlerList->next()) != NULL)
390 {
391 pHandler->setRepeatFrequency(val);
392 }
393 }
394
395
396 void
format_timestamp(const time_t epoch,char * str,size_t len)397 Logger::format_timestamp(const time_t epoch,
398 char* str, size_t len)
399 {
400 assert(len > 0); // Assume buffer has size
401
402 // convert to local timezone
403 tm tm_buf;
404 if (ndb_localtime_r(&epoch, &tm_buf) == NULL)
405 {
406 // Failed to convert to local timezone.
407 // Fill with bogus time stamp value in order
408 // to ensure buffer can be safely printed
409 strncpy(str, "2001-01-01 00:00:00", len);
410 str[len-1] = 0;
411 return;
412 }
413
414 // Print the broken down time in timestamp format
415 // to the string buffer
416 BaseString::snprintf(str, len,
417 "%d-%.2d-%.2d %.2d:%.2d:%.2d",
418 tm_buf.tm_year + 1900,
419 tm_buf.tm_mon + 1, //month is [0,11]. +1 -> [1,12]
420 tm_buf.tm_mday,
421 tm_buf.tm_hour,
422 tm_buf.tm_min,
423 tm_buf.tm_sec);
424 str[len-1] = 0;
425 return;
426 }
427