A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
log-macros-enabled.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2006,2007 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8
9#ifndef NS3_LOG_MACROS_ENABLED_H
10#define NS3_LOG_MACROS_ENABLED_H
11
12/**
13 * \file
14 * \ingroup logging
15 * NS_LOG and related logging macro definitions.
16 */
17
18// These two implementation macros
19// NS_LOG_APPEND_TIME_PREFIX_IMPL
20// NS_LOG_APPEND_NODE_PREFIX_IMPL
21// need to be defined in all configurations (debug, release, optimized)
22// for use by NS_FATAL_...
23
24/**
25 * \ingroup logging
26 * Implementation details for NS_LOG_APPEND_TIME_PREFIX.
27 * \internal
28 * Logging implementation macro; should not be called directly.
29 * We define this separately so we can reuse the definition
30 * in NS_FATAL.
31 */
32#define NS_LOG_APPEND_TIME_PREFIX_IMPL \
33 do \
34 { \
35 ns3::TimePrinter printer = ns3::LogGetTimePrinter(); \
36 if (printer != 0) \
37 { \
38 (*printer)(std::clog); \
39 std::clog << " "; \
40 } \
41 } while (false)
42
43/**
44 * \ingroup logging
45 * Implementation details for NS_LOG_APPEND_NODE_PREFIX.
46 * \internal
47 * Logging implementation macro; should not be called directly.
48 * We define this separately so we can reuse the definition
49 * in NS_FATAL.
50 */
51#define NS_LOG_APPEND_NODE_PREFIX_IMPL \
52 do \
53 { \
54 ns3::NodePrinter printer = ns3::LogGetNodePrinter(); \
55 if (printer != 0) \
56 { \
57 (*printer)(std::clog); \
58 std::clog << " "; \
59 } \
60 } while (false)
61
62#ifdef NS3_LOG_ENABLE
63
64/**
65 * \ingroup logging
66 * Append the simulation time to a log message.
67 * \internal
68 * Logging implementation macro; should not be called directly.
69 */
70#define NS_LOG_APPEND_TIME_PREFIX \
71 if (g_log.IsEnabled(ns3::LOG_PREFIX_TIME)) \
72 { \
73 NS_LOG_APPEND_TIME_PREFIX_IMPL; \
74 }
75
76/**
77 * \ingroup logging
78 * Append the simulation node id to a log message.
79 * \internal
80 * Logging implementation macro; should not be called directly.
81 */
82#define NS_LOG_APPEND_NODE_PREFIX \
83 if (g_log.IsEnabled(ns3::LOG_PREFIX_NODE)) \
84 { \
85 NS_LOG_APPEND_NODE_PREFIX_IMPL; \
86 }
87
88/**
89 * \ingroup logging
90 * Append the function name to a log message.
91 * \internal
92 * Logging implementation macro; should not be called directly.
93 */
94#define NS_LOG_APPEND_FUNC_PREFIX \
95 if (g_log.IsEnabled(ns3::LOG_PREFIX_FUNC)) \
96 { \
97 std::clog << g_log.Name() << ":" << __FUNCTION__ << "(): "; \
98 }
99
100/**
101 * \ingroup logging
102 * Append the log severity level to a log message.
103 * \internal
104 * Logging implementation macro; should not be called directly.
105 */
106#define NS_LOG_APPEND_LEVEL_PREFIX(level) \
107 if (g_log.IsEnabled(ns3::LOG_PREFIX_LEVEL)) \
108 { \
109 std::clog << "[" << g_log.GetLevelLabel(level) << "] "; \
110 }
111
112#ifndef NS_LOG_APPEND_CONTEXT
113/**
114 * \ingroup logging
115 * Append the node id (or other file-local programmatic context, such as
116 * MPI rank) to a log message.
117 *
118 * This is implemented locally in `.cc` files because
119 * the relevant variable is only known there.
120 *
121 * Preferred format is something like (assuming the node id is
122 * accessible from `var`:
123 * \code
124 * if (var)
125 * {
126 * std::clog << "[node " << var->GetObject<Node> ()->GetId () << "] ";
127 * }
128 * \endcode
129 */
130#define NS_LOG_APPEND_CONTEXT
131#endif /* NS_LOG_APPEND_CONTEXT */
132
133#ifndef NS_LOG_CONDITION
134/**
135 * \ingroup logging
136 * Limit logging output based on some file-local condition,
137 * such as MPI rank.
138 *
139 * This is implemented locally in `.cc` files because
140 * the relevant condition variable is only known there.
141 *
142 * Since this appears immediately before the `do { ... } while false`
143 * construct of \c NS_LOG(level, msg), it must have the form
144 * \code
145 * #define NS_LOG_CONDITION if (condition)
146 * \endcode
147 */
148#define NS_LOG_CONDITION
149#endif
150
151/**
152 * \ingroup logging
153 *
154 * This macro allows you to log an arbitrary message at a specific
155 * log level.
156 *
157 * The log message is expected to be a C++ ostream
158 * message such as "my string" << aNumber << "my oth stream".
159 *
160 * Typical usage looks like:
161 * \code
162 * NS_LOG (LOG_DEBUG, "a number="<<aNumber<<", anotherNumber="<<anotherNumber);
163 * \endcode
164 *
165 * \param [in] level The log level
166 * \param [in] msg The message to log
167 * \internal
168 * Logging implementation macro; should not be called directly.
169 */
170#define NS_LOG(level, msg) \
171 NS_LOG_CONDITION \
172 do \
173 { \
174 if (g_log.IsEnabled(level)) \
175 { \
176 NS_LOG_APPEND_TIME_PREFIX; \
177 NS_LOG_APPEND_NODE_PREFIX; \
178 NS_LOG_APPEND_CONTEXT; \
179 NS_LOG_APPEND_FUNC_PREFIX; \
180 NS_LOG_APPEND_LEVEL_PREFIX(level); \
181 auto flags = std::clog.setf(std::ios_base::boolalpha); \
182 std::clog << msg << std::endl; \
183 std::clog.flags(flags); \
184 } \
185 } while (false)
186
187/**
188 * \ingroup logging
189 *
190 * Output the name of the function.
191 *
192 * This should be used only in static functions; most member functions
193 * should instead use NS_LOG_FUNCTION().
194 */
195#define NS_LOG_FUNCTION_NOARGS() \
196 NS_LOG_CONDITION \
197 do \
198 { \
199 if (g_log.IsEnabled(ns3::LOG_FUNCTION)) \
200 { \
201 NS_LOG_APPEND_TIME_PREFIX; \
202 NS_LOG_APPEND_NODE_PREFIX; \
203 NS_LOG_APPEND_CONTEXT; \
204 std::clog << g_log.Name() << ":" << __FUNCTION__ << "()" << std::endl; \
205 } \
206 } while (false)
207
208/**
209 * \ingroup logging
210 *
211 * If log level LOG_FUNCTION is enabled, this macro will output
212 * all input parameters separated by ", ".
213 *
214 * Typical usage looks like:
215 * \code
216 * NS_LOG_FUNCTION (aNumber<<anotherNumber);
217 * \endcode
218 * And the output will look like:
219 * \code
220 * Component:Function (aNumber, anotherNumber)
221 * \endcode
222 *
223 * To facilitate function tracing, most functions should begin with
224 * (at least) NS_LOG_FUNCTION(this). Static functions should use
225 * NS_LOG_FUNCTION_NOARGS() instead.
226 *
227 * \param [in] parameters The parameters to output.
228 */
229#define NS_LOG_FUNCTION(parameters) \
230 NS_LOG_CONDITION \
231 do \
232 { \
233 if (g_log.IsEnabled(ns3::LOG_FUNCTION)) \
234 { \
235 NS_LOG_APPEND_TIME_PREFIX; \
236 NS_LOG_APPEND_NODE_PREFIX; \
237 NS_LOG_APPEND_CONTEXT; \
238 std::clog << g_log.Name() << ":" << __FUNCTION__ << "("; \
239 auto flags = std::clog.setf(std::ios_base::boolalpha); \
240 ns3::ParameterLogger(std::clog) << parameters; \
241 std::clog.flags(flags); \
242 std::clog << ")" << std::endl; \
243 } \
244 } while (false)
245
246/**
247 * \ingroup logging
248 *
249 * Output the requested message unconditionally.
250 *
251 * \param [in] msg The message to log
252 */
253#define NS_LOG_UNCOND(msg) \
254 NS_LOG_CONDITION \
255 do \
256 { \
257 auto flags = std::clog.setf(std::ios_base::boolalpha); \
258 std::clog << msg << std::endl; \
259 std::clog.flags(flags); \
260 } while (false)
261
262#endif /* NS3_LOG_ENABLE */
263
264#endif /* NS3_LOG_MACROS_ENABLED_H */