LCOV - code coverage report
Current view: top level - log - logger_level_impl.cc (source / functions) Hit Total Coverage
Test: report.info Lines: 53 56 94.6 %
Date: 2012-05-15 Functions: 6 6 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 43 70 61.4 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
       2                 :            : //
       3                 :            : // Permission to use, copy, modify, and/or distribute this software for any
       4                 :            : // purpose with or without fee is hereby granted, provided that the above
       5                 :            : // copyright notice and this permission notice appear in all copies.
       6                 :            : //
       7                 :            : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
       8                 :            : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
       9                 :            : // AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
      10                 :            : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      11                 :            : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      12                 :            : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      13                 :            : // PERFORMANCE OF THIS SOFTWARE.
      14                 :            : 
      15                 :            : #include <algorithm>
      16                 :            : #include <string.h>
      17                 :            : #include <iostream>
      18                 :            : #include <boost/lexical_cast.hpp>
      19                 :            : 
      20                 :            : #include <log4cplus/logger.h>
      21                 :            : 
      22                 :            : #include <log/logger_level.h>
      23                 :            : #include <log/logger_level_impl.h>
      24                 :            : #include <log/logimpl_messages.h>
      25                 :            : #include <log/macros.h>
      26                 :            : 
      27                 :            : using namespace log4cplus;
      28                 :            : using namespace std;
      29                 :            : 
      30                 :            : namespace {
      31                 :        141 : isc::log::Logger logger("log");
      32                 :            : }
      33                 :            : 
      34                 :            : namespace isc {
      35                 :            : namespace log {
      36                 :            : 
      37                 :            : // Convert BIND 10 level to a log4cplus logging level.
      38                 :            : log4cplus::LogLevel
      39                 :      79363 : LoggerLevelImpl::convertFromBindLevel(const Level& level) {
      40                 :            : 
      41                 :            :     // BIND 10 logging levels are small integers so we can do a table lookup
      42                 :            :     static const log4cplus::LogLevel log4cplus_levels[] = {
      43                 :            :         log4cplus::NOT_SET_LOG_LEVEL,
      44                 :            :         log4cplus::DEBUG_LOG_LEVEL,
      45                 :            :         log4cplus::INFO_LOG_LEVEL,
      46                 :            :         log4cplus::WARN_LOG_LEVEL,
      47                 :            :         log4cplus::ERROR_LOG_LEVEL,
      48                 :            :         log4cplus::FATAL_LOG_LEVEL,
      49                 :            :         log4cplus::OFF_LOG_LEVEL
      50                 :            :     };
      51                 :            : 
      52                 :            :     // ... with compile-time checks to ensure that table indexes are correct.
      53                 :            :     BOOST_STATIC_ASSERT(static_cast<int>(DEFAULT) == 0);
      54                 :            :     BOOST_STATIC_ASSERT(static_cast<int>(DEBUG) == 1);
      55                 :            :     BOOST_STATIC_ASSERT(static_cast<int>(INFO) == 2);
      56                 :            :     BOOST_STATIC_ASSERT(static_cast<int>(WARN) == 3);
      57                 :            :     BOOST_STATIC_ASSERT(static_cast<int>(ERROR) == 4);
      58                 :            :     BOOST_STATIC_ASSERT(static_cast<int>(FATAL) == 5);
      59                 :            :     BOOST_STATIC_ASSERT(static_cast<int>(NONE) == 6);
      60                 :            : 
      61                 :            :     // Do the conversion
      62         [ +  + ]:      79363 :     if (level.severity == DEBUG) {
      63                 :            : 
      64                 :            :         // Debug severity, so the log4cplus level returned depends on the
      65                 :            :         // debug level.  Silently limit the debug level to the range
      66                 :            :         // MIN_DEBUG_LEVEL to MAX_DEBUG_LEVEL (avoids the hassle of throwing
      67                 :            :         // and catching exceptions and besides, this is for debug information).
      68                 :            :         int limited = std::max(MIN_DEBUG_LEVEL,
      69                 :     237054 :                                std::min(level.dbglevel, MAX_DEBUG_LEVEL));
      70                 :            :         LogLevel newlevel = static_cast<int>(DEBUG_LOG_LEVEL -
      71                 :      79018 :                                             (limited - MIN_DEBUG_LEVEL));
      72                 :      79018 :         return (static_cast<log4cplus::LogLevel>(newlevel));
      73                 :            : 
      74                 :            :     } else {
      75                 :            : 
      76                 :            :         // Can do a table lookup to speed things up.  There is no need to check
      77                 :            :         // that the index is out of range.  That the variable is of type
      78                 :            :         // isc::log::Severity ensures that it must be one of the Severity enum
      79                 :            :         // members - conversion of a numeric value to an enum is not permitted.
      80                 :      79363 :         return (log4cplus_levels[level.severity]);
      81                 :            :     }
      82                 :            : }
      83                 :            : 
      84                 :            : // Convert log4cplus logging level to BIND 10 debug level.  It is up to the
      85                 :            : // caller to validate that the debug level is valid.
      86                 :            : Level
      87                 :        170 : LoggerLevelImpl::convertToBindLevel(const log4cplus::LogLevel loglevel) {
      88                 :            : 
      89                 :            :     // Not easy to do a table lookup as the numerical values of log4cplus levels
      90                 :            :     // are quite high.
      91         [ +  + ]:        170 :     if (loglevel <= log4cplus::NOT_SET_LOG_LEVEL) {
      92                 :         11 :         return (Level(DEFAULT));
      93                 :            : 
      94         [ +  + ]:        159 :     } else if (loglevel <= log4cplus::DEBUG_LOG_LEVEL) {
      95                 :            : 
      96                 :            :         // Debug severity, so extract the debug level from the numeric value.
      97                 :            :         // If outside the limits, change the severity to the level above or
      98                 :            :         // below.
      99                 :            :         int dbglevel = MIN_DEBUG_LEVEL +
     100                 :            :                        static_cast<int>(log4cplus::DEBUG_LOG_LEVEL) -
     101                 :        126 :                        static_cast<int>(loglevel);
     102         [ +  + ]:        126 :         if (dbglevel > MAX_DEBUG_LEVEL) {
     103                 :          2 :             return (Level(DEFAULT));
     104         [ -  + ]:        124 :         } else if (dbglevel < MIN_DEBUG_LEVEL) {
     105                 :          0 :             return (Level(INFO));
     106                 :            :         }
     107                 :        124 :         return (Level(DEBUG, dbglevel));
     108                 :            : 
     109         [ +  + ]:         33 :     } else if (loglevel <= log4cplus::INFO_LOG_LEVEL) {
     110                 :         13 :         return (Level(INFO));
     111                 :            : 
     112         [ +  + ]:         20 :     } else if (loglevel <= log4cplus::WARN_LOG_LEVEL) {
     113                 :          7 :         return (Level(WARN));
     114                 :            : 
     115         [ +  + ]:         13 :     } else if (loglevel <= log4cplus::ERROR_LOG_LEVEL) {
     116                 :          6 :         return (Level(ERROR));
     117                 :            : 
     118         [ +  + ]:          7 :     } else if (loglevel <= log4cplus::FATAL_LOG_LEVEL) {
     119                 :          5 :         return (Level(FATAL));
     120                 :            : 
     121                 :            :     }
     122                 :            : 
     123                 :        170 :     return (Level(NONE));
     124                 :            : }
     125                 :            : 
     126                 :            : 
     127                 :            : // Convert string to appropriate logging level
     128                 :            : log4cplus::LogLevel
     129                 :        211 : LoggerLevelImpl::logLevelFromString(const log4cplus::tstring& level) {
     130                 :            : 
     131                 :        422 :     std::string name = level;       // Get to known type
     132                 :        211 :     size_t length = name.size();    // Length of the string
     133                 :            : 
     134         [ +  + ]:        211 :     if (length < 5) {
     135                 :            : 
     136                 :            :         // String can't possibly start DEBUG so we don't know what it is.
     137                 :            :         // As per documentation, return NOT_SET level.
     138                 :            :         return (NOT_SET_LOG_LEVEL);
     139                 :            :     }
     140                 :            :     else {
     141         [ +  + ]:        210 :         if (strncasecmp(name.c_str(), "DEBUG", 5) == 0) {
     142                 :            : 
     143                 :            :             // String starts "DEBUG" (or "debug" or any case mixture).  The
     144                 :            :             // rest of the string - if any - should be a number.
     145         [ +  - ]:        209 :             if (length == 5) {
     146                 :            : 
     147                 :            :                 // It is plain "DEBUG".  Take this as level 0.
     148                 :            :                 return (DEBUG_LOG_LEVEL);
     149                 :            :             }
     150                 :            :             else {
     151                 :            : 
     152                 :            :                 // Try converting the remainder to an integer.  The "5" is
     153                 :            :                 // the length of the string "DEBUG".  Note that if the number
     154                 :            :                 // is outside the range of debug levels, it is coerced to the
     155                 :            :                 // nearest limit.  Thus a level of DEBUG509 will end up as
     156                 :            :                 // if DEBUG99 has been specified.
     157                 :            :                 try {
     158         [ +  - ]:        418 :                     int dbglevel = boost::lexical_cast<int>(name.substr(5));
     159         [ +  + ]:        209 :                     if (dbglevel < MIN_DEBUG_LEVEL) {
     160 [ +  - ][ +  - ]:         10 :                         LOG_WARN(logger, LOGIMPL_BELOW_MIN_DEBUG).arg(dbglevel)
         [ +  - ][ +  - ]
                 [ +  - ]
     161         [ +  - ]:          5 :                             .arg(MIN_DEBUG_LEVEL);
     162                 :          5 :                         dbglevel = MIN_DEBUG_LEVEL;
     163                 :            : 
     164         [ +  + ]:        204 :                     } else if (dbglevel > MAX_DEBUG_LEVEL) {
     165 [ +  - ][ +  - ]:          8 :                         LOG_WARN(logger, LOGIMPL_ABOVE_MAX_DEBUG).arg(dbglevel)
         [ +  - ][ +  - ]
                 [ +  - ]
     166         [ +  - ]:          4 :                             .arg(MAX_DEBUG_LEVEL);
     167                 :          4 :                         dbglevel = MAX_DEBUG_LEVEL;
     168                 :            : 
     169                 :            :                     }
     170         [ +  - ]:        209 :                     return convertFromBindLevel(Level(DEBUG, dbglevel));
     171                 :            :                 }
     172         [ #  # ]:          0 :                 catch (boost::bad_lexical_cast&) {
     173 [ #  # ][ #  # ]:          0 :                     LOG_ERROR(logger, LOGIMPL_BAD_DEBUG_STRING).arg(name);
         [ #  # ][ #  # ]
     174                 :            :                     return (NOT_SET_LOG_LEVEL);
     175                 :            :                 }
     176                 :            :             }
     177                 :            :         } else {
     178                 :            : 
     179                 :            :             // Unknown string - return default.  Log4cplus will call any other
     180                 :            :             // registered conversion functions to interpret it.
     181                 :            :             return (NOT_SET_LOG_LEVEL);
     182                 :            :         }
     183                 :            :     }
     184                 :            : }
     185                 :            : 
     186                 :            : // Convert logging level to string.  If the level is a valid debug level,
     187                 :            : // return the string DEBUG, else return the empty string.
     188                 :            : log4cplus::tstring
     189                 :        102 : LoggerLevelImpl::logLevelToString(log4cplus::LogLevel level) {
     190                 :        102 :     Level bindlevel = convertToBindLevel(level);
     191                 :        102 :     Severity& severity = bindlevel.severity;
     192                 :        102 :     int& dbglevel = bindlevel.dbglevel;
     193                 :            : 
     194 [ +  + ][ +  - ]:        102 :     if ((severity == DEBUG) &&
     195                 :            :         ((dbglevel >= MIN_DEBUG_LEVEL) && (dbglevel <= MAX_DEBUG_LEVEL))) {
     196                 :        100 :         return (tstring("DEBUG"));
     197                 :            :     }
     198                 :            : 
     199                 :            :     // Unknown, so return empty string for log4cplus to try other conversion
     200                 :            :     // functions.
     201                 :            :     return (tstring());
     202                 :            : }
     203                 :            : 
     204                 :            : // Initialization.  Register the conversion functions with the LogLevelManager.
     205                 :            : void
     206                 :        120 : LoggerLevelImpl::init() {
     207                 :            : 
     208                 :            :     // Get the singleton log-level manager.
     209                 :        120 :     LogLevelManager& manager = getLogLevelManager();
     210                 :            : 
     211                 :            :     // Register the conversion functions
     212                 :        120 :     manager.pushFromStringMethod(LoggerLevelImpl::logLevelFromString);
     213                 :        120 :     manager.pushToStringMethod(LoggerLevelImpl::logLevelToString);
     214                 :        120 : }
     215                 :            : 
     216                 :            : } // namespace log
     217                 :        141 : } // namespace isc

Generated by: LCOV version 1.9