A Discrete-Event Network Simulator
API
log.cc
Go to the documentation of this file.
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 #include "log.h"
21 
22 #include <list>
23 #include <utility>
24 #include <iostream>
25 #include "assert.h"
26 #include "ns3/core-config.h"
27 #include "fatal-error.h"
28 
29 #ifdef HAVE_GETENV
30 #include <cstring>
31 #endif
32 
33 #ifdef HAVE_STDLIB_H
34 #include <cstdlib>
35 #endif
36 
44 namespace ns3 {
45 
57 
64 class PrintList
65 {
66 public:
67  PrintList (); //<! Constructor, prints the list and exits.
68 };
69 
75 
76 
77 /* static */
80 {
81  static LogComponent::ComponentList components;
82  return &components;
83 }
84 
85 
87 {
88 #ifdef HAVE_GETENV
89  char *envVar = getenv ("NS_LOG");
90  if (envVar == 0)
91  {
92  return;
93  }
94  std::string env = envVar;
95  std::string::size_type cur = 0;
96  std::string::size_type next = 0;
97  while (next != std::string::npos)
98  {
99  next = env.find_first_of (":", cur);
100  std::string tmp = std::string (env, cur, next-cur);
101  if (tmp == "print-list")
102  {
104  exit (0);
105  break;
106  }
107  cur = next + 1;
108  }
109 #endif
110 }
111 
112 
113 LogComponent::LogComponent (const std::string & name,
114  const std::string & file,
115  const enum LogLevel mask /* = 0 */)
116  : m_levels (0), m_mask (mask), m_name (name), m_file (file)
117 {
118  EnvVarCheck ();
119 
121  for (LogComponent::ComponentList::const_iterator i = components->begin ();
122  i != components->end ();
123  i++)
124  {
125  if (i->first == name)
126  {
127  NS_FATAL_ERROR ("Log component \""<<name<<"\" has already been registered once.");
128  }
129  }
130  components->insert (std::make_pair (name, this));
131 }
132 
133 void
135 {
136 #ifdef HAVE_GETENV
137  char *envVar = getenv ("NS_LOG");
138  if (envVar == 0)
139  {
140  return;
141  }
142  std::string env = envVar;
143 
144  std::string::size_type cur = 0;
145  std::string::size_type next = 0;
146  while (next != std::string::npos)
147  {
148  next = env.find_first_of (":", cur);
149  std::string tmp = std::string (env, cur, next-cur);
150  std::string::size_type equal = tmp.find ("=");
151  std::string component;
152  if (equal == std::string::npos)
153  {
154  component = tmp;
155  if (component == m_name || component == "*" || component == "***")
156  {
157  int level = LOG_LEVEL_ALL | LOG_PREFIX_ALL;
158  Enable ((enum LogLevel)level);
159  return;
160  }
161  }
162  else
163  {
164  component = tmp.substr (0, equal);
165  if (component == m_name || component == "*")
166  {
167  int level = 0;
168  std::string::size_type cur_lev;
169  std::string::size_type next_lev = equal;
170  bool pre_pipe = true; // before the first '|', enables positional 'all', '*'
171  do
172  {
173  cur_lev = next_lev + 1;
174  next_lev = tmp.find ("|", cur_lev);
175  std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
176  if (lev == "error")
177  {
178  level |= LOG_ERROR;
179  }
180  else if (lev == "warn")
181  {
182  level |= LOG_WARN;
183  }
184  else if (lev == "debug")
185  {
186  level |= LOG_DEBUG;
187  }
188  else if (lev == "info")
189  {
190  level |= LOG_INFO;
191  }
192  else if (lev == "function")
193  {
194  level |= LOG_FUNCTION;
195  }
196  else if (lev == "logic")
197  {
198  level |= LOG_LOGIC;
199  }
200  else if ( pre_pipe && ( (lev == "all") || (lev == "*") ) )
201  {
202  level |= LOG_LEVEL_ALL;
203  }
204  else if ( (lev == "prefix_func") || (lev == "func") )
205  {
206  level |= LOG_PREFIX_FUNC;
207  }
208  else if ( (lev == "prefix_time") || (lev == "time") )
209  {
210  level |= LOG_PREFIX_TIME;
211  }
212  else if ( (lev == "prefix_node") || (lev == "node") )
213  {
214  level |= LOG_PREFIX_NODE;
215  }
216  else if ( (lev == "prefix_level") || (lev == "level") )
217  {
218  level |= LOG_PREFIX_LEVEL;
219  }
220  else if ( (lev == "prefix_all") ||
221  (!pre_pipe && ( (lev == "all") || (lev == "*") ) )
222  )
223  {
224  level |= LOG_PREFIX_ALL;
225  }
226  else if (lev == "level_error")
227  {
228  level |= LOG_LEVEL_ERROR;
229  }
230  else if (lev == "level_warn")
231  {
232  level |= LOG_LEVEL_WARN;
233  }
234  else if (lev == "level_debug")
235  {
236  level |= LOG_LEVEL_DEBUG;
237  }
238  else if (lev == "level_info")
239  {
240  level |= LOG_LEVEL_INFO;
241  }
242  else if (lev == "level_function")
243  {
244  level |= LOG_LEVEL_FUNCTION;
245  }
246  else if (lev == "level_logic")
247  {
248  level |= LOG_LEVEL_LOGIC;
249  }
250  else if (lev == "level_all")
251  {
252  level |= LOG_LEVEL_ALL;
253  }
254  else if (lev == "**")
255  {
256  level |= LOG_LEVEL_ALL | LOG_PREFIX_ALL;
257  }
258 
259  pre_pipe = false;
260  } while (next_lev != std::string::npos);
261 
262  Enable ((enum LogLevel)level);
263  }
264  }
265  cur = next + 1;
266  }
267 #endif
268 }
269 
270 
271 bool
272 LogComponent::IsEnabled (const enum LogLevel level) const
273 {
274  // LogComponentEnableEnvVar ();
275  return (level & m_levels) ? 1 : 0;
276 }
277 
278 bool
280 {
281  return m_levels == 0;
282 }
283 
284 void
285 LogComponent::SetMask (const enum LogLevel level)
286 {
287  m_mask |= level;
288 }
289 
290 void
291 LogComponent::Enable (const enum LogLevel level)
292 {
293  m_levels |= (level & ~m_mask);
294 }
295 
296 void
297 LogComponent::Disable (const enum LogLevel level)
298 {
299  m_levels &= ~level;
300 }
301 
302 char const *
303 LogComponent::Name (void) const
304 {
305  return m_name.c_str ();
306 }
307 
308 std::string
309 LogComponent::File (void) const
310 {
311  return m_file;
312 }
313 
314 /* static */
315 std::string
317 {
318  if (level == LOG_ERROR)
319  {
320  return "ERROR";
321  }
322  else if (level == LOG_WARN)
323  {
324  // whitespace left at the end for aligment
325  return "WARN ";
326  }
327  else if (level == LOG_DEBUG)
328  {
329  return "DEBUG";
330  }
331  else if (level == LOG_INFO)
332  {
333  // whitespace left at the end for aligment
334  return "INFO ";
335  }
336  else if (level == LOG_FUNCTION)
337  {
338  return "FUNCT";
339  }
340  else if (level == LOG_LOGIC)
341  {
342  return "LOGIC";
343  }
344  else
345  {
346  return "unknown";
347  }
348 }
349 
350 void
351 LogComponentEnable (char const *name, enum LogLevel level)
352 {
354  LogComponent::ComponentList::const_iterator i;
355  for (i = components->begin ();
356  i != components->end ();
357  i++)
358  {
359  if (i->first.compare (name) == 0)
360  {
361  i->second->Enable (level);
362  return;
363  }
364  }
365  if (i == components->end())
366  {
367  // nothing matched
369  NS_FATAL_ERROR ("Logging component \"" << name <<
370  "\" not found. See above for a list of available log components");
371  }
372 }
373 
374 void
376 {
378  for (LogComponent::ComponentList::const_iterator i = components->begin ();
379  i != components->end ();
380  i++)
381  {
382  i->second->Enable (level);
383  }
384 }
385 
386 void
387 LogComponentDisable (char const *name, enum LogLevel level)
388 {
390  for (LogComponent::ComponentList::const_iterator i = components->begin ();
391  i != components->end ();
392  i++)
393  {
394  if (i->first.compare (name) == 0)
395  {
396  i->second->Disable (level);
397  break;
398  }
399  }
400 }
401 
402 void
404 {
406  for (LogComponent::ComponentList::const_iterator i = components->begin ();
407  i != components->end ();
408  i++)
409  {
410  i->second->Disable (level);
411  }
412 }
413 
414 void
416 {
418  for (LogComponent::ComponentList::const_iterator i = components->begin ();
419  i != components->end ();
420  i++)
421  {
422  std::cout << i->first << "=";
423  if (i->second->IsNoneEnabled ())
424  {
425  std::cout << "0" << std::endl;
426  continue;
427  }
428  if (i->second->IsEnabled (LOG_LEVEL_ALL))
429  {
430  std::cout << "all";
431  }
432  else
433  {
434  if (i->second->IsEnabled (LOG_ERROR))
435  {
436  std::cout << "error";
437  }
438  if (i->second->IsEnabled (LOG_WARN))
439  {
440  std::cout << "|warn";
441  }
442  if (i->second->IsEnabled (LOG_DEBUG))
443  {
444  std::cout << "|debug";
445  }
446  if (i->second->IsEnabled (LOG_INFO))
447  {
448  std::cout << "|info";
449  }
450  if (i->second->IsEnabled (LOG_FUNCTION))
451  {
452  std::cout << "|function";
453  }
454  if (i->second->IsEnabled (LOG_LOGIC))
455  {
456  std::cout << "|logic";
457  }
458  }
459  if (i->second->IsEnabled (LOG_PREFIX_ALL))
460  {
461  std::cout << "|prefix_all";
462  }
463  else
464  {
465  if (i->second->IsEnabled (LOG_PREFIX_FUNC))
466  {
467  std::cout << "|func";
468  }
469  if (i->second->IsEnabled (LOG_PREFIX_TIME))
470  {
471  std::cout << "|time";
472  }
473  if (i->second->IsEnabled (LOG_PREFIX_NODE))
474  {
475  std::cout << "|node";
476  }
477  if (i->second->IsEnabled (LOG_PREFIX_LEVEL))
478  {
479  std::cout << "|level";
480  }
481  }
482  std::cout << std::endl;
483  }
484 }
485 
494 static bool ComponentExists(std::string componentName)
495 {
496  char const*name=componentName.c_str();
498  LogComponent::ComponentList::const_iterator i;
499  for (i = components->begin ();
500  i != components->end ();
501  i++)
502  {
503  if (i->first.compare (name) == 0)
504  {
505  return true;
506  }
507  }
508  NS_ASSERT (i == components->end());
509  // nothing matched
510  return false;
511 }
512 
518 static void CheckEnvironmentVariables (void)
519 {
520 #ifdef HAVE_GETENV
521  char *envVar = getenv ("NS_LOG");
522  if (envVar == 0 || std::strlen(envVar) == 0)
523  {
524  return;
525  }
526  std::string env = envVar;
527 
528  std::string::size_type cur = 0;
529  std::string::size_type next = 0;
530 
531  while (next != std::string::npos)
532  {
533  next = env.find_first_of (":", cur);
534  std::string tmp = std::string (env, cur, next-cur);
535  std::string::size_type equal = tmp.find ("=");
536  std::string component;
537  if (equal == std::string::npos)
538  {
539  // ie no '=' characters found
540  component = tmp;
541  if (ComponentExists(component) || component == "*" || component == "***")
542  {
543  return;
544  }
545  else
546  {
548  NS_FATAL_ERROR("Invalid or unregistered component name \"" << component <<
549  "\" in env variable NS_LOG, see above for a list of valid components");
550  }
551  }
552  else
553  {
554  component = tmp.substr (0, equal);
555  if (ComponentExists(component) || component == "*")
556  {
557  std::string::size_type cur_lev;
558  std::string::size_type next_lev = equal;
559  do
560  {
561  cur_lev = next_lev + 1;
562  next_lev = tmp.find ("|", cur_lev);
563  std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
564  if (lev == "error"
565  || lev == "warn"
566  || lev == "debug"
567  || lev == "info"
568  || lev == "function"
569  || lev == "logic"
570  || lev == "all"
571  || lev == "prefix_func"
572  || lev == "func"
573  || lev == "prefix_time"
574  || lev == "time"
575  || lev == "prefix_node"
576  || lev == "node"
577  || lev == "prefix_level"
578  || lev == "level"
579  || lev == "prefix_all"
580  || lev == "level_error"
581  || lev == "level_warn"
582  || lev == "level_debug"
583  || lev == "level_info"
584  || lev == "level_function"
585  || lev == "level_logic"
586  || lev == "level_all"
587  || lev == "*"
588  || lev == "**"
589  )
590  {
591  continue;
592  }
593  else
594  {
595  NS_FATAL_ERROR("Invalid log level \"" << lev <<
596  "\" in env variable NS_LOG for component name " << component);
597  }
598  } while (next_lev != std::string::npos);
599  }
600  else
601  {
603  NS_FATAL_ERROR("Invalid or unregistered component name \"" << component <<
604  "\" in env variable NS_LOG, see above for a list of valid components");
605  }
606  }
607  cur = next + 1; // parse next component
608  }
609 #endif
610 }
612 {
613  g_logTimePrinter = printer;
619 }
621 {
622  return g_logTimePrinter;
623 }
624 
626 {
627  g_logNodePrinter = printer;
628 }
630 {
631  return g_logNodePrinter;
632 }
633 
634 
636  : m_first (true),
637  m_os (os)
638 {
639 }
640 
641 template<>
643 ParameterLogger::operator<< <std::string>(const std::string param)
644 {
645  if (m_first)
646  {
647  m_os << "\"" << param << "\"";
648  m_first = false;
649  }
650  else
651  {
652  m_os << ", \"" << param << "\"";
653  }
654  return *this;
655 }
656 
657 template<>
658 ParameterLogger&
659 ParameterLogger::operator<< <const char *>(const char * param)
660 {
661  (*this) << std::string (param);
662  return *this;
663 }
664 
665 } // namespace ns3
NS_FATAL_x macro definitions.
LOG_LOGIC and above.
Definition: log.h:109
LogComponent(const std::string &name, const std::string &file, const enum LogLevel mask=LOG_NONE)
Constructor.
Definition: log.cc:113
void LogComponentDisable(char const *name, enum LogLevel level)
Disable the logging output associated with that log component.
Definition: log.cc:387
static bool ComponentExists(std::string componentName)
Check if a log component exists.
Definition: log.cc:494
static void CheckEnvironmentVariables(void)
Parse the NS_LOG environment variable.
Definition: log.cc:518
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
static LogTimePrinter g_logTimePrinter
The LogTimePrinter.
Definition: log.cc:51
ParameterLogger(std::ostream &os)
Constructor.
Definition: log.cc:635
LOG_ERROR and above.
Definition: log.h:94
void Disable(const enum LogLevel level)
Disable logging at level for this LogComponent.
Definition: log.cc:297
void(* LogTimePrinter)(std::ostream &os)
Function signature for prepending the simulation time to a log message.
Definition: log.h:271
LOG_INFO and above.
Definition: log.h:103
void EnvVarCheck(void)
Parse the NS_LOG environment variable for options relating to this LogComponent.
Definition: log.cc:134
void(* LogNodePrinter)(std::ostream &os)
Function signature for prepending the node id to a log message.
Definition: log.h:278
LOG_FUNCTION and above.
Definition: log.h:106
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
std::string m_file
File defining this LogComponent.
Definition: log.h:408
Rare ad-hoc debug messages.
Definition: log.h:99
Control flow tracing within functions.
Definition: log.h:108
Insert , when streaming function arguments.
Definition: log.h:416
Serious error messages only.
Definition: log.h:93
void LogComponentEnable(char const *name, enum LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:351
void Enable(const enum LogLevel level)
Enable this LogComponent at level.
Definition: log.cc:291
bool IsEnabled(const enum LogLevel level) const
Check if this LogComponent is enabled for level.
Definition: log.cc:272
void LogSetNodePrinter(LogNodePrinter printer)
Set the LogNodePrinter function to be used to prepend log messages with the node id.
Definition: log.cc:625
void SetMask(const enum LogLevel level)
Prevent the enabling of a specific LogLevel.
Definition: log.cc:285
Definition of assertion macros NS_ASSERT() and NS_ASSERT_MSG().
void LogComponentPrintList(void)
Print the list of logging messages available.
Definition: log.cc:415
LogNodePrinter LogGetNodePrinter(void)
Get the LogNodePrinter function currently in use.
Definition: log.cc:629
Warning messages.
Definition: log.h:96
LOG_WARN and above.
Definition: log.h:97
std::map< std::string, LogComponent * > ComponentList
LogComponent name map.
Definition: log.h:383
LOG_DEBUG and above.
Definition: log.h:100
void LogComponentEnableAll(enum LogLevel level)
Enable the logging output for all registered log components.
Definition: log.cc:375
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Prefix all trace prints with simulation time.
Definition: log.h:115
void LogComponentDisableAll(enum LogLevel level)
Disable all logging for all components.
Definition: log.cc:403
Prefix all trace prints with function.
Definition: log.h:114
static ComponentList * GetComponentList(void)
Get the list of LogComponnents.
Definition: log.cc:79
Function tracing.
Definition: log.h:105
int32_t m_mask
Blocked LogLevels.
Definition: log.h:406
int32_t m_levels
Enabled LogLevels.
Definition: log.h:405
static PrintList g_printList
Invoke handler for print-list in NS_LOG environment variable.
Definition: log.cc:74
void LogSetTimePrinter(LogTimePrinter printer)
Set the LogTimePrinter function to be used to prepend log messages with the simulation time...
Definition: log.cc:611
Handler for print-list token in NS_LOG to print the list of log components.
Definition: log.cc:64
std::string File(void) const
Get the compilation unit defining this LogComponent.
Definition: log.cc:309
static LogNodePrinter g_logNodePrinter
The LogNodePrinter.
Definition: log.cc:56
Prefix all trace prints with simulation node.
Definition: log.h:116
All prefixes.
Definition: log.h:118
bool IsNoneEnabled(void) const
Check if all levels are disabled.
Definition: log.cc:279
LogLevel
Logging severity classes and levels.
Definition: log.h:90
PrintList()
Definition: log.cc:86
Print everything.
Definition: log.h:112
Informational messages (e.g., banners).
Definition: log.h:102
Debug message logging.
char const * Name(void) const
Get the name of this LogComponent.
Definition: log.cc:303
Prefix all trace prints with log level (severity).
Definition: log.h:117
static std::string GetLevelLabel(const enum LogLevel level)
Get the string label for the given LogLevel.
Definition: log.cc:316
LogTimePrinter LogGetTimePrinter(void)
Get the LogTimePrinter function currently in use.
Definition: log.cc:620
std::string m_name
LogComponent name.
Definition: log.h:407