3 * @brief logger module implementation class.
5 * L7VSD: Linux Virtual Server for Layer7 Load Balancing
6 * Copyright (C) 2009 NTT COMWARE Corporation.
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
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 GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23 **********************************************************************/
30 #include <log4cxx/logger.h>
31 #include <log4cxx/level.h>
32 #include <log4cxx/net/syslogappender.h>
33 #include <log4cxx/fileappender.h>
34 #include <log4cxx/rollingfileappender.h>
35 #include <log4cxx/patternlayout.h>
36 #include <boost/format.hpp>
37 #include <boost/tr1/unordered_map.hpp>
38 #include <boost/foreach.hpp>
39 #include <boost/thread.hpp>
40 #include "logger_enum.h"
41 #include "logger_rotation_enum.h"
42 #include "appender_property.h"
46 #if !defined(LOGGER_PROCESS_VSD) && !defined(LOGGER_PROCESS_ADM)
47 #define LOGGER_PROCESS_VSD
50 #if defined(LOGGER_PROCESS_VSD)
51 #define LOGGER_PROCESS_ID "VSD"
52 #elif defined(LOGGER_PROCESS_ADM)
53 #define LOGGER_PROCESS_ID "ADM"
56 #define LOGGER_PROCESS_PROTOCOL_MODULE_ID "PRM"
58 #define LOGGER_PROCESS_SCHEDULE_MODULE_ID "SCM"
60 #define LOGGER_NULL "/dev/null"
62 #define LOGGER_LEVEL_NUM (6)
66 typedef helpers::ObjectPtrT<RollingFileAppender> RollingFileAppenderPtr;
73 //! @brief Logger implement class.
74 //! @brief this class manage logger setting and logging by log4cxx.
78 //! typedef category <-> level map
79 typedef std::map< LOG_CATEGORY_TAG, LOG_LEVEL_TAG>
80 category_level_map_type;
81 //! typedef category <-> level map read only
82 typedef std::tr1::unordered_map< LOG_CATEGORY_TAG, LOG_LEVEL_TAG>
83 category_level_read_map_type;
84 //! typedef categoryname <-> CATEGORY_TAG map
85 typedef std::map< std::string, LOG_CATEGORY_TAG>
86 name_category_map_type;
87 //! typedef CATEGORY_TAG <-> categoryname map
88 typedef std::map< LOG_CATEGORY_TAG, std::string>
89 category_name_map_type;
91 //! returns current instance.
92 static LoggerImpl &getInstance();
94 //! initialize function
97 //! Configuration function
98 virtual void loadConf();
101 * retrieve category's log level.
103 * @param category that want to know
106 virtual inline LOG_LEVEL_TAG getLogLevel(LOG_CATEGORY_TAG cat) {
107 return category_level_read_map[cat];
111 * retrieve all category's log level.
113 * @param[out] category level list
115 virtual inline void getLogLevelAll(category_level_list_type &list) {
116 category_level_read_map.clear();
117 BOOST_FOREACH(category_level_map_type::value_type const & itr, category_level_map) {
118 category_level_read_map[itr.first] = itr.second;
119 list.push_back(std::make_pair(itr.first, itr.second));
124 * set category's log level.
126 * @param category to set log level
128 * @retval true succeed
129 * @retval false failed
131 virtual inline bool setLogLevel(LOG_CATEGORY_TAG cat, LOG_LEVEL_TAG level) {
132 category_level_map_type::iterator lv_itr = category_level_map.find(cat);
133 lv_itr->second = level;
135 category_level_read_map.clear();
136 BOOST_FOREACH(category_level_map_type::value_type const & itr, category_level_map) {
137 category_level_read_map[itr.first] = itr.second;
140 category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
143 log4cxx::Logger::getLogger(categoryname_itr->second)->setLevel(log4cxx::Level::toLevel(levelTable[level]));
144 } catch (const std::exception &ex) {
151 * set all category's log level.
153 * @param category to set log level
155 * @retval true succeed
156 * @retval false failed
158 virtual inline bool setLogLevelAll(LOG_LEVEL_TAG level) {
159 category_level_read_map.clear();
160 BOOST_FOREACH(category_level_map_type::value_type & itr, category_level_map) {
162 category_level_read_map[itr.first] = itr.second;
164 category_name_map_type::iterator categoryname_itr = category_name_map.find(itr.first);
166 log4cxx::Logger::getLogger(categoryname_itr->second)->setLevel(log4cxx::Level::toLevel(levelTable[level]));
167 } catch (const std::exception &ex) {
177 * @param category that logging matter occurred
178 * @param log message id
180 * @param current file
181 * @param current line
184 virtual inline void putLogFatal(LOG_CATEGORY_TAG cat,
185 const unsigned int message_id,
186 const std::string &message,
189 std::stringstream buf;
193 case LOG_CAT_PROTOCOL:
195 buf << boost::format("%s%d%07d %s %s")
196 % LOGGER_PROCESS_PROTOCOL_MODULE_ID
203 case LOG_CAT_SCHEDULE:
205 buf << boost::format("%s%d%07d %s %s")
206 % LOGGER_PROCESS_SCHEDULE_MODULE_ID
215 buf << boost::format("%s%d%02d%05d %s %s")
226 category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
227 log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getFatal(),
229 log4cxx::spi::LocationInfo(file, "", line));
231 if (logtrap_enabled.get() == 1) {
232 LOG_LEVEL_TAG tmp_level;
234 rd_scoped_lock lock(logtrap_level_mutex);
235 tmp_level = logtrap_level;
237 if ((tmp_level <= LOG_LV_FATAL) &&
238 snmp_send_trap_func &&
239 (LOG_CAT_L7VSD_SNMPAGENT != cat)) {
240 trapmessage trap_msg;
241 trap_msg.type = trapmessage::FATAL_LOG;
242 trap_msg.message = buf.str();
245 snmp_send_trap_func(trap_msg, err);
248 } catch (const std::exception &ex) {
249 std::ostringstream oss;
250 oss << "Logging Error (Fatal Log) : " << ex.what();
251 errorConf(3, oss.str(), __FILE__, __LINE__);
257 * @param category that logging matter occurred
258 * @param log message id
260 * @param current file
261 * @param current line
264 virtual inline void putLogError(LOG_CATEGORY_TAG cat,
265 const unsigned int message_id,
266 const std::string &message,
269 std::stringstream buf;
272 case LOG_CAT_PROTOCOL:
274 buf << boost::format("%s%d%07d %s %s")
275 % LOGGER_PROCESS_PROTOCOL_MODULE_ID
282 case LOG_CAT_SCHEDULE:
284 buf << boost::format("%s%d%07d %s %s")
285 % LOGGER_PROCESS_SCHEDULE_MODULE_ID
294 buf << boost::format("%s%d%02d%05d %s %s")
305 category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
306 log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getError(),
308 log4cxx::spi::LocationInfo(file, "", line));
310 if (logtrap_enabled.get() == 1) {
311 LOG_LEVEL_TAG tmp_level;
313 rd_scoped_lock lock(logtrap_level_mutex);
314 tmp_level = logtrap_level;
316 if ((tmp_level <= LOG_LV_ERROR) &&
317 snmp_send_trap_func &&
318 (LOG_CAT_L7VSD_SNMPAGENT != cat)) {
319 trapmessage trap_msg;
320 trap_msg.type = trapmessage::ERROR_LOG;
321 trap_msg.message = buf.str();
324 snmp_send_trap_func(trap_msg, err);
327 } catch (const std::exception &ex) {
328 std::ostringstream oss;
329 oss << "Logging Error (Error Log) : " << ex.what();
330 errorConf(4, oss.str(), __FILE__, __LINE__);
336 * @param category that logging matter occurred
337 * @param log message id
339 * @param current file
340 * @param current line
343 virtual inline void putLogWarn(LOG_CATEGORY_TAG cat,
344 const unsigned int message_id,
345 const std::string &message,
348 std::stringstream buf;
351 case LOG_CAT_PROTOCOL:
353 buf << boost::format("%s%d%07d %s %s")
354 % LOGGER_PROCESS_PROTOCOL_MODULE_ID
361 case LOG_CAT_SCHEDULE:
363 buf << boost::format("%s%d%07d %s %s")
364 % LOGGER_PROCESS_SCHEDULE_MODULE_ID
373 buf << boost::format("%s%d%02d%05d %s %s")
384 category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
385 log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getWarn(),
387 log4cxx::spi::LocationInfo(file, "", line));
389 if (logtrap_enabled.get() == 1) {
390 LOG_LEVEL_TAG tmp_level;
392 rd_scoped_lock lock(logtrap_level_mutex);
393 tmp_level = logtrap_level;
395 if ((tmp_level <= LOG_LV_WARN) &&
396 snmp_send_trap_func &&
397 (LOG_CAT_L7VSD_SNMPAGENT != cat)) {
398 trapmessage trap_msg;
399 trap_msg.type = trapmessage::WARN_LOG;
400 trap_msg.message = buf.str();
403 snmp_send_trap_func(trap_msg, err);
406 } catch (const std::exception &ex) {
407 std::ostringstream oss;
408 oss << "Logging Error (Warn Log) : " << ex.what();
409 errorConf(5, oss.str(), __FILE__, __LINE__);
415 * @param category that logging matter occurred
416 * @param log message id
418 * @param current file
419 * @param current line
422 virtual inline void putLogInfo(LOG_CATEGORY_TAG cat,
423 const unsigned int message_id,
424 const std::string &message,
427 std::stringstream buf;
430 case LOG_CAT_PROTOCOL:
432 buf << boost::format("%s%d%07d %s %s")
433 % LOGGER_PROCESS_PROTOCOL_MODULE_ID
440 case LOG_CAT_SCHEDULE:
442 buf << boost::format("%s%d%07d %s %s")
443 % LOGGER_PROCESS_SCHEDULE_MODULE_ID
452 buf << boost::format("%s%d%02d%05d %s %s")
463 category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
464 log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getInfo(),
466 log4cxx::spi::LocationInfo(file, "", line));
469 if (logtrap_enabled.get() == 1) {
470 LOG_LEVEL_TAG tmp_level;
472 rd_scoped_lock lock(logtrap_level_mutex);
473 tmp_level = logtrap_level;
475 if ((tmp_level <= LOG_LV_INFO) &&
476 snmp_send_trap_func &&
477 (LOG_CAT_L7VSD_SNMPAGENT != cat)) {
478 trapmessage trap_msg;
479 trap_msg.type = trapmessage::INFO_LOG;
480 trap_msg.message = buf.str();
483 snmp_send_trap_func(trap_msg, err);
486 } catch (const std::exception &ex) {
487 std::ostringstream oss;
488 oss << "Logging Error (Info Log) : " << ex.what();
489 errorConf(6, oss.str(), __FILE__, __LINE__);
495 * @param category that logging matter occurred
496 * @param log message id
498 * @param current file
499 * @param current line
502 virtual inline void putLogDebug(LOG_CATEGORY_TAG cat,
503 const unsigned int message_id,
504 const std::string &message,
507 std::stringstream buf;
508 std::string logger_process_id = LOGGER_PROCESS_ID;
511 case LOG_CAT_PROTOCOL:
513 buf << boost::format("%s%d%07d %s %s")
514 % LOGGER_PROCESS_PROTOCOL_MODULE_ID
521 case LOG_CAT_SCHEDULE:
523 buf << boost::format("%s%d%07d %s %s")
524 % LOGGER_PROCESS_SCHEDULE_MODULE_ID
533 buf << boost::format("%s%d%02d%05d %s %s")
545 category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
546 log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getDebug(),
547 buf.str(), log4cxx::spi::LocationInfo(file, "", line));
549 if (logtrap_enabled.get() == 1) {
550 LOG_LEVEL_TAG tmp_level;
552 rd_scoped_lock lock(logtrap_level_mutex);
553 tmp_level = logtrap_level;
555 if ((tmp_level <= LOG_LV_DEBUG) &&
556 snmp_send_trap_func &&
557 (LOG_CAT_L7VSD_SNMPAGENT != cat)) {
558 trapmessage trap_msg;
559 trap_msg.type = trapmessage::DEBUG_LOG;
560 trap_msg.message = buf.str();
564 snmp_send_trap_func(trap_msg, err);
567 } catch (const std::exception &ex) {
568 std::ostringstream oss;
569 oss << "Logging Error (Debug Log) : " << ex.what();
570 errorConf(7, oss.str(), __FILE__, __LINE__);
575 * set snmp sendtrap function
577 * @param snmp send trap function object
580 void set_snmp_send_trap_func(const snmp_send_trap_func_type func) {
581 snmp_send_trap_func = func;
585 * set log trap enable
588 void logtrap_enable() {
589 logtrap_enabled = true;
593 * set log trap disable
596 void logtrap_disable() {
597 logtrap_enabled = false;
602 * @param log trap level
605 void set_logtrap_level(LOG_LEVEL_TAG in_logtrap_level) {
606 rw_scoped_lock lock(logtrap_level_mutex);
607 logtrap_level = in_logtrap_level;
612 //! default constructor initialize member variables.
615 //! copy constructor disable
616 LoggerImpl(const LoggerImpl &);
618 //! operator= disable
619 LoggerImpl &operator=(const LoggerImpl &);
621 //! LOG_LEVEL_TAG to log4cxx::LevelPtr translator
622 virtual inline const log4cxx::LevelPtr toLevel(LOG_LEVEL_TAG level) {
623 return log4cxx::Level::toLevel(levelTable[level]);
626 //! if error occurred, switch appenders to syslogappender and fileappender(/dev/console)
627 virtual void errorConf(unsigned int messageId,
628 const std::string &errorMessage,
632 virtual void logic_error(const unsigned int, const std::string &, const char *, const unsigned int);
635 //! log4cxx::LevelPtr to LOG_LEVEL_TAG translator
636 virtual inline LOG_LEVEL_TAG toLevelTag(const log4cxx::LevelPtr level){
637 int levelInt = level->toInt();
639 case log4cxx::Level::DEBUG_INT:
641 case log4cxx::Level::INFO_INT:
643 case log4cxx::Level::WARN_INT:
645 case log4cxx::Level::ERROR_INT:
647 case log4cxx::Level::FATAL_INT:
656 virtual ~LoggerImpl() {}
660 std::string hostname;
662 //log4cxx::Level* levelTable[LOGGER_LEVEL_NUM];
663 int levelTable[LOGGER_LEVEL_NUM];
665 //! category - loglevel hash map
666 category_level_map_type category_level_map;
667 category_level_read_map_type category_level_read_map;
668 //! category string -> logcategory hash map
669 name_category_map_type name_category_map;
670 //! log_category -> category string hash map
671 category_name_map_type category_name_map;
673 appender_property normal_log_property;
674 appender_property access_log_property;
676 //! snmp trap function
677 snmp_send_trap_func_type snmp_send_trap_func;
679 //! snmp log trap enable flag
680 atomic<unsigned int> logtrap_enabled;
682 //! snmp log trap level
683 LOG_LEVEL_TAG logtrap_level;
685 //! snmp log trap level mutex
686 wr_mutex logtrap_level_mutex;
691 #endif //__LOGGER_IMPL_H__