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::list<std::pair <std::string, LogComponent *> > ComponentList;
43 typedef std::list<std::pair <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 (char const * 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->push_back (std::make_pair (name, this));
103 }
104 
105 void
106 LogComponent::EnvVarCheck (char const * 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 == "*")
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;
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  return "WARN ";
285  }
286  else if (level == LOG_DEBUG)
287  {
288  return "DEBUG";
289  }
290  else if (level == LOG_INFO)
291  {
292  return "INFO ";
293  }
294  else if (level == LOG_FUNCTION)
295  {
296  return "FUNCT";
297  }
298  else if (level == LOG_LOGIC)
299  {
300  return "LOGIC";
301  }
302  else
303  {
304  return "unknown";
305  }
306 }
307 
308 void
309 LogComponentEnable (char const *name, enum LogLevel level)
310 {
311  ComponentList *components = GetComponentList ();
312  ComponentListI i;
313  for (i = components->begin ();
314  i != components->end ();
315  i++)
316  {
317  if (i->first.compare (name) == 0)
318  {
319  i->second->Enable (level);
320  return;
321  }
322  }
323  if (i == components->end())
324  {
325  // nothing matched
327  NS_FATAL_ERROR ("Logging component \"" << name <<
328  "\" not found. See above for a list of available log components");
329  }
330 }
331 
332 void
334 {
335  ComponentList *components = GetComponentList ();
336  for (ComponentListI i = components->begin ();
337  i != components->end ();
338  i++)
339  {
340  i->second->Enable (level);
341  }
342 }
343 
344 void
345 LogComponentDisable (char const *name, enum LogLevel level)
346 {
347  ComponentList *components = GetComponentList ();
348  for (ComponentListI i = components->begin ();
349  i != components->end ();
350  i++)
351  {
352  if (i->first.compare (name) == 0)
353  {
354  i->second->Disable (level);
355  break;
356  }
357  }
358 }
359 
360 void
362 {
363  ComponentList *components = GetComponentList ();
364  for (ComponentListI i = components->begin ();
365  i != components->end ();
366  i++)
367  {
368  i->second->Disable (level);
369  }
370 }
371 
372 void
374 {
375  ComponentList *components = GetComponentList ();
376  for (ComponentListI i = components->begin ();
377  i != components->end ();
378  i++)
379  {
380  std::cout << i->first << "=";
381  if (i->second->IsNoneEnabled ())
382  {
383  std::cout << "0" << std::endl;
384  continue;
385  }
386  if (i->second->IsEnabled (LOG_LEVEL_ALL))
387  {
388  std::cout << "all";
389  }
390  else
391  {
392  if (i->second->IsEnabled (LOG_ERROR))
393  {
394  std::cout << "error";
395  }
396  if (i->second->IsEnabled (LOG_WARN))
397  {
398  std::cout << "|warn";
399  }
400  if (i->second->IsEnabled (LOG_DEBUG))
401  {
402  std::cout << "|debug";
403  }
404  if (i->second->IsEnabled (LOG_INFO))
405  {
406  std::cout << "|info";
407  }
408  if (i->second->IsEnabled (LOG_FUNCTION))
409  {
410  std::cout << "|function";
411  }
412  if (i->second->IsEnabled (LOG_LOGIC))
413  {
414  std::cout << "|logic";
415  }
416  }
417  if (i->second->IsEnabled (LOG_PREFIX_ALL))
418  {
419  std::cout << "|prefix_all";
420  }
421  else
422  {
423  if (i->second->IsEnabled (LOG_PREFIX_FUNC))
424  {
425  std::cout << "|func";
426  }
427  if (i->second->IsEnabled (LOG_PREFIX_TIME))
428  {
429  std::cout << "|time";
430  }
431  if (i->second->IsEnabled (LOG_PREFIX_NODE))
432  {
433  std::cout << "|node";
434  }
435  if (i->second->IsEnabled (LOG_PREFIX_LEVEL))
436  {
437  std::cout << "|level";
438  }
439  }
440  std::cout << std::endl;
441  }
442 }
443 
444 static bool ComponentExists(std::string componentName)
445 {
446  char const*name=componentName.c_str();
447  ComponentList *components = GetComponentList ();
448  ComponentListI i;
449  for (i = components->begin ();
450  i != components->end ();
451  i++)
452  {
453  if (i->first.compare (name) == 0)
454  {
455  return true;
456  }
457  }
458  NS_ASSERT (i == components->end());
459  // nothing matched
460  return false;
461 }
462 
463 static void CheckEnvironmentVariables (void)
464 {
465 #ifdef HAVE_GETENV
466  char *envVar = getenv ("NS_LOG");
467  if (envVar == 0 || std::strlen(envVar) == 0)
468  {
469  return;
470  }
471  std::string env = envVar;
472 
473  std::string::size_type cur = 0;
474  std::string::size_type next = 0;
475 
476  while (next != std::string::npos)
477  {
478  next = env.find_first_of (":", cur);
479  std::string tmp = std::string (env, cur, next-cur);
480  std::string::size_type equal = tmp.find ("=");
481  std::string component;
482  if (equal == std::string::npos)
483  {
484  // ie no '=' characters found
485  component = tmp;
486  if (ComponentExists(component) || component == "*")
487  {
488  return;
489  }
490  else
491  {
493  NS_FATAL_ERROR("Invalid or unregistered component name \"" << component <<
494  "\" in env variable NS_LOG, see above for a list of valid components");
495  }
496  }
497  else
498  {
499  component = tmp.substr (0, equal);
500  if (ComponentExists(component) || component == "*")
501  {
502  std::string::size_type cur_lev;
503  std::string::size_type next_lev = equal;
504  do
505  {
506  cur_lev = next_lev + 1;
507  next_lev = tmp.find ("|", cur_lev);
508  std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
509  if (lev == "error"
510  || lev == "warn"
511  || lev == "debug"
512  || lev == "info"
513  || lev == "function"
514  || lev == "logic"
515  || lev == "all"
516  || lev == "prefix_func"
517  || lev == "func"
518  || lev == "prefix_time"
519  || lev == "time"
520  || lev == "prefix_node"
521  || lev == "node"
522  || lev == "prefix_level"
523  || lev == "level"
524  || lev == "prefix_all"
525  || lev == "level_error"
526  || lev == "level_warn"
527  || lev == "level_debug"
528  || lev == "level_info"
529  || lev == "level_function"
530  || lev == "level_logic"
531  || lev == "level_all"
532  || lev == "*"
533  || lev == "**"
534  )
535  {
536  continue;
537  }
538  else
539  {
540  NS_FATAL_ERROR("Invalid log level \"" << lev <<
541  "\" in env variable NS_LOG for component name " << component);
542  }
543  } while (next_lev != std::string::npos);
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  cur = next + 1; // parse next component
553  }
554 #endif
555 }
557 {
558  g_logTimePrinter = printer;
559  // This is the only place where we are more or less sure that all log variables
560  // are registered. See bug 1082 for details.
562 }
564 {
565  return g_logTimePrinter;
566 }
567 
569 {
570  g_logNodePrinter = printer;
571 }
573 {
574  return g_logNodePrinter;
575 }
576 
577 
579  : m_itemNumber (0),
580  m_os (os)
581 {
582 }
583 
584 } // namespace ns3