OSDN Git Service

Merge pull request #36314 (suigintoh/ultramonkey-l7-v3/fix_signum_cast into master).
[ultramonkey-l7/ultramonkey-l7-v3.git] / l7vsd / include / logger_impl.h
1 /*!
2  * @file  logger_impl.h
3  * @brief logger module implementation class.
4  *
5  * L7VSD: Linux Virtual Server for Layer7 Load Balancing
6  * Copyright (C) 2009  NTT COMWARE Corporation.
7  *
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.
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 GNU
16  * Lesser General Public License for more details.
17  *
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
21  * 02110-1301 USA
22  *
23  **********************************************************************/
24
25 #ifndef LOGGER_IMPL_H
26 #define LOGGER_IMPL_H
27
28 #include <sstream>
29 #include <map>
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"
43 #include "atomic.h"
44 #include "wrlock.h"
45
46 #if !defined(LOGGER_PROCESS_VSD) && !defined(LOGGER_PROCESS_ADM)
47 #define LOGGER_PROCESS_VSD
48 #endif
49
50 #if defined(LOGGER_PROCESS_VSD)
51 #define LOGGER_PROCESS_ID "VSD"
52 #elif defined(LOGGER_PROCESS_ADM)
53 #define LOGGER_PROCESS_ID "ADM"
54 #endif
55
56 #define LOGGER_PROCESS_PROTOCOL_MODULE_ID "PRM"
57
58 #define LOGGER_PROCESS_SCHEDULE_MODULE_ID "SCM"
59
60 #define LOGGER_NULL "/dev/null"
61
62 #define LOGGER_LEVEL_NUM (6)
63
64 namespace log4cxx
65 {
66 typedef helpers::ObjectPtrT<RollingFileAppender> RollingFileAppenderPtr;
67 }
68
69 namespace l7vs
70 {
71
72 //! @class LoggerImpl
73 //! @brief Logger implement class.
74 //! @brief this class manage logger setting and logging by log4cxx.
75 class LoggerImpl
76 {
77 protected:
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;
90 public:
91         //! returns current instance.
92         static LoggerImpl &getInstance();
93
94         //! initialize function
95         virtual bool init();
96
97         //! Configuration function
98         virtual    void loadConf();
99
100         /*!
101          * retrieve category's log level.
102          *
103          * @param   category that want to know
104          * @return  log level
105          */
106         virtual inline LOG_LEVEL_TAG getLogLevel(LOG_CATEGORY_TAG cat) {
107                 return category_level_read_map[cat];
108         }
109
110         /*!
111          * retrieve all category's log level.
112          *
113          * @param[out]   category level list
114          */
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));
120                 }
121         }
122
123         /*!
124          * set category's log level.
125          *
126          * @param   category to set log level
127          * @param   level
128          * @retval  true  succeed
129          * @retval  false failed
130          */
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;
134
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;
138                 }
139
140                 category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
141
142                 try {
143                         log4cxx::Logger::getLogger(categoryname_itr->second)->setLevel(log4cxx::Level::toLevel(levelTable[level]));
144                 } catch (const std::exception &ex) {
145                         return false;
146                 }
147                 return true;
148         }
149
150         /*!
151          * set all category's log level.
152          *
153          * @param   category to set log level
154          * @param   level
155          * @retval  true  succeed
156          * @retval  false failed
157          */
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) {
161                         itr.second = level;
162                         category_level_read_map[itr.first] = itr.second;
163
164                         category_name_map_type::iterator categoryname_itr = category_name_map.find(itr.first);
165                         try {
166                                 log4cxx::Logger::getLogger(categoryname_itr->second)->setLevel(log4cxx::Level::toLevel(levelTable[level]));
167                         } catch (const std::exception &ex) {
168                                 return false;
169                         }
170                 }
171                 return true;
172         }
173
174         /*!
175          * output fatal log.
176          *
177          * @param   category that logging matter occurred
178          * @param   log message id
179          * @param   log message
180          * @param   current file
181          * @param   current line
182          * @retrun  void
183          */
184         virtual inline void putLogFatal(LOG_CATEGORY_TAG cat,
185                                         const unsigned int message_id,
186                                         const std::string &message,
187                                         const char *file,
188                                         int line) {
189                 std::stringstream   buf;
190
191
192                 switch (cat) {
193                 case    LOG_CAT_PROTOCOL:
194
195                         buf << boost::format("%s%d%07d %s %s")
196                             % LOGGER_PROCESS_PROTOCOL_MODULE_ID
197                             % LOG_LV_FATAL
198                             % message_id
199                             % message.c_str()
200                             % hostname;
201
202                         break;
203                 case    LOG_CAT_SCHEDULE:
204
205                         buf << boost::format("%s%d%07d %s %s")
206                             % LOGGER_PROCESS_SCHEDULE_MODULE_ID
207                             % LOG_LV_FATAL
208                             % message_id
209                             % message.c_str()
210                             % hostname;
211
212                         break;
213                 default:
214
215                         buf << boost::format("%s%d%02d%05d %s %s")
216                             % LOGGER_PROCESS_ID
217                             % LOG_LV_FATAL
218                             % cat
219                             % message_id
220                             % message.c_str()
221                             % hostname;
222
223                 }
224
225                 try {
226                         category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
227                         log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getFatal(),
228                                         buf.str(),
229                                         log4cxx::spi::LocationInfo(file, "", line));
230                         // send_trap
231                         if (logtrap_enabled.get() == 1) {
232                                 LOG_LEVEL_TAG tmp_level;
233                                 {
234                                         rd_scoped_lock lock(logtrap_level_mutex);
235                                         tmp_level = logtrap_level;
236                                 }
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();
243                                         error_code err;
244                                         //send trap message
245                                         snmp_send_trap_func(trap_msg, err);
246                                 }
247                         }
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__);
252                 }
253         }
254         /*!
255          * output error log.
256          *
257          * @param   category that logging matter occurred
258          * @param   log message id
259          * @param   log message
260          * @param   current file
261          * @param   current line
262          * @retrun  void
263          */
264         virtual inline void putLogError(LOG_CATEGORY_TAG cat,
265                                         const unsigned int message_id,
266                                         const std::string &message,
267                                         const char *file,
268                                         int line) {
269                 std::stringstream    buf;
270
271                 switch (cat) {
272                 case    LOG_CAT_PROTOCOL:
273
274                         buf << boost::format("%s%d%07d %s %s")
275                             % LOGGER_PROCESS_PROTOCOL_MODULE_ID
276                             % LOG_LV_ERROR
277                             % message_id
278                             % message.c_str()
279                             % hostname;
280
281                         break;
282                 case    LOG_CAT_SCHEDULE:
283
284                         buf << boost::format("%s%d%07d %s %s")
285                             % LOGGER_PROCESS_SCHEDULE_MODULE_ID
286                             % LOG_LV_ERROR
287                             % message_id
288                             % message.c_str()
289                             % hostname;
290
291                         break;
292                 default:
293
294                         buf << boost::format("%s%d%02d%05d %s %s")
295                             % LOGGER_PROCESS_ID
296                             % LOG_LV_ERROR
297                             % cat
298                             % message_id
299                             % message.c_str()
300                             % hostname;
301
302                 }
303
304                 try {
305                         category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
306                         log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getError(),
307                                         buf.str(),
308                                         log4cxx::spi::LocationInfo(file, "", line));
309                         // send_trap
310                         if (logtrap_enabled.get() == 1) {
311                                 LOG_LEVEL_TAG tmp_level;
312                                 {
313                                         rd_scoped_lock lock(logtrap_level_mutex);
314                                         tmp_level = logtrap_level;
315                                 }
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();
322                                         error_code err;
323                                         //send trap message
324                                         snmp_send_trap_func(trap_msg, err);
325                                 }
326                         }
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__);
331                 }
332         }
333         /*!
334          * output warn log.
335          *
336          * @param   category that logging matter occurred
337          * @param   log message id
338          * @param   log message
339          * @param   current file
340          * @param   current line
341          * @retrun  void
342          */
343         virtual inline void putLogWarn(LOG_CATEGORY_TAG cat,
344                                        const unsigned int message_id,
345                                        const std::string &message,
346                                        const char *file,
347                                        int line) {
348                 std::stringstream buf;
349
350                 switch (cat) {
351                 case    LOG_CAT_PROTOCOL:
352
353                         buf << boost::format("%s%d%07d %s %s")
354                             % LOGGER_PROCESS_PROTOCOL_MODULE_ID
355                             % LOG_LV_WARN
356                             % message_id
357                             % message.c_str()
358                             % hostname;
359
360                         break;
361                 case    LOG_CAT_SCHEDULE:
362
363                         buf << boost::format("%s%d%07d %s %s")
364                             % LOGGER_PROCESS_SCHEDULE_MODULE_ID
365                             % LOG_LV_WARN
366                             % message_id
367                             % message.c_str()
368                             % hostname;
369
370                         break;
371                 default:
372
373                         buf << boost::format("%s%d%02d%05d %s %s")
374                             % LOGGER_PROCESS_ID
375                             % LOG_LV_WARN
376                             % cat
377                             % message_id
378                             % message.c_str()
379                             % hostname;
380
381                 }
382
383                 try {
384                         category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
385                         log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getWarn(),
386                                         buf.str(),
387                                         log4cxx::spi::LocationInfo(file, "", line));
388                         // send_trap
389                         if (logtrap_enabled.get() == 1) {
390                                 LOG_LEVEL_TAG tmp_level;
391                                 {
392                                         rd_scoped_lock lock(logtrap_level_mutex);
393                                         tmp_level = logtrap_level;
394                                 }
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();
401                                         error_code err;
402                                         //send trap message
403                                         snmp_send_trap_func(trap_msg, err);
404                                 }
405                         }
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__);
410                 }
411         }
412         /*!
413          * output info log.
414          *
415          * @param   category that logging matter occurred
416          * @param   log message id
417          * @param   log message
418          * @param   current file
419          * @param   current line
420          * @retrun  void
421          */
422         virtual inline void putLogInfo(LOG_CATEGORY_TAG cat,
423                                        const unsigned int message_id,
424                                        const std::string &message,
425                                        const char *file,
426                                        int line) {
427                 std::stringstream    buf;
428
429                 switch (cat) {
430                 case    LOG_CAT_PROTOCOL:
431
432                         buf << boost::format("%s%d%07d %s %s")
433                             % LOGGER_PROCESS_PROTOCOL_MODULE_ID
434                             % LOG_LV_INFO
435                             % message_id
436                             % message.c_str()
437                             % hostname;
438
439                         break;
440                 case    LOG_CAT_SCHEDULE:
441
442                         buf << boost::format("%s%d%07d %s %s")
443                             % LOGGER_PROCESS_SCHEDULE_MODULE_ID
444                             % LOG_LV_INFO
445                             % message_id
446                             % message.c_str()
447                             % hostname;
448
449                         break;
450                 default:
451
452                         buf << boost::format("%s%d%02d%05d %s %s")
453                             % LOGGER_PROCESS_ID
454                             % LOG_LV_INFO
455                             % cat
456                             % message_id
457                             % message.c_str()
458                             % hostname;
459
460                 }
461
462                 try {
463                         category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
464                         log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getInfo(),
465                                         buf.str(),
466                                         log4cxx::spi::LocationInfo(file, "", line));
467
468                         // send_trap
469                         if (logtrap_enabled.get() == 1) {
470                                 LOG_LEVEL_TAG tmp_level;
471                                 {
472                                         rd_scoped_lock lock(logtrap_level_mutex);
473                                         tmp_level = logtrap_level;
474                                 }
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();
481                                         error_code err;
482                                         //send trap message
483                                         snmp_send_trap_func(trap_msg, err);
484                                 }
485                         }
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__);
490                 }
491         }
492         /*!
493          * output debug log.
494          *
495          * @param   category that logging matter occurred
496          * @param   log message id
497          * @param   log message
498          * @param   current file
499          * @param   current line
500          * @retrun  void
501          */
502         virtual inline void putLogDebug(LOG_CATEGORY_TAG cat,
503                                         const unsigned int message_id,
504                                         const std::string &message,
505                                         const char *file,
506                                         int line) {
507                 std::stringstream    buf;
508                 std::string logger_process_id = LOGGER_PROCESS_ID;
509
510                 switch (cat) {
511                 case    LOG_CAT_PROTOCOL:
512
513                         buf << boost::format("%s%d%07d %s %s")
514                             % LOGGER_PROCESS_PROTOCOL_MODULE_ID
515                             % LOG_LV_DEBUG
516                             % message_id
517                             % message.c_str()
518                             % hostname;
519
520                         break;
521                 case    LOG_CAT_SCHEDULE:
522
523                         buf << boost::format("%s%d%07d %s %s")
524                             % LOGGER_PROCESS_SCHEDULE_MODULE_ID
525                             % LOG_LV_DEBUG
526                             % message_id
527                             % message.c_str()
528                             % hostname;
529
530                         break;
531                 default:
532
533                         buf << boost::format("%s%d%02d%05d %s %s")
534                             % LOGGER_PROCESS_ID
535                             % LOG_LV_DEBUG
536                             % cat
537                             % message_id
538                             % message.c_str()
539                             % hostname;
540
541                 }
542
543
544                 try {
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));
548                         // send_trap
549                         if (logtrap_enabled.get() == 1) {
550                                 LOG_LEVEL_TAG tmp_level;
551                                 {
552                                         rd_scoped_lock lock(logtrap_level_mutex);
553                                         tmp_level = logtrap_level;
554                                 }
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();
561
562                                         error_code err;
563                                         //send trap message
564                                         snmp_send_trap_func(trap_msg, err);
565                                 }
566                         }
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__);
571                 }
572         }
573
574         /*!
575          * set snmp sendtrap function
576          *
577          * @param   snmp send trap function object
578          * @retrun  void
579          */
580         void    set_snmp_send_trap_func(const snmp_send_trap_func_type func) {
581                 snmp_send_trap_func = func;
582         }
583
584         /*!
585          * set log trap enable
586          * @retrun  void
587          */
588         void    logtrap_enable() {
589                 logtrap_enabled = true;
590         }
591
592         /*!
593          * set log trap disable
594          * @retrun  void
595          */
596         void    logtrap_disable() {
597                 logtrap_enabled = false;
598         }
599
600         /*!
601          * set log trap level
602          * @param   log trap level
603          * @retrun  void
604          */
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;
608         }
609
610
611 protected:
612         //! default constructor initialize member variables.
613         LoggerImpl();
614
615         //! copy constructor disable
616         LoggerImpl(const LoggerImpl &);
617
618         //! operator= disable
619         LoggerImpl &operator=(const LoggerImpl &);
620
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]);
624         }
625
626         //! if error occurred, switch appenders to syslogappender and fileappender(/dev/console)
627         virtual void errorConf(unsigned int messageId,
628                                const std::string &errorMessage,
629                                const char *file,
630                                int line);
631
632         virtual void logic_error(const unsigned int, const std::string &, const char *, const unsigned int);
633
634         /*
635             //! log4cxx::LevelPtr to LOG_LEVEL_TAG translator
636             virtual inline LOG_LEVEL_TAG toLevelTag(const log4cxx::LevelPtr level){
637                 int levelInt = level->toInt();
638                 switch (levelInt) {
639                 case log4cxx::Level::DEBUG_INT:
640                     return LOG_LV_DEBUG;
641                 case log4cxx::Level::INFO_INT:
642                     return LOG_LV_INFO;
643                 case log4cxx::Level::WARN_INT:
644                     return LOG_LV_WARN;
645                 case log4cxx::Level::ERROR_INT:
646                     return LOG_LV_ERROR;
647                 case log4cxx::Level::FATAL_INT:
648                     return LOG_LV_FATAL;
649                 default:
650                     return LOG_LV_DEBUG;
651                 }
652             }
653         */
654
655         //! destructor.
656         virtual ~LoggerImpl() {}
657         //! initialized flag
658         bool initialized;
659         //! hostname
660         std::string hostname;
661
662         //log4cxx::Level* levelTable[LOGGER_LEVEL_NUM];
663         int    levelTable[LOGGER_LEVEL_NUM];
664
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;
672
673         appender_property    normal_log_property;
674         appender_property    access_log_property;
675
676         //! snmp trap function
677         snmp_send_trap_func_type    snmp_send_trap_func;
678
679         //! snmp log trap enable flag
680         atomic<unsigned int>    logtrap_enabled;
681
682         //! snmp log trap level
683         LOG_LEVEL_TAG    logtrap_level;
684
685         //! snmp log trap level mutex
686         wr_mutex    logtrap_level_mutex;
687
688 };
689
690 }    //namespace l7vs
691 #endif    //__LOGGER_IMPL_H__