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