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  : m_levels (0), m_name (name)
89 {
90  EnvVarCheck (name);
91 
92  ComponentList *components = GetComponentList ();
93  for (ComponentListI i = components->begin ();
94  i != components->end ();
95  i++)
96  {
97  if (i->first == name)
98  {
99  NS_FATAL_ERROR ("Log component \""<<name<<"\" has already been registered once.");
100  }
101  }
102  components->insert (std::make_pair (name, this));
103 }
104 
105 void
106 LogComponent::EnvVarCheck (const std::string & name)
107 {
108 #ifdef HAVE_GETENV
109  char *envVar = getenv ("NS_LOG");
110  if (envVar == 0)
111  {
112  return;
113  }
114  std::string env = envVar;
115  std::string myName = name;
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 == myName || 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 == myName || 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
246 {
247  // LogComponentEnableEnvVar ();
248  return (level & m_levels) ? 1 : 0;
249 }
250 
251 bool
253 {
254  return m_levels == 0;
255 }
256 
257 void
259 {
260  m_levels |= level;
261 }
262 
263 void
265 {
266  m_levels &= ~level;
267 }
268 
269 char const *
270 LogComponent::Name (void) const
271 {
272  return m_name.c_str ();
273 }
274 
275 std::string
276 LogComponent::GetLevelLabel(const enum LogLevel level) const
277 {
278  if (level == LOG_ERROR)
279  {
280  return "ERROR";
281  }
282  else if (level == LOG_WARN)
283  {
284  // whitespace left at the end for aligment
285  return "WARN ";
286  }
287  else if (level == LOG_DEBUG)
288  {
289  return "DEBUG";
290  }
291  else if (level == LOG_INFO)
292  {
293  // whitespace left at the end for aligment
294  return "INFO ";
295  }
296  else if (level == LOG_FUNCTION)
297  {
298  return "FUNCT";
299  }
300  else if (level == LOG_LOGIC)
301  {
302  return "LOGIC";
303  }
304  else
305  {
306  return "unknown";
307  }
308 }
309 
310 void
311 LogComponentEnable (char const *name, enum LogLevel level)
312 {
313  ComponentList *components = GetComponentList ();
314  ComponentListI i;
315  for (i = components->begin ();
316  i != components->end ();
317  i++)
318  {
319  if (i->first.compare (name) == 0)
320  {
321  i->second->Enable (level);
322  return;
323  }
324  }
325  if (i == components->end())
326  {
327  // nothing matched
329  NS_FATAL_ERROR ("Logging component \"" << name <<
330  "\" not found. See above for a list of available log components");
331  }
332 }
333 
334 void
336 {
337  ComponentList *components = GetComponentList ();
338  for (ComponentListI i = components->begin ();
339  i != components->end ();
340  i++)
341  {
342  i->second->Enable (level);
343  }
344 }
345 
346 void
347 LogComponentDisable (char const *name, enum LogLevel level)
348 {
349  ComponentList *components = GetComponentList ();
350  for (ComponentListI i = components->begin ();
351  i != components->end ();
352  i++)
353  {
354  if (i->first.compare (name) == 0)
355  {
356  i->second->Disable (level);
357  break;
358  }
359  }
360 }
361 
362 void
364 {
365  ComponentList *components = GetComponentList ();
366  for (ComponentListI i = components->begin ();
367  i != components->end ();
368  i++)
369  {
370  i->second->Disable (level);
371  }
372 }
373 
374 void
376 {
377  ComponentList *components = GetComponentList ();
378  for (ComponentListI i = components->begin ();
379  i != components->end ();
380  i++)
381  {
382  std::cout << i->first << "=";
383  if (i->second->IsNoneEnabled ())
384  {
385  std::cout << "0" << std::endl;
386  continue;
387  }
388  if (i->second->IsEnabled (LOG_LEVEL_ALL))
389  {
390  std::cout << "all";
391  }
392  else
393  {
394  if (i->second->IsEnabled (LOG_ERROR))
395  {
396  std::cout << "error";
397  }
398  if (i->second->IsEnabled (LOG_WARN))
399  {
400  std::cout << "|warn";
401  }
402  if (i->second->IsEnabled (LOG_DEBUG))
403  {
404  std::cout << "|debug";
405  }
406  if (i->second->IsEnabled (LOG_INFO))
407  {
408  std::cout << "|info";
409  }
410  if (i->second->IsEnabled (LOG_FUNCTION))
411  {
412  std::cout << "|function";
413  }
414  if (i->second->IsEnabled (LOG_LOGIC))
415  {
416  std::cout << "|logic";
417  }
418  }
419  if (i->second->IsEnabled (LOG_PREFIX_ALL))
420  {
421  std::cout << "|prefix_all";
422  }
423  else
424  {
425  if (i->second->IsEnabled (LOG_PREFIX_FUNC))
426  {
427  std::cout << "|func";
428  }
429  if (i->second->IsEnabled (LOG_PREFIX_TIME))
430  {
431  std::cout << "|time";
432  }
433  if (i->second->IsEnabled (LOG_PREFIX_NODE))
434  {
435  std::cout << "|node";
436  }
437  if (i->second->IsEnabled (LOG_PREFIX_LEVEL))
438  {
439  std::cout << "|level";
440  }
441  }
442  std::cout << std::endl;
443  }
444 }
445 
446 static bool ComponentExists(std::string componentName)
447 {
448  char const*name=componentName.c_str();
449  ComponentList *components = GetComponentList ();
450  ComponentListI i;
451  for (i = components->begin ();
452  i != components->end ();
453  i++)
454  {
455  if (i->first.compare (name) == 0)
456  {
457  return true;
458  }
459  }
460  NS_ASSERT (i == components->end());
461  // nothing matched
462  return false;
463 }
464 
465 static void CheckEnvironmentVariables (void)
466 {
467 #ifdef HAVE_GETENV
468  char *envVar = getenv ("NS_LOG");
469  if (envVar == 0 || std::strlen(envVar) == 0)
470  {
471  return;
472  }
473  std::string env = envVar;
474 
475  std::string::size_type cur = 0;
476  std::string::size_type next = 0;
477 
478  while (next != std::string::npos)
479  {
480  next = env.find_first_of (":", cur);
481  std::string tmp = std::string (env, cur, next-cur);
482  std::string::size_type equal = tmp.find ("=");
483  std::string component;
484  if (equal == std::string::npos)
485  {
486  // ie no '=' characters found
487  component = tmp;
488  if (ComponentExists(component) || component == "*" || component == "***")
489  {
490  return;
491  }
492  else
493  {
495  NS_FATAL_ERROR("Invalid or unregistered component name \"" << component <<
496  "\" in env variable NS_LOG, see above for a list of valid components");
497  }
498  }
499  else
500  {
501  component = tmp.substr (0, equal);
502  if (ComponentExists(component) || component == "*")
503  {
504  std::string::size_type cur_lev;
505  std::string::size_type next_lev = equal;
506  do
507  {
508  cur_lev = next_lev + 1;
509  next_lev = tmp.find ("|", cur_lev);
510  std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
511  if (lev == "error"
512  || lev == "warn"
513  || lev == "debug"
514  || lev == "info"
515  || lev == "function"
516  || lev == "logic"
517  || lev == "all"
518  || lev == "prefix_func"
519  || lev == "func"
520  || lev == "prefix_time"
521  || lev == "time"
522  || lev == "prefix_node"
523  || lev == "node"
524  || lev == "prefix_level"
525  || lev == "level"
526  || lev == "prefix_all"
527  || lev == "level_error"
528  || lev == "level_warn"
529  || lev == "level_debug"
530  || lev == "level_info"
531  || lev == "level_function"
532  || lev == "level_logic"
533  || lev == "level_all"
534  || lev == "*"
535  || lev == "**"
536  )
537  {
538  continue;
539  }
540  else
541  {
542  NS_FATAL_ERROR("Invalid log level \"" << lev <<
543  "\" in env variable NS_LOG for component name " << component);
544  }
545  } while (next_lev != std::string::npos);
546  }
547  else
548  {
550  NS_FATAL_ERROR("Invalid or unregistered component name \"" << component <<
551  "\" in env variable NS_LOG, see above for a list of valid components");
552  }
553  }
554  cur = next + 1; // parse next component
555  }
556 #endif
557 }
559 {
560  g_logTimePrinter = printer;
566 }
568 {
569  return g_logTimePrinter;
570 }
571 
573 {
574  g_logNodePrinter = printer;
575 }
577 {
578  return g_logNodePrinter;
579 }
580 
581 
583  : std::basic_ostream<char> (os.rdbuf ()),
584  m_itemNumber (0),
585  m_os (os)
586 {
587 }
588 
589 } // namespace ns3
void LogComponentEnableAll(enum LogLevel level)
Definition: log.cc:335
void LogComponentDisableAll(enum LogLevel level)
Definition: log.cc:363
void LogSetNodePrinter(LogNodePrinter printer)
Definition: log.cc:572
LogComponent(const std::string &name)
Definition: log.cc:87
static void CheckEnvironmentVariables(void)
Definition: log.cc:465
bool IsEnabled(enum LogLevel level) const
Definition: log.cc:245
#define NS_ASSERT(condition)
Definition: assert.h:64
ParameterLogger(std::ostream &os)
Definition: log.cc:582
void Disable(enum LogLevel level)
Definition: log.cc:264
void LogSetTimePrinter(LogTimePrinter printer)
Definition: log.cc:558
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
LogTimePrinter g_logTimePrinter
Definition: log.cc:39
LogNodePrinter LogGetNodePrinter(void)
Definition: log.cc:576
LogNodePrinter g_logNodePrinter
Definition: log.cc:40
std::map< std::string, LogComponent * > ComponentList
Definition: log.cc:42
std::string GetLevelLabel(const enum LogLevel level) const
Definition: log.cc:276
void LogComponentDisable(char const *name, enum LogLevel level)
Definition: log.cc:347
int32_t m_levels
Definition: log.h:430
void EnvVarCheck(const std::string &name)
Definition: log.cc:106
std::map< std::string, LogComponent * >::iterator ComponentListI
Definition: log.cc:43
static class ns3::PrintList g_printList
void(* LogTimePrinter)(std::ostream &os)
Definition: log.h:409
bool IsNoneEnabled(void) const
Definition: log.cc:252
void(* LogNodePrinter)(std::ostream &os)
Definition: log.h:410
LogLevel
Logging severity classes and levels.
Definition: log.h:68
PrintList()
Definition: log.cc:60
static bool ComponentExists(std::string componentName)
Definition: log.cc:446
static ComponentList * GetComponentList(void)
Definition: log.cc:52
char const * Name(void) const
Definition: log.cc:270
LogTimePrinter LogGetTimePrinter(void)
Definition: log.cc:567
void LogComponentPrintList(void)
Print the list of logging messages available.
Definition: log.cc:375
void Enable(enum LogLevel level)
Definition: log.cc:258
std::string m_name
Definition: log.h:431
void LogComponentEnable(char const *name, enum LogLevel level)
Definition: log.cc:311