LCOV - code coverage report
Current view: top level - log - logger.h (source / functions) Hit Total Coverage
Test: report.info Lines: 11 11 100.0 %
Date: 2012-05-15 Functions: 3 4 75.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 5 8 62.5 %

           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                 :            : #ifndef __LOGGER_H
      16                 :            : #define __LOGGER_H
      17                 :            : 
      18                 :            : #include <cassert>
      19                 :            : #include <cstdlib>
      20                 :            : #include <string>
      21                 :            : #include <cstring>
      22                 :            : 
      23                 :            : #include <exceptions/exceptions.h>
      24                 :            : #include <log/logger_level.h>
      25                 :            : #include <log/message_types.h>
      26                 :            : #include <log/log_formatter.h>
      27                 :            : 
      28                 :            : 
      29                 :            : namespace isc {
      30                 :            : namespace log {
      31                 :            : 
      32                 :            : /// \page LoggingApi Logging API
      33                 :            : /// \section LoggingApiOverview Overview
      34                 :            : /// BIND 10 logging uses the concepts of the widely-used Java logging
      35                 :            : /// package log4j (http://logging.apache.log/log4j), albeit implemented 
      36                 :            : /// in C++ using an open-source port.  Features of the system are:
      37                 :            : /// 
      38                 :            : /// - Within the code objects - known as loggers - can be created and
      39                 :            : /// used to log messages.  These loggers have names; those with the
      40                 :            : /// same name share characteristics (such as output destination).
      41                 :            : /// - Loggers have a hierarchical relationship, with each logger being
      42                 :            : /// the child of another logger, except for the top of the hierarchy, the
      43                 :            : /// root logger.  If a logger does not log a message, it is passed to the
      44                 :            : /// parent logger.
      45                 :            : /// - Messages can be logged at severity levels of FATAL, ERROR, WARN, INFO
      46                 :            : /// or DEBUG.  The DEBUG level has further sub-levels numbered 0 (least
      47                 :            : /// informative) to 99 (most informative).
      48                 :            : /// - Each logger has a severity level set associated with it.  When a
      49                 :            : /// message is logged, it is output only if it is logged at a level equal
      50                 :            : /// to the logger severity level or greater, e.g. if the logger's severity
      51                 :            : /// is WARN, only messages logged at WARN, ERROR or FATAL will be output.
      52                 :            : /// 
      53                 :            : /// \section LoggingApiLoggerNames BIND 10 Logger Names
      54                 :            : /// Within BIND 10, the root logger root logger is given the name of the
      55                 :            : /// program (via the stand-alone function setRootLoggerName()). Other loggers
      56                 :            : /// are children of the root logger and are named "<program>.<sublogger>".
      57                 :            : /// This name appears in logging output, allowing users to identify both
      58                 :            : /// the BIND 10 program and the component within the program that generated
      59                 :            : /// the message.
      60                 :            : /// 
      61                 :            : /// When creating a logger, the abbreviated name "<sublogger>" can be used;
      62                 :            : /// the program name will be prepended to it when the logger is created.
      63                 :            : /// In this way, individual libraries can have their own loggers without
      64                 :            : /// worrying about the program in which they are used, but:
      65                 :            : /// - The origin of the message will be clearly identified.
      66                 :            : /// - The same component can have different options (e.g. logging severity)
      67                 :            : /// in different programs at the same time.
      68                 :            : /// 
      69                 :            : /// \section LoggingApiLoggingMessages Logging Messages
      70                 :            : /// Instead of embedding the text of messages within the code, each message
      71                 :            : /// is referred to using a symbolic name.  The logging code uses this name as
      72                 :            : /// a key in a dictionary from which the message text is obtained.  Such a
      73                 :            : /// system allows for the optional replacement of message text at run time.
      74                 :            : /// More details about the message dictionary (and the compiler used to create
      75                 :            : /// the symbol definitions) can be found in other modules in the src/lib/log
      76                 :            : /// directory.
      77                 :            : ///
      78                 :            : /// \section LoggingApiImplementationIssues Implementation Issues
      79                 :            : /// Owing to the way that the logging is implemented, notably that loggers can
      80                 :            : /// be declared as static external objects, there is a restriction on the
      81                 :            : /// length of the name of a logger component (i.e. the length of
      82                 :            : /// the string passed to the Logger constructor) to a maximum of 31 characters.
      83                 :            : /// There is no reason for this particular value other than limiting the amount
      84                 :            : /// of memory used.  It is defined by the constant Logger::MAX_LOGGER_NAME_SIZE,
      85                 :            : /// and can be made larger (or smaller) if so desired.  Note however, using a
      86                 :            : /// logger name larger than this limit will cause an assertion failure.
      87                 :            : 
      88                 :            : class LoggerImpl;   // Forward declaration of the implementation class
      89                 :            : 
      90                 :            : /// \brief Logging Not Initialized
      91                 :            : ///
      92                 :            : /// Exception thrown if an attempt is made to access a logging function
      93                 :            : /// if the logging system has not been initialized.
      94                 :          2 : class LoggingNotInitialized : public isc::Exception {
      95                 :            : public:
      96                 :            :     LoggingNotInitialized(const char* file, size_t line, const char* what) :
      97                 :          4 :         isc::Exception(file, line, what)
      98                 :            :     {}
      99                 :            : };
     100                 :            : 
     101                 :            : /// \brief Logger Class
     102                 :            : ///
     103                 :            : /// This class is the main class used for logging.  Use comprises:
     104                 :            : ///
     105                 :            : /// 1. Constructing a logger by instantiating it with a specific name. (If the
     106                 :            : /// same logger is in multiple functions within a file, overhead can be
     107                 :            : /// minimised by declaring it as a file-wide static variable.)
     108                 :            : /// 2. Using the error(), info() etc. methods to log an error.  (However, it is
     109                 :            : /// recommended to use the LOG_ERROR, LOG_INFO etc. macros defined in macros.h.
     110                 :            : /// These will avoid the potentially-expensive evaluation of arguments if the
     111                 :            : /// severity is such that the message will be suppressed.)
     112                 :            : 
     113                 :            : class Logger {
     114                 :            : public:
     115                 :            :     /// Maximum size of a logger name
     116                 :            :     static const size_t MAX_LOGGER_NAME_SIZE = 31;
     117                 :            : 
     118                 :            :     /// \brief Constructor
     119                 :            :     ///
     120                 :            :     /// Creates/attaches to a logger of a specific name.
     121                 :            :     ///
     122                 :            :     /// \param name Name of the logger.  If the name is that of the root name,
     123                 :            :     /// this creates an instance of the root logger; otherwise it creates a
     124                 :            :     /// child of the root logger.
     125                 :            :     ///
     126                 :            :     /// \note The name of the logger may be no longer than MAX_LOGGER_NAME_SIZE
     127                 :            :     /// else the program will halt with an assertion failure.  This restriction
     128                 :            :     /// allows loggers to be declared statically: the name is stored in a
     129                 :            :     /// fixed-size array to avoid the need to allocate heap storage during
     130                 :            :     /// program initialization (which causes problems on some operating
     131                 :            :     /// systems).
     132                 :            :     ///
     133                 :            :     /// \note Note also that there is no constructor taking a std::string. This
     134                 :            :     /// minimises the possibility of initializing a static logger with a
     135                 :            :     /// string, so leading to problems mentioned above.
     136                 :        891 :     Logger(const char* name) : loggerptr_(NULL) {
     137         [ -  + ]:        250 :         assert(std::strlen(name) < sizeof(name_));
     138                 :            :         // Do the copy.  Note that the assertion above has checked that the
     139                 :            :         // contents of "name" and a trailing null will fit within the space
     140                 :            :         // allocated for name_, so we could use strcpy here and be safe.
     141                 :            :         // However, a bit of extra paranoia doesn't hurt.
     142                 :        891 :         std::strncpy(name_, name, sizeof(name_));
     143 [ -  + ][ -  + ]:        891 :         assert(name_[sizeof(name_) - 1] == '\0');
     144                 :         57 :     }
     145                 :            : 
     146                 :            :     /// \brief Destructor
     147                 :            :     virtual ~Logger();
     148                 :            : 
     149                 :            :     /// \brief The formatter used to replace placeholders
     150                 :            :     typedef isc::log::Formatter<Logger> Formatter;
     151                 :            : 
     152                 :            :     /// \brief Get Name of Logger
     153                 :            :     ///
     154                 :            :     /// \return The full name of the logger (including the root name)
     155                 :            :     virtual std::string getName();
     156                 :            : 
     157                 :            :     /// \brief Set Severity Level for Logger
     158                 :            :     ///
     159                 :            :     /// Sets the level at which this logger will log messages.  If none is set,
     160                 :            :     /// the level is inherited from the parent.
     161                 :            :     ///
     162                 :            :     /// \param severity Severity level to log
     163                 :            :     /// \param dbglevel If the severity is DEBUG, this is the debug level.
     164                 :            :     /// This can be in the range 1 to 100 and controls the verbosity.  A value
     165                 :            :     /// outside these limits is silently coerced to the nearest boundary.
     166                 :            :     virtual void setSeverity(isc::log::Severity severity, int dbglevel = 1);
     167                 :            : 
     168                 :            :     /// \brief Get Severity Level for Logger
     169                 :            :     ///
     170                 :            :     /// \return The current logging level of this logger.  In most cases though,
     171                 :            :     /// the effective logging level is what is required.
     172                 :            :     virtual isc::log::Severity getSeverity();
     173                 :            : 
     174                 :            :     /// \brief Get Effective Severity Level for Logger
     175                 :            :     ///
     176                 :            :     /// \return The effective severity level of the logger.  This is the same
     177                 :            :     /// as getSeverity() if the logger has a severity level set, but otherwise
     178                 :            :     /// is the severity of the parent.
     179                 :            :     virtual isc::log::Severity getEffectiveSeverity();
     180                 :            : 
     181                 :            :     /// \brief Return DEBUG Level
     182                 :            :     ///
     183                 :            :     /// \return Current setting of debug level.  This is returned regardless of
     184                 :            :     /// whether the severity is set to debug.
     185                 :            :     virtual int getDebugLevel();
     186                 :            : 
     187                 :            :     /// \brief Get Effective Debug Level for Logger
     188                 :            :     ///
     189                 :            :     /// \return The effective debug level of the logger.  This is the same
     190                 :            :     /// as getDebugLevel() if the logger has a debug level set, but otherwise
     191                 :            :     /// is the debug level of the parent.
     192                 :            :     virtual int getEffectiveDebugLevel();
     193                 :            : 
     194                 :            :     /// \brief Returns if Debug Message Should Be Output
     195                 :            :     ///
     196                 :            :     /// \param dbglevel Level for which debugging is checked.  Debugging is
     197                 :            :     /// enabled only if the logger has DEBUG enabled and if the dbglevel
     198                 :            :     /// checked is less than or equal to the debug level set for the logger.
     199                 :            :     virtual bool isDebugEnabled(int dbglevel = MIN_DEBUG_LEVEL);
     200                 :            : 
     201                 :            :     /// \brief Is INFO Enabled?
     202                 :            :     virtual bool isInfoEnabled();
     203                 :            : 
     204                 :            :     /// \brief Is WARNING Enabled?
     205                 :            :     virtual bool isWarnEnabled();
     206                 :            : 
     207                 :            :     /// \brief Is ERROR Enabled?
     208                 :            :     virtual bool isErrorEnabled();
     209                 :            : 
     210                 :            :     /// \brief Is FATAL Enabled?
     211                 :            :     virtual bool isFatalEnabled();
     212                 :            : 
     213                 :            :     /// \brief Output Debug Message
     214                 :            :     ///
     215                 :            :     /// \param dbglevel Debug level, ranging between 0 and 99.  Higher numbers
     216                 :            :     /// are used for more verbose output.
     217                 :            :     /// \param ident Message identification.
     218                 :            :     Formatter debug(int dbglevel, const MessageID& ident);
     219                 :            : 
     220                 :            :     /// \brief Output Informational Message
     221                 :            :     ///
     222                 :            :     /// \param ident Message identification.
     223                 :            :     Formatter info(const MessageID& ident);
     224                 :            : 
     225                 :            :     /// \brief Output Warning Message
     226                 :            :     ///
     227                 :            :     /// \param ident Message identification.
     228                 :            :     Formatter warn(const MessageID& ident);
     229                 :            : 
     230                 :            :     /// \brief Output Error Message
     231                 :            :     ///
     232                 :            :     /// \param ident Message identification.
     233                 :            :     Formatter error(const MessageID& ident);
     234                 :            : 
     235                 :            :     /// \brief Output Fatal Message
     236                 :            :     ///
     237                 :            :     /// \param ident Message identification.
     238                 :            :     Formatter fatal(const MessageID& ident);
     239                 :            : 
     240                 :            :     /// \brief Equality
     241                 :            :     ///
     242                 :            :     /// Check if two instances of this logger refer to the same stream.
     243                 :            :     ///
     244                 :            :     /// \return true if the logger objects are instances of the same logger.
     245                 :            :     bool operator==(Logger& other);
     246                 :            : 
     247                 :            : private:
     248                 :            :     friend class isc::log::Formatter<Logger>;
     249                 :            : 
     250                 :            :     /// \brief Raw output function
     251                 :            :     ///
     252                 :            :     /// This is used by the formatter to output formatted output.
     253                 :            :     ///
     254                 :            :     /// \param severity Severity of the message being output.
     255                 :            :     /// \param message Text of the message to be output.
     256                 :            :     void output(const Severity& severity, const std::string& message);
     257                 :            : 
     258                 :            :     /// \brief Copy Constructor
     259                 :            :     ///
     260                 :            :     /// Disabled (marked private) as it makes no sense to copy the logger -
     261                 :            :     /// just create another one of the same name.
     262                 :            :     Logger(const Logger&);
     263                 :            : 
     264                 :            :     /// \brief Assignment Operator
     265                 :            :     ///
     266                 :            :     /// Disabled (marked private) as it makes no sense to copy the logger -
     267                 :            :     /// just create another one of the same name.
     268                 :            :     Logger& operator=(const Logger&);
     269                 :            : 
     270                 :            :     /// \brief Initialize Implementation
     271                 :            :     ///
     272                 :            :     /// Returns the logger pointer.  If not yet set, the implementation class is
     273                 :            :     /// initialized.
     274                 :            :     ///
     275                 :            :     /// The main reason for this is to allow loggers to be declared statically
     276                 :            :     /// before the underlying logging system is initialized.  However, any
     277                 :            :     /// attempt to access a logging method on any logger before initialization -
     278                 :            :     /// regardless of whether is is statically or automatically declared -  will
     279                 :            :     /// cause a "LoggingNotInitialized" exception to be thrown.
     280                 :            :     ///
     281                 :            :     /// \return Returns pointer to implementation
     282                 :     162158 :     LoggerImpl* getLoggerPtr() {
     283         [ +  + ]:     162158 :         if (!loggerptr_) {
     284                 :        171 :             initLoggerImpl();
     285                 :            :         }
     286                 :     162156 :         return (loggerptr_);
     287                 :            :     }
     288                 :            : 
     289                 :            :     /// \brief Initialize Underlying Implementation and Set loggerptr_
     290                 :            :     void initLoggerImpl();
     291                 :            : 
     292                 :            :     LoggerImpl* loggerptr_;                  ///< Pointer to underlying logger
     293                 :            :     char        name_[MAX_LOGGER_NAME_SIZE + 1]; ///< Copy of the logger name
     294                 :            : };
     295                 :            : 
     296                 :            : } // namespace log
     297                 :            : } // namespace isc
     298                 :            : 
     299                 :            : 
     300                 :            : #endif // __LOGGER_H

Generated by: LCOV version 1.9