src/core/log.h
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Jul 2009 08:15:48 +0200
changeset 4654 2eaebe77d66b
parent 3530 b1744fac67da
permissions -rw-r--r--
Added tag ns-3.5 for changeset c975274c9707
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * Copyright (c) 2006,2007 INRIA
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  *
    18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    19  */
    20 
    21 #ifndef __LOG_H__
    22 #define __LOG_H__
    23 
    24 #include <string>
    25 #include <iostream>
    26 #include <stdint.h>
    27 
    28 namespace ns3 {
    29 
    30 enum LogLevel {
    31   LOG_NONE           = 0x00000000, // no logging
    32 
    33   LOG_ERROR          = 0x00000001, // serious error messages only
    34   LOG_LEVEL_ERROR    = 0x00000001,
    35 
    36   LOG_WARN           = 0x00000002, // warning messages
    37   LOG_LEVEL_WARN     = 0x00000003,
    38 
    39   LOG_DEBUG          = 0x00000004, // rare ad-hoc debug messages
    40   LOG_LEVEL_DEBUG    = 0x00000007,
    41 
    42   LOG_INFO           = 0x00000008, // informational messages (e.g., banners)
    43   LOG_LEVEL_INFO     = 0x0000000f,
    44 
    45   LOG_FUNCTION       = 0x00000010, // function tracing
    46   LOG_LEVEL_FUNCTION = 0x0000001f, 
    47 
    48   LOG_LOGIC          = 0x00000020, // control flow tracing within functions
    49   LOG_LEVEL_LOGIC    = 0x0000003f,
    50 
    51   LOG_ALL            = 0x3fffffff, // print everything
    52   LOG_LEVEL_ALL      = LOG_ALL,
    53 
    54   LOG_PREFIX_FUNC    = 0x80000000, // prefix all trace prints with function
    55   LOG_PREFIX_TIME    = 0x40000000  // prefix all trace prints with simulation time
    56 };
    57 
    58 /**
    59  * \param name a log component name
    60  * \param level a logging level
    61  * \ingroup logging
    62  *
    63  * Enable the logging output associated with that log component.
    64  * The logging output can be later disabled with a call
    65  * to ns3::LogComponentDisable.
    66  *
    67  * Same as running your program with the NS_LOG environment
    68  * variable set as NS_LOG='name=level'
    69  */
    70 void LogComponentEnable (char const *name, enum LogLevel level);
    71 
    72 /**
    73  * \param level a logging level
    74  * \ingroup logging
    75  *
    76  * Enable the logging output for all registered log components.
    77  *
    78  * Same as running your program with the NS_LOG environment
    79  * variable set as NS_LOG='*=level'
    80  */
    81 void LogComponentEnableAll (enum LogLevel level);
    82 
    83 
    84 /**
    85  * \param name a log component name
    86  * \param level a logging level
    87  * \ingroup logging
    88  *
    89  * Disable the logging output associated with that log component.
    90  * The logging output can be later re-enabled with a call
    91  * to ns3::LogComponentEnable.
    92  */
    93 void LogComponentDisable (char const *name, enum LogLevel level);
    94 
    95 /**
    96  * \param level a logging level
    97  * \ingroup logging
    98  *
    99  * Disable all logging for all components.
   100  */
   101 void LogComponentDisableAll (enum LogLevel level);
   102 
   103 
   104 } // namespace ns3
   105 
   106 
   107 #ifdef NS3_LOG_ENABLE
   108 
   109 
   110 /**
   111  * \ingroup debugging
   112  * \defgroup logging Logging
   113  * \brief Logging functions and macros
   114  *
   115  * LOG functionality: macros which allow developers to
   116  * send information out on screen. All logging messages 
   117  * are disabled by default. To enable selected logging 
   118  * messages, use the ns3::LogComponentEnable
   119  * function or use the NS_LOG environment variable 
   120  *
   121  * Use the environment variable NS_LOG to define a ':'-separated list of
   122  * logging components to enable. For example (using bash syntax), 
   123  * NS_LOG="OlsrAgent" would enable one component at all log levels. 
   124  * NS_LOG="OlsrAgent:Ipv4L3Protocol" would enable two components, 
   125  * at all log levels, etc.  
   126  * NS_LOG="*" will enable all available log components at all levels.
   127  *
   128  * To control more selectively the log levels for each component, use
   129  * this syntax: NS_LOG='Component1=func|warn:Component2=error|debug'
   130  * This example would enable the 'func', and 'warn' log
   131  * levels for 'Component1' and the 'error' and 'debug' log levels
   132  * for 'Component2'.  The wildcard can be used here as well.  For example
   133  * NS_LOG='*=level_all|prefix' would enable all log levels and prefix all
   134  * prints with the component and function names.
   135  */
   136 
   137 /**
   138  * \ingroup logging
   139  * \param name a string
   140  *
   141  * Define a Log component with a specific name. This macro
   142  * should be used at the top of every file in which you want 
   143  * to use the NS_LOG macro. This macro defines a new
   144  * "log component" which can be later selectively enabled
   145  * or disabled with the ns3::LogComponentEnable and 
   146  * ns3::LogComponentDisable functions or with the NS_LOG
   147  * environment variable.
   148  */
   149 #define NS_LOG_COMPONENT_DEFINE(name)                           \
   150   static ns3::LogComponent g_log = ns3::LogComponent (name)
   151 
   152 #define NS_LOG_APPEND_TIME_PREFIX                               \
   153   if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME))                   \
   154     {                                                           \
   155       ns3::LogTimePrinter printer = ns3::LogGetTimePrinter ();  \
   156       if (printer != 0)                                         \
   157         {                                                       \
   158           (*printer) (std::clog);                               \
   159           std::clog << " ";                                     \
   160         }                                                       \
   161     }
   162 
   163 #define NS_LOG_APPEND_FUNC_PREFIX                               \
   164   if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC))                   \
   165     {                                                           \
   166       std::clog << g_log.Name () << ":" <<                      \
   167         __FUNCTION__ << "(): ";                                 \
   168     }                                                           \
   169 
   170 #ifndef NS_LOG_APPEND_CONTEXT
   171 #define NS_LOG_APPEND_CONTEXT
   172 #endif /* NS_LOG_APPEND_CONTEXT */
   173 
   174 
   175 /**
   176  * \ingroup logging
   177  * \param level the log level
   178  * \param msg the message to log
   179  *
   180  * This macro allows you to log an arbitrary message at a specific
   181  * log level. The log message is expected to be a C++ ostream
   182  * message such as "my string" << aNumber << "my oth stream".
   183  *
   184  * Typical usage looks like:
   185  * \code
   186  * NS_LOG (LOG_DEBUG, "a number="<<aNumber<<", anotherNumber="<<anotherNumber);
   187  * \endcode
   188  */
   189 #define NS_LOG(level, msg)                                      \
   190   do                                                            \
   191     {                                                           \
   192       if (g_log.IsEnabled (level))                              \
   193         {                                                       \
   194           NS_LOG_APPEND_TIME_PREFIX;                            \
   195           NS_LOG_APPEND_CONTEXT;                                \
   196           NS_LOG_APPEND_FUNC_PREFIX;                            \
   197           std::clog << msg << std::endl;                        \
   198         }                                                       \
   199     }                                                           \
   200   while (false)
   201 
   202 /**
   203  * \ingroup logging
   204  * \param msg the message to log
   205  *
   206  * Use \ref NS_LOG to output a message of level LOG_ERROR.
   207  */
   208 #define NS_LOG_ERROR(msg) \
   209   NS_LOG(ns3::LOG_ERROR, msg)
   210 
   211 /**
   212  * \ingroup logging
   213  * \param msg the message to log
   214  *
   215  * Use \ref NS_LOG to output a message of level LOG_WARN.
   216  */
   217 #define NS_LOG_WARN(msg) \
   218   NS_LOG(ns3::LOG_WARN, msg)
   219 
   220 /**
   221  * \ingroup logging
   222  * \param msg the message to log
   223  *
   224  * Use \ref NS_LOG to output a message of level LOG_DEBUG.
   225  */
   226 #define NS_LOG_DEBUG(msg) \
   227   NS_LOG(ns3::LOG_DEBUG, msg)
   228 
   229 /**
   230  * \ingroup logging
   231  * \param msg the message to log
   232  *
   233  * Use \ref NS_LOG to output a message of level LOG_INFO.
   234  */
   235 #define NS_LOG_INFO(msg) \
   236   NS_LOG(ns3::LOG_INFO, msg)
   237 
   238 /**
   239  * \ingroup logging
   240  *
   241  * Output the name of the function.
   242  */
   243 #define NS_LOG_FUNCTION_NOARGS()                                \
   244   do                                                            \
   245     {                                                           \
   246       if (g_log.IsEnabled (ns3::LOG_FUNCTION))                  \
   247         {                                                       \
   248           NS_LOG_APPEND_TIME_PREFIX;                            \
   249           NS_LOG_APPEND_CONTEXT;                                \
   250           std::clog << g_log.Name () << ":"                     \
   251                     << __FUNCTION__ << "()" << std::endl;       \
   252         }                                                       \
   253     }                                                           \
   254   while (false)
   255 
   256 
   257 /**
   258  * \ingroup logging
   259  * \param parameters the parameters to output.
   260  *
   261  * If log level LOG_FUNCTION is enabled, this macro will output
   262  * all input parameters separated by ", ".
   263  *
   264  * Typical usage looks like:
   265  * \code
   266  * NS_LOG_FUNCTION (aNumber<<anotherNumber);
   267  * \endcode
   268  * And the output will look like:
   269  * \code
   270  * Component:Function (aNumber, anotherNumber)
   271  * \endcode
   272  */
   273 #define NS_LOG_FUNCTION(parameters)                             \
   274   do                                                            \
   275     {                                                           \
   276       if (g_log.IsEnabled (ns3::LOG_FUNCTION))                  \
   277         {                                                       \
   278           NS_LOG_APPEND_TIME_PREFIX;                            \
   279           NS_LOG_APPEND_CONTEXT;                                \
   280           std::clog << g_log.Name () << ":"                     \
   281                     << __FUNCTION__ << "(";                     \
   282           ns3::ParameterLogger (std::clog)  << parameters;      \
   283           std::clog << ")" << std::endl;                        \
   284         }                                                       \
   285     }                                                           \
   286   while (false)
   287 
   288 
   289 /**
   290  * \ingroup logging
   291  * \param msg the message to log
   292  *
   293  * Use \ref NS_LOG to output a message of level LOG_LOGIC
   294  */
   295 #define NS_LOG_LOGIC(msg) \
   296   NS_LOG(ns3::LOG_LOGIC, msg)
   297 
   298 /**
   299  * \ingroup logging
   300  * \param msg the message to log
   301  *
   302  * Output the requested message unconditionaly.
   303  */
   304 #define NS_LOG_UNCOND(msg)              \
   305   do                                    \
   306     {                                   \
   307       std::clog << msg << std::endl;    \
   308     }                                   \
   309   while (false)
   310 
   311 namespace ns3 {
   312 
   313 
   314 /**
   315  * \ingroup logging
   316  *
   317  * Print the list of logging messages available.
   318  * Same as running your program with the NS_LOG environment
   319  * variable set as NS_LOG=print-list
   320  */
   321 void LogComponentPrintList (void);
   322 
   323 typedef void (*LogTimePrinter) (std::ostream &os);
   324 
   325 void LogSetTimePrinter (LogTimePrinter);
   326 LogTimePrinter LogGetTimePrinter(void);
   327 
   328 
   329 class LogComponent {
   330 public:
   331   LogComponent (char const *name);
   332   void EnvVarCheck (char const *name);
   333   bool IsEnabled (enum LogLevel level) const;
   334   bool IsNoneEnabled (void) const;
   335   void Enable (enum LogLevel level);
   336   void Disable (enum LogLevel level);
   337   char const *Name (void) const;
   338 private:
   339   int32_t     m_levels;
   340   char const *m_name;
   341 };
   342 
   343 class ParameterLogger : public std::ostream
   344 {
   345   int m_itemNumber;
   346   std::ostream &m_os;
   347 public:
   348   ParameterLogger (std::ostream &os);
   349 
   350   template<typename T>
   351   ParameterLogger& operator<< (T param)
   352   {
   353     switch (m_itemNumber)
   354       {
   355       case 0: // first parameter
   356         m_os << param;
   357         break;
   358       default: // parameter following a previous parameter
   359         m_os << ", " << param;
   360         break;
   361       }
   362     m_itemNumber++;
   363     return *this;
   364   }
   365 };
   366 
   367 } // namespace ns3
   368 
   369 #else /* LOG_ENABLE */
   370 
   371 #define NS_LOG_COMPONENT_DEFINE(component)
   372 #define NS_LOG(level, msg)
   373 #define NS_LOG_ERROR(msg)
   374 #define NS_LOG_WARN(msg)
   375 #define NS_LOG_DEBUG(msg)
   376 #define NS_LOG_INFO(msg)
   377 #define NS_LOG_FUNCTION_NOARGS()
   378 #define NS_LOG_FUNCTION(msg)
   379 #define NS_LOG_LOGIC(msg)
   380 #define NS_LOG_UNCOND(msg)
   381 
   382 #define LogComponentPrintList
   383 #define LogRegisterTimePrinter(printer)
   384 
   385 #define LogSetTimePrinter(printer)
   386 #define LogGetTimePrinter
   387 
   388 #endif /* LOG_ENABLE */
   389 
   390 #endif // __LOG_H__