A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 
37 namespace ns3 {
38 
41 
42 typedef std::map<std::string, LogComponent *> ComponentList;
43 typedef std::map<std::string, LogComponent *>::iterator ComponentListI;
44 
45 static class PrintList
46 {
47 public:
48  PrintList ();
49 } g_printList;
50 
51 static
53 {
54  static ComponentList components;
55  return &components;
56 }
57 
58 
59 
61 {
62 #ifdef HAVE_GETENV
63  char *envVar = getenv ("NS_LOG");
64  if (envVar == 0)
65  {
66  return;
67  }
68  std::string env = envVar;
69  std::string::size_type cur = 0;
70  std::string::size_type next = 0;
71  while (next != std::string::npos)
72  {
73  next = env.find_first_of (":", cur);
74  std::string tmp = std::string (env, cur, next-cur);
75  if (tmp == "print-list")
76  {
78  exit (0);
79  break;
80  }
81  cur = next + 1;
82  }
83 #endif
84 }
85 
86 
87 LogComponent::LogComponent (const std::string & name,
88  const enum LogLevel mask /* = 0 */)
89  : m_levels (0), m_mask (mask), m_name (name)
90 {
91  EnvVarCheck ();
92 
93  ComponentList *components = GetComponentList ();
94  for (ComponentListI i = components->begin ();
95  i != components->end ();
96  i++)
97  {
98  if (i->first == name)
99  {
100  NS_FATAL_ERROR ("Log component \""<<name<<"\" has already been registered once.");
101  }
102  }
103  components->insert (std::make_pair (name, this));
104 }
105 
106 void
108 {
109 #ifdef HAVE_GETENV
110  char *envVar = getenv ("NS_LOG");
111  if (envVar == 0)
112  {
113  return;
114  }
115  std::string env = envVar;
116 
117  std::string::size_type cur = 0;
118  std::string::size_type next = 0;
119  while (next != std::string::npos)
120  {
121  next = env.find_first_of (":", cur);
122  std::string tmp = std::string (env, cur, next-cur);
123  std::string::size_type equal = tmp.find ("=");
124  std::string component;
125  if (equal == std::string::npos)
126  {
127  component = tmp;
128  if (component == m_name || component == "*" || component == "***")
129  {
130  int level = LOG_LEVEL_ALL | LOG_PREFIX_ALL;
131  Enable ((enum LogLevel)level);
132  return;
133  }
134  }
135  else
136  {
137  component = tmp.substr (0, equal);
138  if (component == m_name || component == "*")
139  {
140  int level = 0;
141  std::string::size_type cur_lev;
142  std::string::size_type next_lev = equal;
143  bool pre_pipe = true; // before the first '|', enables positional 'all', '*'
144  do
145  {
146  cur_lev = next_lev + 1;
147  next_lev = tmp.find ("|", cur_lev);
148  std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
149  if (lev == "error")
150  {
151  level |= LOG_ERROR;
152  }
153  else if (lev == "warn")
154  {
155  level |= LOG_WARN;
156  }
157  else if (lev == "debug")
158  {
159  level |= LOG_DEBUG;
160  }
161  else if (lev == "info")
162  {
163  level |= LOG_INFO;
164  }
165  else if (lev == "function")
166  {
167  level |= LOG_FUNCTION;
168  }
169  else if (lev == "logic")
170  {
171  level |= LOG_LOGIC;
172  }
173  else if ( pre_pipe && ( (lev == "all") || (lev == "*") ) )
174  {
175  level |= LOG_LEVEL_ALL;
176  }
177  else if ( (lev == "prefix_func") || (lev == "func") )
178  {
179  level |= LOG_PREFIX_FUNC;
180  }
181  else if ( (lev == "prefix_time") || (lev == "time") )
182  {
183  level |= LOG_PREFIX_TIME;
184  }
185  else if ( (lev == "prefix_node") || (lev == "node") )
186  {
187  level |= LOG_PREFIX_NODE;
188  }
189  else if ( (lev == "prefix_level") || (lev == "level") )
190  {
191  level |= LOG_PREFIX_LEVEL;
192  }
193  else if ( (lev == "prefix_all") ||
194  (!pre_pipe && ( (lev == "all") || (lev == "*") ) )
195  )
196  {
197  level |= LOG_PREFIX_ALL;
198  }
199  else if (lev == "level_error")
200  {
201  level |= LOG_LEVEL_ERROR;
202  }
203  else if (lev == "level_warn")
204  {
205  level |= LOG_LEVEL_WARN;
206  }
207  else if (lev == "level_debug")
208  {
209  level |= LOG_LEVEL_DEBUG;
210  }
211  else if (lev == "level_info")
212  {
213  level |= LOG_LEVEL_INFO;
214  }
215  else if (lev == "level_function")
216  {
217  level |= LOG_LEVEL_FUNCTION;
218  }
219  else if (lev == "level_logic")
220  {
221  level |= LOG_LEVEL_LOGIC;
222  }
223  else if (lev == "level_all")
224  {
225  level |= LOG_LEVEL_ALL;
226  }
227  else if (lev == "**")
228  {
229  level |= LOG_LEVEL_ALL | LOG_PREFIX_ALL;
230  }
231 
232  pre_pipe = false;
233  } while (next_lev != std::string::npos);
234 
235  Enable ((enum LogLevel)level);
236  }
237  }
238  cur = next + 1;
239  }
240 #endif
241 }
242 
243 
244 bool
245 LogComponent::IsEnabled (const enum LogLevel level) const
246 {
247  // LogComponentEnableEnvVar ();
248  return (level & m_levels) ? 1 : 0;
249 }
250 
251 bool
253 {
254  return m_levels == 0;
255 }
256 
257 void
258 LogComponent::SetMask (const enum LogLevel level)
259 {
260  m_mask |= level;
261 }
262 
263 void
264 LogComponent::Enable (const enum LogLevel level)
265 {
266  m_levels |= (level & ~m_mask);
267 }
268 
269 void
270 LogComponent::Disable (const enum LogLevel level)
271 {
272  m_levels &= ~level;
273 }
274 
275 char const *
276 LogComponent::Name (void) const
277 {
278  return m_name.c_str ();
279 }
280 
281 /* static */
282 std::string
284 {
285  if (level == LOG_ERROR)
286  {
287  return "ERROR";
288  }
289  else if (level == LOG_WARN)
290  {
291  // whitespace left at the end for aligment
292  return "WARN ";
293  }
294  else if (level == LOG_DEBUG)
295  {
296  return "DEBUG";
297  }
298  else if (level == LOG_INFO)
299  {
300  // whitespace left at the end for aligment
301  return "INFO ";
302  }
303  else if (level == LOG_FUNCTION)
304  {
305  return "FUNCT";
306  }
307  else if (level == LOG_LOGIC)
308  {
309  return "LOGIC";
310  }
311  else
312  {
313  return "unknown";
314  }
315 }
316 
317 void
318 LogComponentEnable (char const *name, enum LogLevel level)
319 {
320  ComponentList *components = GetComponentList ();
321  ComponentListI i;
322  for (i = components->begin ();
323  i != components->end ();
324  i++)
325  {
326  if (i->first.compare (name) == 0)
327  {
328  i->second->Enable (level);
329  return;
330  }
331  }
332  if (i == components->end())
333  {
334  // nothing matched
336  NS_FATAL_ERROR ("Logging component \"" << name <<
337  "\" not found. See above for a list of available log components");
338  }
339 }
340 
341 void
343 {
344  ComponentList *components = GetComponentList ();
345  for (ComponentListI i = components->begin ();
346  i != components->end ();
347  i++)
348  {
349  i->second->Enable (level);
350  }
351 }
352 
353 void
354 LogComponentDisable (char const *name, enum LogLevel level)
355 {
356  ComponentList *components = GetComponentList ();
357  for (ComponentListI i = components->begin ();
358  i != components->end ();
359  i++)
360  {
361  if (i->first.compare (name) == 0)
362  {
363  i->second->Disable (level);
364  break;
365  }
366  }
367 }
368 
369 void
371 {
372  ComponentList *components = GetComponentList ();
373  for (ComponentListI i = components->begin ();
374  i != components->end ();
375  i++)
376  {
377  i->second->Disable (level);
378  }
379 }
380 
381 void
383 {
384  ComponentList *components = GetComponentList ();
385  for (ComponentListI i = components->begin ();
386  i != components->end ();
387  i++)
388  {
389  std::cout << i->first << "=";
390  if (i->second->IsNoneEnabled ())
391  {
392  std::cout << "0" << std::endl;
393  continue;
394  }
395  if (i->second->IsEnabled (LOG_LEVEL_ALL))
396  {
397  std::cout << "all";
398  }
399  else
400  {
401  if (i->second->IsEnabled (LOG_ERROR))
402  {
403  std::cout << "error";
404  }
405  if (i->second->IsEnabled (LOG_WARN))
406  {
407  std::cout << "|warn";
408  }
409  if (i->second->IsEnabled (LOG_DEBUG))
410  {
411  std::cout << "|debug";
412  }
413  if (i->second->IsEnabled (LOG_INFO))
414  {
415  std::cout << "|info";
416  }
417  if (i->second->IsEnabled (LOG_FUNCTION))
418  {
419  std::cout << "|function";
420  }
421  if (i->second->IsEnabled (LOG_LOGIC))
422  {
423  std::cout << "|logic";
424  }
425  }
426  if (i->second->IsEnabled (LOG_PREFIX_ALL))
427  {
428  std::cout << "|prefix_all";
429  }
430  else
431  {
432  if (i->second->IsEnabled (LOG_PREFIX_FUNC))
433  {
434  std::cout << "|func";
435  }
436  if (i->second->IsEnabled (LOG_PREFIX_TIME))
437  {
438  std::cout << "|time";
439  }
440  if (i->second->IsEnabled (LOG_PREFIX_NODE))
441  {
442  std::cout << "|node";
443  }
444  if (i->second->IsEnabled (LOG_PREFIX_LEVEL))
445  {
446  std::cout << "|level";
447  }
448  }
449  std::cout << std::endl;
450  }
451 }
452 
453 static bool ComponentExists(std::string componentName)
454 {
455  char const*name=componentName.c_str();
456  ComponentList *components = GetComponentList ();
457  ComponentListI i;
458  for (i = components->begin ();
459  i != components->end ();
460  i++)
461  {
462  if (i->first.compare (name) == 0)
463  {
464  return true;
465  }
466  }
467  NS_ASSERT (i == components->end());
468  // nothing matched
469  return false;
470 }
471 
472 static void CheckEnvironmentVariables (void)
473 {
474 #ifdef HAVE_GETENV
475  char *envVar = getenv ("NS_LOG");
476  if (envVar == 0 || std::strlen(envVar) == 0)
477  {
478  return;
479  }
480  std::string env = envVar;
481 
482  std::string::size_type cur = 0;
483  std::string::size_type next = 0;
484 
485  while (next != std::string::npos)
486  {
487  next = env.find_first_of (":", cur);
488  std::string tmp = std::string (env, cur, next-cur);
489  std::string::size_type equal = tmp.find ("=");
490  std::string component;
491  if (equal == std::string::npos)
492  {
493  // ie no '=' characters found
494  component = tmp;
495  if (ComponentExists(component) || component == "*" || component == "***")
496  {
497  return;
498  }
499  else
500  {
502  NS_FATAL_ERROR("Invalid or unregistered component name \"" << component <<
503  "\" in env variable NS_LOG, see above for a list of valid components");
504  }
505  }
506  else
507  {
508  component = tmp.substr (0, equal);
509  if (ComponentExists(component) || component == "*")
510  {
511  std::string::size_type cur_lev;
512  std::string::size_type next_lev = equal;
513  do
514  {
515  cur_lev = next_lev + 1;
516  next_lev = tmp.find ("|", cur_lev);
517  std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
518  if (lev == "error"
519  || lev == "warn"
520  || lev == "debug"
521  || lev == "info"
522  || lev == "function"
523  || lev == "logic"
524  || lev == "all"
525  || lev == "prefix_func"
526  || lev == "func"
527  || lev == "prefix_time"
528  || lev == "time"
529  || lev == "prefix_node"
530  || lev == "node"
531  || lev == "prefix_level"
532  || lev == "level"
533  || lev == "prefix_all"
534  || lev == "level_error"
535  || lev == "level_warn"
536  || lev == "level_debug"
537  || lev == "level_info"
538  || lev == "level_function"
539  || lev == "level_logic"
540  || lev == "level_all"
541  || lev == "*"
542  || lev == "**"
543  )
544  {
545  continue;
546  }
547  else
548  {
549  NS_FATAL_ERROR("Invalid log level \"" << lev <<
550  "\" in env variable NS_LOG for component name " << component);
551  }
552  } while (next_lev != std::string::npos);
553  }
554  else
555  {
557  NS_FATAL_ERROR("Invalid or unregistered component name \"" << component <<
558  "\" in env variable NS_LOG, see above for a list of valid components");
559  }
560  }
561  cur = next + 1; // parse next component
562  }
563 #endif
564 }
566 {
567  g_logTimePrinter = printer;
573 }
575 {
576  return g_logTimePrinter;
577 }
578 
580 {
581  g_logNodePrinter = printer;
582 }
584 {
585  return g_logNodePrinter;
586 }
587 
588 
590  : m_first (true),
591  m_os (os)
592 {
593 }
594 
595 } // namespace ns3
void LogComponentEnableAll(enum LogLevel level)
Enable the logging output for all registered log components.
Definition: log.cc:342
void LogComponentDisableAll(enum LogLevel level)
Disable all logging for all components.
Definition: log.cc:370
void LogSetNodePrinter(LogNodePrinter printer)
Definition: log.cc:579
static void CheckEnvironmentVariables(void)
Definition: log.cc:472
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:61
ParameterLogger(std::ostream &os)
Constructor.
Definition: log.cc:589
void Disable(const enum LogLevel level)
Disable logging at level for this LogComponent.
Definition: log.cc:270
void EnvVarCheck(void)
Parse the NS_LOG environment variable for options relating to this LogComponent.
Definition: log.cc:107
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:95
void LogSetTimePrinter(LogTimePrinter printer)
Definition: log.cc:565
rare ad-hoc debug messages
Definition: log.h:80
control flow tracing within functions
Definition: log.h:89
serious error messages only
Definition: log.h:74
void Enable(const enum LogLevel level)
Enable this LogComponent at level
Definition: log.cc:264
bool IsEnabled(const enum LogLevel level) const
Check if this LogComponent is enabled for level
Definition: log.cc:245
static LogTimePrinter g_logTimePrinter
Definition: log.cc:39
void SetMask(const enum LogLevel level)
Prevent the enabling of a specific LogLevel.
Definition: log.cc:258
LogNodePrinter LogGetNodePrinter(void)
Definition: log.cc:583
warning messages
Definition: log.h:77
LogComponent(const std::string &name, const enum LogLevel mask=LOG_NONE)
Constructor.
Definition: log.cc:87
static LogNodePrinter g_logNodePrinter
Definition: log.cc:40
std::map< std::string, LogComponent * > ComponentList
Definition: log.cc:42
prefix all trace prints with simulation time
Definition: log.h:96
void LogComponentDisable(char const *name, enum LogLevel level)
Disable the logging output associated with that log component.
Definition: log.cc:354
prefix all trace prints with function
Definition: log.h:95
function tracing
Definition: log.h:86
int32_t m_mask
Blocked LogLevels.
Definition: log.h:327
int32_t m_levels
Enabled LogLevels.
Definition: log.h:326
std::map< std::string, LogComponent * >::iterator ComponentListI
Definition: log.cc:43
prefix all trace prints with simulation node
Definition: log.h:97
all prefixes
Definition: log.h:99
static class ns3::PrintList g_printList
void(* LogTimePrinter)(std::ostream &os)
Definition: log.h:248
bool IsNoneEnabled(void) const
Check if all levels are disabled.
Definition: log.cc:252
void(* LogNodePrinter)(std::ostream &os)
Definition: log.h:249
LogLevel
Logging severity classes and levels.
Definition: log.h:71
PrintList()
Definition: log.cc:60
static bool ComponentExists(std::string componentName)
Definition: log.cc:453
static ComponentList * GetComponentList(void)
Definition: log.cc:52
informational messages (e.g., banners)
Definition: log.h:83
char const * Name(void) const
Get the name of this LogComponent.
Definition: log.cc:276
prefix all trace prints with log level (severity)
Definition: log.h:98
static std::string GetLevelLabel(const enum LogLevel level)
Get the string label for the given LogLevel.
Definition: log.cc:283
LogTimePrinter LogGetTimePrinter(void)
Definition: log.cc:574
void LogComponentPrintList(void)
Print the list of logging messages available.
Definition: log.cc:382
std::string m_name
LogComponent name.
Definition: log.h:328
void LogComponentEnable(char const *name, enum LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:318