OSDN Git Service

Marge SourceIP code <= SNMP code
[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) && !defined(LOGGER_PROCESS_SNM)
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 #else
55 #define LOGGER_PROCESS_ID "SNM"
56 #endif
57
58 #define LOGGER_PROCESS_PROTOCOL_MODULE_ID "PRM"
59
60 #define LOGGER_PROCESS_SCHEDULE_MODULE_ID "SCM"
61
62 #define LOGGER_NULL "/dev/null"
63
64 #define LOGGER_LEVEL_NUM (6)
65
66 namespace log4cxx
67 {
68 typedef helpers::ObjectPtrT<RollingFileAppender> RollingFileAppenderPtr;
69 }
70
71 namespace l7vs
72 {
73
74 //! @class LoggerImpl
75 //! @brief Logger implement class.
76 //! @brief this class manage logger setting and logging by log4cxx.
77 class LoggerImpl
78 {
79 protected:
80         //! typedef    category <-> level map
81         typedef    std::map< LOG_CATEGORY_TAG, LOG_LEVEL_TAG>
82         category_level_map_type;
83         //! typedef category <-> level map read only
84         typedef std::tr1::unordered_map< LOG_CATEGORY_TAG, LOG_LEVEL_TAG>
85         category_level_read_map_type;
86         //! typedef    categoryname <-> CATEGORY_TAG map
87         typedef    std::map< std::string, LOG_CATEGORY_TAG>
88         name_category_map_type;
89         //! typedef CATEGORY_TAG <-> categoryname map
90         typedef    std::map< LOG_CATEGORY_TAG, std::string>
91         category_name_map_type;
92 public:
93         //! returns current instance.
94         static LoggerImpl &getInstance();
95
96         //! initialze function
97         virtual bool init();
98
99         //! Configuration function
100         virtual    void loadConf();
101
102         /*!
103          * retrieve category's log level.
104          *
105          * @param   category that want to know
106          * @return  log level
107          */
108         virtual inline LOG_LEVEL_TAG getLogLevel(LOG_CATEGORY_TAG cat) {
109                 return category_level_read_map[cat];
110         }
111
112         /*!
113          * retrieve all category's log level.
114          *
115          * @param[out]   category level list
116          */
117         virtual inline void getLogLevelAll(category_level_list_type &list) {
118                 category_level_read_map.clear();
119                 BOOST_FOREACH(category_level_map_type::value_type const & itr, category_level_map) {
120                         category_level_read_map[itr.first] = itr.second;
121                         list.push_back(std::make_pair(itr.first, itr.second));
122                 }
123         }
124
125         /*!
126          * set category's log level.
127          *
128          * @param   category to set log level
129          * @param   level
130          * @retval  true  succeed
131          * @retval  false failed
132          */
133         virtual inline bool setLogLevel(LOG_CATEGORY_TAG cat, LOG_LEVEL_TAG level) {
134                 category_level_map_type::iterator lv_itr = category_level_map.find(cat);
135                 lv_itr->second = level;
136
137                 category_level_read_map.clear();
138                 BOOST_FOREACH(category_level_map_type::value_type const & itr, category_level_map) {
139                         category_level_read_map[itr.first] = itr.second;
140                 }
141
142                 category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
143
144                 try {
145                         log4cxx::Logger::getLogger(categoryname_itr->second)->setLevel(log4cxx::Level::toLevel(levelTable[level]));
146                 } catch (const std::exception &ex) {
147                         return false;
148                 }
149                 return true;
150         }
151
152         /*!
153          * set all category's log level.
154          *
155          * @param   category to set log level
156          * @param   level
157          * @retval  true  succeed
158          * @retval  false failed
159          */
160         virtual inline bool setLogLevelAll(LOG_LEVEL_TAG level) {
161                 category_level_read_map.clear();
162                 BOOST_FOREACH(category_level_map_type::value_type & itr, category_level_map) {
163                         itr.second = level;
164                         category_level_read_map[itr.first] = itr.second;
165
166                         category_name_map_type::iterator categoryname_itr = category_name_map.find(itr.first);
167                         try {
168                                 log4cxx::Logger::getLogger(categoryname_itr->second)->setLevel(log4cxx::Level::toLevel(levelTable[level]));
169                         } catch (const std::exception &ex) {
170                                 return false;
171                         }
172                 }
173                 return true;
174         }
175
176         /*!
177          * output fatal log.
178          *
179          * @param   category that logging matter occured
180          * @param   log message id
181          * @param   log message
182          * @param   current file
183          * @param   current line
184          * @retrun  void
185          */
186         virtual inline void putLogFatal(LOG_CATEGORY_TAG cat,
187                                         const unsigned int message_id,
188                                         const std::string &message,
189                                         const char *file,
190                                         int line) {
191                 std::stringstream   buf;
192
193
194                 switch (cat) {
195                 case    LOG_CAT_PROTOCOL:
196
197                         buf << boost::format("%s%d%07d %s %s")
198                             % LOGGER_PROCESS_PROTOCOL_MODULE_ID
199                             % LOG_LV_FATAL
200                             % message_id
201                             % message.c_str()
202                             % hostname;
203
204                         break;
205                 case    LOG_CAT_SCHEDULE:
206
207                         buf << boost::format("%s%d%07d %s %s")
208                             % LOGGER_PROCESS_SCHEDULE_MODULE_ID
209                             % LOG_LV_FATAL
210                             % message_id
211                             % message.c_str()
212                             % hostname;
213
214                         break;
215                 default:
216
217                         buf << boost::format("%s%d%02d%05d %s %s")
218                             % LOGGER_PROCESS_ID
219                             % LOG_LV_FATAL
220                             % cat
221                             % message_id
222                             % message.c_str()
223                             % hostname;
224
225                 }
226
227                 try {
228                         category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
229                         log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getFatal(),
230                                         buf.str(),
231                                         log4cxx::spi::LocationInfo(file, "", line));
232                         // send_trap
233                         if (logtrap_enabled.get() == 1) {
234                                 LOG_LEVEL_TAG tmp_level;
235                                 {
236                                         rd_scoped_lock lock(logtrap_level_mutex);
237                                         tmp_level = logtrap_level;
238                                 }
239                                 if ( (tmp_level >= LOG_LV_FATAL) &&
240                                       snmp_send_trap_func        &&
241                                       (LOG_CAT_L7VSD_SNMPAGENT != cat)) {
242                                         trapmessage trap_msg;
243                                         trap_msg.type = trapmessage::FATAL_LOG;
244                                         trap_msg.message = buf.str();
245                                         error_code err;
246                                         //send trap message
247                                         snmp_send_trap_func(trap_msg, err);
248                                 }
249                         }
250                 } catch (const std::exception &ex) {
251                         std::ostringstream oss;
252                         oss << "Logging Error (Fatal Log) : " << ex.what();
253                         errorConf(3, oss.str(), __FILE__, __LINE__);
254                 }
255         }
256         /*!
257          * output error log.
258          *
259          * @param   category that logging matter occured
260          * @param   log message id
261          * @param   log message
262          * @param   current file
263          * @param   current line
264          * @retrun  void
265          */
266         virtual inline void putLogError(LOG_CATEGORY_TAG cat,
267                                         const unsigned int message_id,
268                                         const std::string &message,
269                                         const char *file,
270                                         int line) {
271                 std::stringstream    buf;
272
273                 switch (cat) {
274                 case    LOG_CAT_PROTOCOL:
275
276                         buf << boost::format("%s%d%07d %s %s")
277                             % LOGGER_PROCESS_PROTOCOL_MODULE_ID
278                             % LOG_LV_ERROR
279                             % message_id
280                             % message.c_str()
281                             % hostname;
282
283                         break;
284                 case    LOG_CAT_SCHEDULE:
285
286                         buf << boost::format("%s%d%07d %s %s")
287                             % LOGGER_PROCESS_SCHEDULE_MODULE_ID
288                             % LOG_LV_ERROR
289                             % message_id
290                             % message.c_str()
291                             % hostname;
292
293                         break;
294                 default:
295
296                         buf << boost::format("%s%d%02d%05d %s %s")
297                             % LOGGER_PROCESS_ID
298                             % LOG_LV_ERROR
299                             % cat
300                             % message_id
301                             % message.c_str()
302                             % hostname;
303
304                 }
305
306                 try {
307                         category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
308                         log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getError(),
309                                         buf.str(),
310                                         log4cxx::spi::LocationInfo(file, "", line));
311                         // send_trap
312                         if (logtrap_enabled.get() == 1) {
313                                 LOG_LEVEL_TAG tmp_level;
314                                 {
315                                         rd_scoped_lock lock(logtrap_level_mutex);
316                                         tmp_level = logtrap_level;
317                                 }
318                                 if ( (tmp_level >= LOG_LV_ERROR) &&
319                                       snmp_send_trap_func        &&
320                                       (LOG_CAT_L7VSD_SNMPAGENT != cat)) {
321                                         trapmessage trap_msg;
322                                         trap_msg.type = trapmessage::ERROR_LOG;
323                                         trap_msg.message = buf.str();
324                                         error_code err;
325                                         //send trap message
326                                         snmp_send_trap_func(trap_msg, err);
327                                 }
328                         }
329                 } catch (const std::exception &ex) {
330                         std::ostringstream oss;
331                         oss << "Logging Error (Error Log) : " << ex.what();
332                         errorConf(4, oss.str(), __FILE__, __LINE__);
333                 }
334         }
335         /*!
336          * output warn log.
337          *
338          * @param   category that logging matter occured
339          * @param   log message id
340          * @param   log message
341          * @param   current file
342          * @param   current line
343          * @retrun  void
344          */
345         virtual inline void putLogWarn(LOG_CATEGORY_TAG cat,
346                                        const unsigned int message_id,
347                                        const std::string &message,
348                                        const char *file,
349                                        int line) {
350                 std::stringstream buf;
351
352                 switch (cat) {
353                 case    LOG_CAT_PROTOCOL:
354
355                         buf << boost::format("%s%d%07d %s %s")
356                             % LOGGER_PROCESS_PROTOCOL_MODULE_ID
357                             % LOG_LV_WARN
358                             % message_id
359                             % message.c_str()
360                             % hostname;
361
362                         break;
363                 case    LOG_CAT_SCHEDULE:
364
365                         buf << boost::format("%s%d%07d %s %s")
366                             % LOGGER_PROCESS_SCHEDULE_MODULE_ID
367                             % LOG_LV_WARN
368                             % message_id
369                             % message.c_str()
370                             % hostname;
371
372                         break;
373                 default:
374
375                         buf << boost::format("%s%d%02d%05d %s %s")
376                             % LOGGER_PROCESS_ID
377                             % LOG_LV_WARN
378                             % cat
379                             % message_id
380                             % message.c_str()
381                             % hostname;
382
383                 }
384
385                 try {
386                         category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
387                         log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getWarn(),
388                                         buf.str(),
389                                         log4cxx::spi::LocationInfo(file, "", line));
390                         // send_trap
391                         if (logtrap_enabled.get() == 1) {
392                                 LOG_LEVEL_TAG tmp_level;
393                                 {
394                                         rd_scoped_lock lock(logtrap_level_mutex);
395                                         tmp_level = logtrap_level;
396                                 }
397                                 if ( (tmp_level >= LOG_LV_WARN) &&
398                                       snmp_send_trap_func       &&
399                                       (LOG_CAT_L7VSD_SNMPAGENT != cat)) {
400                                         trapmessage trap_msg;
401                                         trap_msg.type = trapmessage::WARN_LOG;
402                                         trap_msg.message = buf.str();
403                                         error_code err;
404                                         //send trap message
405                                         snmp_send_trap_func(trap_msg, err);
406                                 }
407                         }
408                 } catch (const std::exception &ex) {
409                         std::ostringstream oss;
410                         oss << "Logging Error (Warn Log) : " << ex.what();
411                         errorConf(5, oss.str(), __FILE__, __LINE__);
412                 }
413         }
414         /*!
415          * output info log.
416          *
417          * @param   category that logging matter occured
418          * @param   log message id
419          * @param   log message
420          * @param   current file
421          * @param   current line
422          * @retrun  void
423          */
424         virtual inline void putLogInfo(LOG_CATEGORY_TAG cat,
425                                        const unsigned int message_id,
426                                        const std::string &message,
427                                        const char *file,
428                                        int line) {
429                 std::stringstream    buf;
430
431                 switch (cat) {
432                 case    LOG_CAT_PROTOCOL:
433
434                         buf << boost::format("%s%d%07d %s %s")
435                             % LOGGER_PROCESS_PROTOCOL_MODULE_ID
436                             % LOG_LV_INFO
437                             % message_id
438                             % message.c_str()
439                             % hostname;
440
441                         break;
442                 case    LOG_CAT_SCHEDULE:
443
444                         buf << boost::format("%s%d%07d %s %s")
445                             % LOGGER_PROCESS_SCHEDULE_MODULE_ID
446                             % LOG_LV_INFO
447                             % message_id
448                             % message.c_str()
449                             % hostname;
450
451                         break;
452                 default:
453
454                         buf << boost::format("%s%d%02d%05d %s %s")
455                             % LOGGER_PROCESS_ID
456                             % LOG_LV_INFO
457                             % cat
458                             % message_id
459                             % message.c_str()
460                             % hostname;
461
462                 }
463
464                 try {
465                         category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
466                         log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getInfo(),
467                                         buf.str(),
468                                         log4cxx::spi::LocationInfo(file, "", line));
469
470                         // send_trap
471                         if (logtrap_enabled.get() == 1) {
472                                 LOG_LEVEL_TAG tmp_level;
473                                 {
474                                         rd_scoped_lock lock(logtrap_level_mutex);
475                                         tmp_level = logtrap_level;
476                                 }
477                                 if ( (tmp_level >= LOG_LV_INFO) &&
478                                       snmp_send_trap_func       &&
479                                       (LOG_CAT_L7VSD_SNMPAGENT != cat)) {
480                                         trapmessage trap_msg;
481                                         trap_msg.type = trapmessage::INFO_LOG;
482                                         trap_msg.message = buf.str();
483                                         error_code err;
484                                         //send trap message
485                                         snmp_send_trap_func(trap_msg, err);
486                                 }
487                         }
488                 } catch (const std::exception &ex) {
489                         std::ostringstream oss;
490                         oss << "Logging Error (Info Log) : " << ex.what();
491                         errorConf(6, oss.str(), __FILE__, __LINE__);
492                 }
493         }
494         /*!
495          * output debug log.
496          *
497          * @param   category that logging matter occured
498          * @param   log message id
499          * @param   log message
500          * @param   current file
501          * @param   current line
502          * @retrun  void
503          */
504         virtual inline void putLogDebug(LOG_CATEGORY_TAG cat,
505                                         const unsigned int message_id,
506                                         const std::string &message,
507                                         const char *file,
508                                         int line) {
509                 std::stringstream    buf;
510                 std::string logger_process_id = LOGGER_PROCESS_ID;
511
512                 switch (cat) {
513                 case    LOG_CAT_PROTOCOL:
514
515                         buf << boost::format("%s%d%07d %s %s")
516                             % LOGGER_PROCESS_PROTOCOL_MODULE_ID
517                             % LOG_LV_DEBUG
518                             % message_id
519                             % message.c_str()
520                             % hostname;
521
522                         break;
523                 case    LOG_CAT_SCHEDULE:
524
525                         buf << boost::format("%s%d%07d %s %s")
526                             % LOGGER_PROCESS_SCHEDULE_MODULE_ID
527                             % LOG_LV_DEBUG
528                             % message_id
529                             % message.c_str()
530                             % hostname;
531
532                         break;
533                 default:
534
535                         buf << boost::format("%s%d%02d%05d %s %s")
536                             % LOGGER_PROCESS_ID
537                             % LOG_LV_DEBUG
538                             % cat
539                             % message_id
540                             % message.c_str()
541                             % hostname;
542
543                 }
544
545
546                 try {
547                         category_name_map_type::iterator categoryname_itr = category_name_map.find(cat);
548                         log4cxx::Logger::getLogger(categoryname_itr->second)->forcedLog(log4cxx::Level::getDebug(),
549                                         buf.str(), log4cxx::spi::LocationInfo(file, "", line));
550                         // send_trap
551                         if (logtrap_enabled.get() == 1) {
552                                 LOG_LEVEL_TAG tmp_level;
553                                 {
554                                         rd_scoped_lock lock(logtrap_level_mutex);
555                                         tmp_level = logtrap_level;
556                                 }
557                                 if ( (tmp_level >= LOG_LV_DEBUG) &&
558                                       snmp_send_trap_func        &&
559                                       (LOG_CAT_L7VSD_SNMPAGENT != cat)) {
560                                         trapmessage trap_msg;
561                                         trap_msg.type = trapmessage::DEBUG_LOG;
562                                         trap_msg.message = buf.str();
563
564                                         error_code err;
565                                         //send trap message
566                                         snmp_send_trap_func(trap_msg, err);
567                                 }
568                         }
569                 } catch (const std::exception &ex) {
570                         std::ostringstream oss;
571                         oss << "Logging Error (Debug Log) : " << ex.what();
572                         errorConf(7, oss.str(), __FILE__, __LINE__);
573                 }
574         }
575
576         /*!
577          * set snmp sendtrap function
578          *
579          * @param   snmp send trap function object
580          * @retrun  void
581          */
582          void    set_snmp_send_trap_func(const snmp_send_trap_func_type func) {
583                 snmp_send_trap_func = func;
584         }
585
586         /*!
587          * set log trap enable
588          * @retrun  void
589          */
590         void    logtrap_enable() {
591                 logtrap_enabled = true;
592         }
593
594         /*!
595          * set log trap disable         
596          * @retrun  void
597          */
598         void    logtrap_disable() {
599                 logtrap_enabled = false;
600         }
601
602         /*!
603          * set log trap level
604          * @param   log trap level
605          * @retrun  void
606          */
607         void    set_logtrap_level(LOG_LEVEL_TAG in_logtrap_level) {
608                 rw_scoped_lock lock(logtrap_level_mutex);
609                 logtrap_level = in_logtrap_level;
610         }
611
612
613 protected:
614         //! default constructor initialize member variables.
615         LoggerImpl();
616
617         //! cpoy constructor disable
618         LoggerImpl(const LoggerImpl &);
619
620         //! operator= disable
621         LoggerImpl &operator=(const LoggerImpl &);
622
623         //! LOG_LEVEL_TAG to log4cxx::LevelPtr transrator
624         virtual inline const log4cxx::LevelPtr toLevel(LOG_LEVEL_TAG level)    {
625                 return log4cxx::Level::toLevel(levelTable[level]);
626         }
627
628         //! if error occured, switch appenders to syslogappender and fileappender(/dev/console)
629         virtual void errorConf(unsigned int messageId,
630                                const std::string &errorMessage,
631                                const char *file,
632                                int line);
633
634         virtual void logic_error(const unsigned int, const std::string &, const char *, const unsigned int);
635
636         /*
637             //! log4cxx::LevelPtr to LOG_LEVEL_TAG transrator
638             virtual inline LOG_LEVEL_TAG toLevelTag(const log4cxx::LevelPtr level){
639                 int levelInt = level->toInt();
640                 switch (levelInt) {
641                 case log4cxx::Level::DEBUG_INT:
642                     return LOG_LV_DEBUG;
643                 case log4cxx::Level::INFO_INT:
644                     return LOG_LV_INFO;
645                 case log4cxx::Level::WARN_INT:
646                     return LOG_LV_WARN;
647                 case log4cxx::Level::ERROR_INT:
648                     return LOG_LV_ERROR;
649                 case log4cxx::Level::FATAL_INT:
650                     return LOG_LV_FATAL;
651                 default:
652                     return LOG_LV_DEBUG;
653                 }
654             }
655         */
656
657         //! destructor.
658         virtual ~LoggerImpl() {}
659         //! initialized flag
660         bool initialized;
661         //! hostname
662         std::string hostname;
663
664         //log4cxx::Level* levelTable[LOGGER_LEVEL_NUM];
665         int    levelTable[LOGGER_LEVEL_NUM];
666
667         //! category - loglevel hash map
668         category_level_map_type    category_level_map;
669         category_level_read_map_type category_level_read_map;
670         //! category string -> logcateogry hash map
671         name_category_map_type    name_category_map;
672         //! log_category -> category string hash map
673         category_name_map_type    category_name_map;
674
675         appender_property    normal_log_property;
676         appender_property    access_log_property;
677
678         //! snmp trap function
679         snmp_send_trap_func_type    snmp_send_trap_func;
680
681         //! snmp log trap enable flag
682         atomic<unsigned int>    logtrap_enabled;
683
684         //! snmp log trap level
685         LOG_LEVEL_TAG    logtrap_level;
686
687         //! snmp log trap level mutex
688         wr_mutex    logtrap_level_mutex;
689
690 };
691
692 }    //namespace l7vs
693 #endif    //__LOGGER_IMPL_H__