A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
log.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2006,2007 INRIA
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19#include "log.h"
20
21#include "assert.h"
23#include "fatal-error.h"
24#include "string.h"
25
26#include "ns3/core-config.h"
27
28#include <algorithm> // transform
29#include <cstring> // strlen
30#include <iostream>
31#include <list>
32#include <locale> // toupper
33#include <map>
34#include <numeric> // accumulate
35#include <stdexcept>
36#include <utility>
37
48namespace
49{
51const std::map<std::string, ns3::LogLevel> LOG_LABEL_LEVELS = {
52 // clang-format off
53 {"none", ns3::LOG_NONE},
54 {"error", ns3::LOG_ERROR},
55 {"level_error", ns3::LOG_LEVEL_ERROR},
56 {"warn", ns3::LOG_WARN},
57 {"level_warn", ns3::LOG_LEVEL_WARN},
58 {"debug", ns3::LOG_DEBUG},
59 {"level_debug", ns3::LOG_LEVEL_DEBUG},
60 {"info", ns3::LOG_INFO},
61 {"level_info", ns3::LOG_LEVEL_INFO},
62 {"function", ns3::LOG_FUNCTION},
63 {"level_function", ns3::LOG_LEVEL_FUNCTION},
64 {"logic", ns3::LOG_LOGIC},
65 {"level_logic", ns3::LOG_LEVEL_LOGIC},
66 {"all", ns3::LOG_ALL},
67 {"level_all", ns3::LOG_LEVEL_ALL},
68 {"func", ns3::LOG_PREFIX_FUNC},
69 {"prefix_func", ns3::LOG_PREFIX_FUNC},
70 {"time", ns3::LOG_PREFIX_TIME},
71 {"prefix_time", ns3::LOG_PREFIX_TIME},
72 {"node", ns3::LOG_PREFIX_NODE},
73 {"prefix_node", ns3::LOG_PREFIX_NODE},
74 {"level", ns3::LOG_PREFIX_LEVEL},
75 {"prefix_level", ns3::LOG_PREFIX_LEVEL},
76 {"prefix_all", ns3::LOG_PREFIX_ALL}
77 // clang-format on
78};
79
81const std::map<ns3::LogLevel, std::string> LOG_LEVEL_LABELS = {[]() {
82 std::map<ns3::LogLevel, std::string> labels;
83 for (const auto& [label, lev] : LOG_LABEL_LEVELS)
84 {
85 // Only keep the first label for a level
86 if (labels.find(lev) == labels.end())
87 {
88 std::string pad{label};
89 // Add whitespace for alignment with "ERROR", "DEBUG" etc.
90 if (pad.size() < 5)
91 {
92 pad.insert(pad.size(), 5 - pad.size(), ' ');
93 }
94 std::transform(pad.begin(), pad.end(), pad.begin(), ::toupper);
95 labels[lev] = pad;
96 }
97 }
98 return labels;
99}()};
100
101} // Unnamed namespace
102
103namespace ns3
104{
105
117
130{
131 public:
132 PrintList(); //<! Constructor, prints the list and exits.
133};
134
140
141/* static */
144{
145 static LogComponent::ComponentList components;
146 return &components;
147}
148
150{
151 auto [found, value] = EnvironmentVariable::Get("NS_LOG", "print-list", ":");
152 if (found)
153 {
155 exit(0);
156 }
157}
158
159LogComponent::LogComponent(const std::string& name,
160 const std::string& file,
161 const LogLevel mask /* = 0 */)
162 : m_levels(0),
163 m_mask(mask),
164 m_name(name),
165 m_file(file)
166{
167 // Check if we're mentioned in NS_LOG, and set our flags appropriately
168 EnvVarCheck();
169
171
172 if (components->find(name) != components->end())
173 {
174 NS_FATAL_ERROR("Log component \"" << name << "\" has already been registered once.");
175 }
176
177 components->insert(std::make_pair(name, this));
178}
179
181GetLogComponent(const std::string name)
182{
184 LogComponent* ret;
185
186 try
187 {
188 ret = components->at(name);
189 }
190 catch (std::out_of_range&)
191 {
192 NS_FATAL_ERROR("Log component \"" << name << "\" does not exist.");
193 }
194 return *ret;
195}
196
197void
199{
200 auto [found, value] = EnvironmentVariable::Get("NS_LOG", m_name, ":");
201 if (!found)
202 {
203 std::tie(found, value) = EnvironmentVariable::Get("NS_LOG", "*", ":");
204 }
205 if (!found)
206 {
207 std::tie(found, value) = EnvironmentVariable::Get("NS_LOG", "***", ":");
208 }
209
210 if (!found)
211 {
212 return;
213 }
214
215 if (value.empty())
216 {
217 // Default is enable all levels, all prefixes
218 value = "**";
219 }
220
221 // Got a value, might have flags
222 int level = 0;
223 StringVector flags = SplitString(value, "|");
224 NS_ASSERT_MSG(!flags.empty(), "Unexpected empty flags from non-empty value");
225 bool pre_pipe{true};
226
227 for (const auto& lev : flags)
228 {
229 if (lev == "**")
230 {
231 level |= LOG_LEVEL_ALL | LOG_PREFIX_ALL;
232 }
233 else if (lev == "all" || lev == "*")
234 {
235 level |= (pre_pipe ? LOG_LEVEL_ALL : LOG_PREFIX_ALL);
236 }
237 else if (LOG_LABEL_LEVELS.find(lev) != LOG_LABEL_LEVELS.end())
238 {
239 level |= LOG_LABEL_LEVELS.at(lev);
240 }
241 pre_pipe = false;
242 }
243 Enable((LogLevel)level);
244}
245
246bool
248{
249 // LogComponentEnableEnvVar ();
250 return (level & m_levels) ? 1 : 0;
251}
252
253bool
255{
256 return m_levels == 0;
257}
258
259void
261{
262 m_mask |= level;
263}
264
265void
267{
268 m_levels |= (level & ~m_mask);
269}
270
271void
273{
274 m_levels &= ~level;
275}
276
277std::string
279{
280 return m_name;
281}
282
283std::string
285{
286 return m_file;
287}
288
289/* static */
290std::string
292{
293 auto it = LOG_LEVEL_LABELS.find(level);
294 if (it != LOG_LEVEL_LABELS.end())
295 {
296 return it->second;
297 }
298 return "unknown";
299}
300
301void
302LogComponentEnable(const std::string& name, LogLevel level)
303{
305 auto logComponent = components->find(name);
306
307 if (logComponent == components->end())
308 {
309 NS_LOG_UNCOND("Logging component \"" << name << "\" not found.");
311 NS_FATAL_ERROR("Logging component \""
312 << name << "\" not found."
313 << " See above for a list of available log components");
314 }
315
316 logComponent->second->Enable(level);
317}
318
319void
321{
323 for (LogComponent::ComponentList::const_iterator i = components->begin();
324 i != components->end();
325 i++)
326 {
327 i->second->Enable(level);
328 }
329}
330
331void
332LogComponentDisable(const std::string& name, LogLevel level)
333{
335 auto logComponent = components->find(name);
336
337 if (logComponent != components->end())
338 {
339 logComponent->second->Disable(level);
340 }
341}
342
343void
345{
347 for (LogComponent::ComponentList::const_iterator i = components->begin();
348 i != components->end();
349 i++)
350 {
351 i->second->Disable(level);
352 }
353}
354
355void
357{
358 // Create sorted map of components by inserting them into a map
359 std::map<std::string, LogComponent*> componentsSorted;
360
361 for (const auto& component : *LogComponent::GetComponentList())
362 {
363 componentsSorted.insert(component);
364 }
365
366 // Iterate through sorted components
367 for (const auto& [name, component] : componentsSorted)
368 {
369 std::cout << name << "=";
370 if (component->IsNoneEnabled())
371 {
372 std::cout << "0" << std::endl;
373 continue;
374 }
375 if (component->IsEnabled(LOG_LEVEL_ALL))
376 {
377 std::cout << "all";
378 }
379 else
380 {
381 if (component->IsEnabled(LOG_ERROR))
382 {
383 std::cout << "error";
384 }
385 if (component->IsEnabled(LOG_WARN))
386 {
387 std::cout << "|warn";
388 }
389 if (component->IsEnabled(LOG_DEBUG))
390 {
391 std::cout << "|debug";
392 }
393 if (component->IsEnabled(LOG_INFO))
394 {
395 std::cout << "|info";
396 }
397 if (component->IsEnabled(LOG_FUNCTION))
398 {
399 std::cout << "|function";
400 }
401 if (component->IsEnabled(LOG_LOGIC))
402 {
403 std::cout << "|logic";
404 }
405 }
406 if (component->IsEnabled(LOG_PREFIX_ALL))
407 {
408 std::cout << "|prefix_all";
409 }
410 else
411 {
412 if (component->IsEnabled(LOG_PREFIX_FUNC))
413 {
414 std::cout << "|func";
415 }
416 if (component->IsEnabled(LOG_PREFIX_TIME))
417 {
418 std::cout << "|time";
419 }
420 if (component->IsEnabled(LOG_PREFIX_NODE))
421 {
422 std::cout << "|node";
423 }
424 if (component->IsEnabled(LOG_PREFIX_LEVEL))
425 {
426 std::cout << "|level";
427 }
428 }
429 std::cout << std::endl;
430 }
431}
432
441static bool
442ComponentExists(std::string componentName)
443{
445
446 return components->find(componentName) != components->end();
447}
448
454static void
456{
457 auto dict = EnvironmentVariable::GetDictionary("NS_LOG", ":")->GetStore();
458
459 for (auto& [component, value] : dict)
460 {
461 if (component != "*" && component != "***" && !ComponentExists(component))
462 {
463 NS_LOG_UNCOND("Invalid or unregistered component name \"" << component << "\"");
466 "Invalid or unregistered component name \""
467 << component
468 << "\" in env variable NS_LOG, see above for a list of valid components");
469 }
470
471 // We have a valid component or wildcard, check the flags
472 if (!value.empty())
473 {
474 // Check the flags present in value
475 StringVector flags = SplitString(value, "|");
476 for (const auto& flag : flags)
477 {
478 // Handle wild cards
479 if (flag == "*" || flag == "**")
480 {
481 continue;
482 }
483 bool ok = LOG_LABEL_LEVELS.find(flag) != LOG_LABEL_LEVELS.end();
484 if (!ok)
485 {
486 NS_FATAL_ERROR("Invalid log level \""
487 << flag << "\" in env variable NS_LOG for component name "
488 << component);
489 }
490 } // for flag
491 } // !value.empty
492 } // for component
493}
494
495void
497{
498 g_logTimePrinter = printer;
504}
505
508{
509 return g_logTimePrinter;
510}
511
512void
514{
515 g_logNodePrinter = printer;
516}
517
520{
521 return g_logNodePrinter;
522}
523
525 : m_os(os)
526{
527}
528
529void
531{
532 if (m_first)
533 {
534 m_first = false;
535 }
536 else
537 {
538 m_os << ", ";
539 }
540}
541
542template <>
544ParameterLogger::operator<< <std::string>(const std::string& param)
545{
546 CommaRest();
547 m_os << "\"" << param << "\"";
548 return *this;
549}
550
552ParameterLogger::operator<<(const char* param)
553{
554 (*this) << std::string(param);
555 return *this;
556}
557
558template <>
560ParameterLogger::operator<< <int8_t>(const int8_t param)
561{
562 (*this) << static_cast<int16_t>(param);
563 return *this;
564}
565
566template <>
567ParameterLogger&
568ParameterLogger::operator<< <uint8_t>(const uint8_t param)
569{
570 (*this) << static_cast<uint16_t>(param);
571 return *this;
572}
573
574} // namespace ns3
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
static KeyFoundType Get(const std::string &envvar, const std::string &key="", const std::string &delim=";")
Get the value corresponding to a key from an environment variable.
static std::shared_ptr< Dictionary > GetDictionary(const std::string &envvar, const std::string &delim=";")
Get the dictionary for a particular environment variable.
A single log component configuration.
Definition: log.h:328
static ComponentList * GetComponentList()
Get the list of LogComponents.
Definition: log.cc:143
void Enable(const LogLevel level)
Enable this LogComponent at level.
Definition: log.cc:266
bool IsEnabled(const LogLevel level) const
Check if this LogComponent is enabled for level.
Definition: log.cc:247
std::string File() const
Get the compilation unit defining this LogComponent.
Definition: log.cc:284
int32_t m_levels
Enabled LogLevels.
Definition: log.h:419
void Disable(const LogLevel level)
Disable logging at level for this LogComponent.
Definition: log.cc:272
static std::string GetLevelLabel(const LogLevel level)
Get the string label for the given LogLevel.
Definition: log.cc:291
void EnvVarCheck()
Parse the NS_LOG environment variable for options relating to this LogComponent.
Definition: log.cc:198
std::string m_file
File defining this LogComponent.
Definition: log.h:422
bool IsNoneEnabled() const
Check if all levels are disabled.
Definition: log.cc:254
std::string Name() const
Get the name of this LogComponent.
Definition: log.cc:278
std::unordered_map< std::string, LogComponent * > ComponentList
LogComponent name map.
Definition: log.h:398
int32_t m_mask
Blocked LogLevels.
Definition: log.h:420
LogComponent(const std::string &name, const std::string &file, const LogLevel mask=LOG_NONE)
Constructor.
Definition: log.cc:159
void SetMask(const LogLevel level)
Prevent the enabling of a specific LogLevel.
Definition: log.cc:260
std::string m_name
LogComponent name.
Definition: log.h:421
Insert , when streaming function arguments.
Definition: log.h:438
ParameterLogger & operator<<(T param)
Write a function parameter on the output stream, separating parameters after the first by ,...
Definition: log.h:498
void CommaRest()
Add , before every parameter after the first.
Definition: log.cc:530
bool m_first
First argument flag, doesn't get ,.
Definition: log.h:492
ParameterLogger(std::ostream &os)
Constructor.
Definition: log.cc:524
std::ostream & m_os
Underlying output stream.
Definition: log.h:493
Handler for the undocumented print-list token in NS_LOG which triggers printing of the list of log co...
Definition: log.cc:130
Class Environment declaration.
NS_FATAL_x macro definitions.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_UNCOND(msg)
Output the requested message unconditionally.
static NodePrinter g_logNodePrinter
The Log NodePrinter.
Definition: log.cc:116
static void CheckEnvironmentVariables()
Parse the NS_LOG environment variable.
Definition: log.cc:455
static bool ComponentExists(std::string componentName)
Check if a log component exists.
Definition: log.cc:442
static TimePrinter g_logTimePrinter
The Log TimePrinter.
Definition: log.cc:111
Debug message logging.
const std::map< std::string, ns3::LogLevel > LOG_LABEL_LEVELS
Mapping of log level text names to values.
Definition: log.cc:51
const std::map< ns3::LogLevel, std::string > LOG_LEVEL_LABELS
Inverse mapping of level values to log level text names.
Definition: log.cc:81
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:302
static PrintList g_printList
Invoke handler for print-list in NS_LOG environment variable.
Definition: log.cc:139
void LogSetTimePrinter(TimePrinter printer)
Set the TimePrinter function to be used to prepend log messages with the simulation time.
Definition: log.cc:496
void(* TimePrinter)(std::ostream &os)
Function signature for features requiring a time formatter, such as logging or ShowProgress.
Definition: time-printer.h:43
void(* NodePrinter)(std::ostream &os)
Function signature for prepending the node id to a log message.
Definition: node-printer.h:40
std::vector< std::string > StringVector
Return type of SplitString.
Definition: string.h:37
NodePrinter LogGetNodePrinter()
Get the LogNodePrinter function currently in use.
Definition: log.cc:519
StringVector SplitString(const std::string &str, const std::string &delim)
Split a string on a delimiter.
Definition: string.cc:34
void LogComponentDisable(const std::string &name, LogLevel level)
Disable the logging output associated with that log component.
Definition: log.cc:332
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:110
@ LOG_NONE
No logging.
Definition: log.h:95
@ LOG_PREFIX_TIME
Prefix all trace prints with simulation time.
Definition: log.h:119
@ LOG_FUNCTION
Function tracing for non-trivial function calls.
Definition: log.h:106
@ LOG_ERROR
Serious error messages only.
Definition: log.h:97
@ LOG_WARN
Warning messages.
Definition: log.h:100
@ LOG_INFO
Something happened to change state.
Definition: log.h:103
@ LOG_PREFIX_ALL
All prefixes.
Definition: log.h:122
@ LOG_LEVEL_FUNCTION
LOG_FUNCTION and above.
Definition: log.h:107
@ LOG_LEVEL_ERROR
LOG_ERROR and above.
Definition: log.h:98
@ LOG_ALL
Print everything.
Definition: log.h:115
@ LOG_LEVEL_WARN
LOG_WARN and above.
Definition: log.h:101
@ LOG_LEVEL_DEBUG
LOG_DEBUG and above.
Definition: log.h:113
@ LOG_PREFIX_LEVEL
Prefix all trace prints with log level (severity).
Definition: log.h:121
@ LOG_LOGIC
Debugging logs for key branches and decisions in a function.
Definition: log.h:109
@ LOG_PREFIX_NODE
Prefix all trace prints with simulation node.
Definition: log.h:120
@ LOG_LEVEL_INFO
LOG_INFO and above.
Definition: log.h:104
@ LOG_DEBUG
Full voluminous logging to support debugging.
Definition: log.h:112
TimePrinter LogGetTimePrinter()
Get the LogTimePrinter function currently in use.
Definition: log.cc:507
void LogComponentDisableAll(LogLevel level)
Disable all logging for all components.
Definition: log.cc:344
LogComponent & GetLogComponent(const std::string name)
Get the LogComponent registered with the given name.
Definition: log.cc:181
void LogComponentEnableAll(LogLevel level)
Enable the logging output for all registered log components.
Definition: log.cc:320
void LogSetNodePrinter(NodePrinter printer)
Set the LogNodePrinter function to be used to prepend log messages with the node id.
Definition: log.cc:513
void LogComponentPrintList()
Print the list of logging messages available.
Definition: log.cc:356
ns3::StringValue attribute value declarations.