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