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;
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 (auto i = components->begin(); i != components->end(); i++)
324 {
325 i->second->Enable(level);
326 }
327}
328
329void
330LogComponentDisable(const std::string& name, LogLevel level)
331{
333 auto logComponent = components->find(name);
334
335 if (logComponent != components->end())
336 {
337 logComponent->second->Disable(level);
338 }
339}
340
341void
343{
345 for (auto i = components->begin(); i != components->end(); i++)
346 {
347 i->second->Disable(level);
348 }
349}
350
351void
353{
354 // Create sorted map of components by inserting them into a map
355 std::map<std::string, LogComponent*> componentsSorted;
356
357 for (const auto& component : *LogComponent::GetComponentList())
358 {
359 componentsSorted.insert(component);
360 }
361
362 // Iterate through sorted components
363 for (const auto& [name, component] : componentsSorted)
364 {
365 std::cout << name << "=";
366 if (component->IsNoneEnabled())
367 {
368 std::cout << "0" << std::endl;
369 continue;
370 }
371 if (component->IsEnabled(LOG_LEVEL_ALL))
372 {
373 std::cout << "all";
374 }
375 else
376 {
377 if (component->IsEnabled(LOG_ERROR))
378 {
379 std::cout << "error";
380 }
381 if (component->IsEnabled(LOG_WARN))
382 {
383 std::cout << "|warn";
384 }
385 if (component->IsEnabled(LOG_DEBUG))
386 {
387 std::cout << "|debug";
388 }
389 if (component->IsEnabled(LOG_INFO))
390 {
391 std::cout << "|info";
392 }
393 if (component->IsEnabled(LOG_FUNCTION))
394 {
395 std::cout << "|function";
396 }
397 if (component->IsEnabled(LOG_LOGIC))
398 {
399 std::cout << "|logic";
400 }
401 }
402 if (component->IsEnabled(LOG_PREFIX_ALL))
403 {
404 std::cout << "|prefix_all";
405 }
406 else
407 {
408 if (component->IsEnabled(LOG_PREFIX_FUNC))
409 {
410 std::cout << "|func";
411 }
412 if (component->IsEnabled(LOG_PREFIX_TIME))
413 {
414 std::cout << "|time";
415 }
416 if (component->IsEnabled(LOG_PREFIX_NODE))
417 {
418 std::cout << "|node";
419 }
420 if (component->IsEnabled(LOG_PREFIX_LEVEL))
421 {
422 std::cout << "|level";
423 }
424 }
425 std::cout << std::endl;
426 }
427}
428
437static bool
438ComponentExists(std::string componentName)
439{
441
442 return components->find(componentName) != components->end();
443}
444
450static void
452{
453 auto dict = EnvironmentVariable::GetDictionary("NS_LOG", ":")->GetStore();
454
455 for (auto& [component, value] : dict)
456 {
457 if (component != "*" && component != "***" && !ComponentExists(component))
458 {
459 NS_LOG_UNCOND("Invalid or unregistered component name \"" << component << "\"");
462 "Invalid or unregistered component name \""
463 << component
464 << "\" in env variable NS_LOG, see above for a list of valid components");
465 }
466
467 // We have a valid component or wildcard, check the flags
468 if (!value.empty())
469 {
470 // Check the flags present in value
471 StringVector flags = SplitString(value, "|");
472 for (const auto& flag : flags)
473 {
474 // Handle wild cards
475 if (flag == "*" || flag == "**")
476 {
477 continue;
478 }
479 bool ok = LOG_LABEL_LEVELS.find(flag) != LOG_LABEL_LEVELS.end();
480 if (!ok)
481 {
482 NS_FATAL_ERROR("Invalid log level \""
483 << flag << "\" in env variable NS_LOG for component name "
484 << component);
485 }
486 } // for flag
487 } // !value.empty
488 } // for component
489}
490
491void
493{
494 g_logTimePrinter = printer;
500}
501
504{
505 return g_logTimePrinter;
506}
507
508void
510{
511 g_logNodePrinter = printer;
512}
513
516{
517 return g_logNodePrinter;
518}
519
521 : m_os(os)
522{
523}
524
525void
527{
528 if (m_first)
529 {
530 m_first = false;
531 }
532 else
533 {
534 m_os << ", ";
535 }
536}
537
538} // 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
void CommaRest()
Add , before every parameter after the first.
Definition: log.cc:526
bool m_first
First argument flag, doesn't get ,.
Definition: log.h:470
ParameterLogger(std::ostream &os)
Constructor.
Definition: log.cc:520
std::ostream & m_os
Underlying output stream.
Definition: log.h:471
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:451
static bool ComponentExists(std::string componentName)
Check if a log component exists.
Definition: log.cc:438
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:492
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:515
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:330
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:503
void LogComponentDisableAll(LogLevel level)
Disable all logging for all components.
Definition: log.cc:342
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:509
void LogComponentPrintList()
Print the list of logging messages available.
Definition: log.cc:352
ns3::StringValue attribute value declarations.