• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2022, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes logging related  definitions.
32  */
33 
34 #ifndef LOG_HPP_
35 #define LOG_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/logging.h>
40 #include <openthread/platform/logging.h>
41 #include <openthread/platform/toolchain.h>
42 
43 #include "common/error.hpp"
44 
45 namespace ot {
46 
47 /**
48  * @def OT_SHOULD_LOG
49  *
50  * This definition indicates whether or not logging is enabled.
51  */
52 #define OT_SHOULD_LOG (OPENTHREAD_CONFIG_LOG_OUTPUT != OPENTHREAD_CONFIG_LOG_OUTPUT_NONE)
53 
54 /**
55  * Indicates whether the OpenThread logging is enabled at a given log level.
56  *
57  * @param[in] aLevel   The log level to check.
58  *
59  * @returns TRUE if logging is enabled at @p aLevel, FALSE otherwise.
60  */
61 #define OT_SHOULD_LOG_AT(aLevel) (OT_SHOULD_LOG && (OPENTHREAD_CONFIG_LOG_LEVEL >= (aLevel)))
62 
63 /**
64  * Represents the log level.
65  */
66 enum LogLevel : uint8_t
67 {
68     kLogLevelNone = OT_LOG_LEVEL_NONE, ///< None (disable logs)
69     kLogLevelCrit = OT_LOG_LEVEL_CRIT, ///< Critical log level
70     kLogLevelWarn = OT_LOG_LEVEL_WARN, ///< Warning log level
71     kLogLevelNote = OT_LOG_LEVEL_NOTE, ///< Note log level
72     kLogLevelInfo = OT_LOG_LEVEL_INFO, ///< Info log level
73     kLogLevelDebg = OT_LOG_LEVEL_DEBG, ///< Debug log level
74 };
75 
76 constexpr uint8_t kMaxLogModuleNameLength = 14; ///< Maximum module name length
77 
78 constexpr uint16_t kMaxLogStringSize = OPENTHREAD_CONFIG_LOG_MAX_SIZE; ///< Max size of log string
79 
80 #if OT_SHOULD_LOG
81 /**
82  * Registers log module name.
83  *
84  * Is used in a `cpp` file to register the log module name for that file before using any other logging
85  * functions or macros (e.g., `LogInfo()` or `DumpInfo()`, ...) in the file.
86  *
87  * @param[in] aName  The log module name string (MUST be shorter than `kMaxLogModuleNameLength`).
88  */
89 #define RegisterLogModule(aName)                                     \
90     constexpr char kLogModuleName[] = aName;                         \
91     namespace {                                                      \
92     /* Defining this type to silence "unused constant" warning/error \
93      * for `kLogModuleName` under any log level config.              \
94      */                                                              \
95     using DummyType = char[sizeof(kLogModuleName)];                  \
96     }                                                                \
97     static_assert(sizeof(kLogModuleName) <= kMaxLogModuleNameLength + 1, "Log module name is too long")
98 
99 #else
100 #define RegisterLogModule(aName) static_assert(true, "Consume the required semi-colon at the end of macro")
101 #endif
102 
103 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_CRIT)
104 /**
105  * Emits a log message at critical log level.
106  *
107  * @param[in]  ...   Arguments for the format specification.
108  */
109 #define LogCrit(...) Logger::LogAtLevel<kLogLevelCrit>(kLogModuleName, __VA_ARGS__)
110 #else
111 #define LogCrit(...)
112 #endif
113 
114 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
115 /**
116  * Emits a log message at warning log level.
117  *
118  * @param[in]  ...   Arguments for the format specification.
119  */
120 #define LogWarn(...) Logger::LogAtLevel<kLogLevelWarn>(kLogModuleName, __VA_ARGS__)
121 #else
122 #define LogWarn(...)
123 #endif
124 
125 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
126 /**
127  * Emits a log message at note log level.
128  *
129  * @param[in]  ...   Arguments for the format specification.
130  */
131 #define LogNote(...) Logger::LogAtLevel<kLogLevelNote>(kLogModuleName, __VA_ARGS__)
132 #else
133 #define LogNote(...)
134 #endif
135 
136 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
137 /**
138  * Emits a log message at info log level.
139  *
140  * @param[in]  ...   Arguments for the format specification.
141  */
142 #define LogInfo(...) Logger::LogAtLevel<kLogLevelInfo>(kLogModuleName, __VA_ARGS__)
143 #else
144 #define LogInfo(...)
145 #endif
146 
147 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_DEBG)
148 /**
149  * Emits a log message at debug log level.
150  *
151  * @param[in]  ...   Arguments for the format specification.
152  */
153 #define LogDebg(...) Logger::LogAtLevel<kLogLevelDebg>(kLogModuleName, __VA_ARGS__)
154 #else
155 #define LogDebg(...)
156 #endif
157 
158 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
159 /**
160  * Emits an error log message at warning log level if there is an error.
161  *
162  * The emitted log will use the the following format "Failed to {aText}: {ErrorToString(aError)}", and will be emitted
163  * only if there is an error, i.e., @p aError is not `kErrorNone`.
164  *
165  * @param[in] aError       The error to check and log.
166  * @param[in] aText        The text to include in the log.
167  */
168 #define LogWarnOnError(aError, aText) Logger::LogOnError(kLogModuleName, aError, aText)
169 #else
170 #define LogWarnOnError(aError, aText)
171 #endif
172 
173 #if OT_SHOULD_LOG
174 /**
175  * Emits a log message at a given log level.
176  *
177  * @param[in] aLogLevel  The log level to use.
178  * @param[in] ...        Argument for the format specification.
179  */
180 #define LogAt(aLogLevel, ...) Logger::LogInModule(kLogModuleName, aLogLevel, __VA_ARGS__)
181 #else
182 #define LogAt(aLogLevel, ...)
183 #endif
184 
185 #if OT_SHOULD_LOG
186 /**
187  * Emits a log message independent of the configured log level.
188  *
189  * @param[in]  ...   Arguments for the format specification.
190  */
191 #define LogAlways(...) Logger::LogInModule("", kLogLevelNone, __VA_ARGS__)
192 #else
193 #define LogAlways(...)
194 #endif
195 
196 #if OT_SHOULD_LOG && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
197 /**
198  * Emit a log message for the certification test.
199  *
200  * @param[in]  ...  Arguments for the format specification.
201  */
202 #define LogCert(...) LogAlways(__VA_ARGS__)
203 #else
204 #define LogCert(...)
205 #endif
206 
207 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_CRIT) && OPENTHREAD_CONFIG_LOG_PKT_DUMP
208 /**
209  * Generates a memory dump at log level critical.
210  *
211  * @param[in]  aText         A string that is printed before the bytes.
212  * @param[in]  aData         A pointer to the data buffer.
213  * @param[in]  aDataLength   Number of bytes in @p aData.
214  */
215 #define DumpCrit(aText, aData, aDataLength) Logger::Dump<kLogLevelCrit, kLogModuleName>(aText, aData, aDataLength)
216 #else
217 #define DumpCrit(aText, aData, aDataLength)
218 #endif
219 
220 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN) && OPENTHREAD_CONFIG_LOG_PKT_DUMP
221 /**
222  * Generates a memory dump at log level warning.
223  *
224  * @param[in]  aText         A string that is printed before the bytes.
225  * @param[in]  aData         A pointer to the data buffer.
226  * @param[in]  aDataLength   Number of bytes in @p aData.
227  */
228 #define DumpWarn(aText, aData, aDataLength) Logger::Dump<kLogLevelWarn, kLogModuleName>(aText, aData, aDataLength)
229 #else
230 #define DumpWarn(aText, aData, aDataLength)
231 #endif
232 
233 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) && OPENTHREAD_CONFIG_LOG_PKT_DUMP
234 /**
235  * Generates a memory dump at log level note.
236  *
237  * @param[in]  aText         A string that is printed before the bytes.
238  * @param[in]  aData         A pointer to the data buffer.
239  * @param[in]  aDataLength   Number of bytes in @p aData.
240  */
241 #define DumpNote(aText, aData, aDataLength) Logger::Dump<kLogLevelNote, kLogModuleName>(aText, aData, aDataLength)
242 #else
243 #define DumpNote(aText, aData, aDataLength)
244 #endif
245 
246 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) && OPENTHREAD_CONFIG_LOG_PKT_DUMP
247 /**
248  * Generates a memory dump at log level info.
249  *
250  * @param[in]  aText         A string that is printed before the bytes.
251  * @param[in]  aData         A pointer to the data buffer.
252  * @param[in]  aDataLength   Number of bytes in @p aData.
253  */
254 #define DumpInfo(aText, aData, aDataLength) Logger::Dump<kLogLevelInfo, kLogModuleName>(aText, aData, aDataLength)
255 #else
256 #define DumpInfo(aText, aData, aDataLength)
257 #endif
258 
259 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_DEBG) && OPENTHREAD_CONFIG_LOG_PKT_DUMP
260 /**
261  * Generates a memory dump at log level debug.
262  *
263  * @param[in]  aText         A string that is printed before the bytes.
264  * @param[in]  aData         A pointer to the data buffer.
265  * @param[in]  aDataLength   Number of bytes in @p aData.
266  */
267 #define DumpDebg(aText, aData, aDataLength) Logger::Dump<kLogLevelDebg, kLogModuleName>(aText, aData, aDataLength)
268 #else
269 #define DumpDebg(aText, aData, aDataLength)
270 #endif
271 
272 #if OT_SHOULD_LOG && OPENTHREAD_CONFIG_LOG_PKT_DUMP
273 /**
274  * Generates a memory dump independent of the configured log level.
275  *
276  * @param[in]  aText         A string that is printed before the bytes.
277  * @param[in]  aData         A pointer to the data buffer.
278  * @param[in]  aDataLength   Number of bytes in @p aData.
279  */
280 #define DumpAlways(aText, aData, aDataLength) Logger::DumpInModule("", kLogLevelNone, aText, aData, aDataLength)
281 #endif
282 
283 #if OT_SHOULD_LOG && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE && OPENTHREAD_CONFIG_LOG_PKT_DUMP
284 /**
285  * Generates a memory dump for certification test.
286  *
287  * @param[in]  aText         A string that is printed before the bytes.
288  * @param[in]  aData         A pointer to the data buffer.
289  * @param[in]  aDataLength   Number of bytes in @p aData.
290  */
291 #define DumpCert(aText, aData, aDataLength) DumpAlways(aText, aData, aDataLength)
292 #else
293 #define DumpCert(aText, aData, aDataLength)
294 #endif
295 
296 //----------------------------------------------------------------------------------------------------------------------
297 
298 #if OT_SHOULD_LOG
299 
300 class Logger
301 {
302     // The `Logger` class implements the logging methods.
303     //
304     // The `Logger` methods are not intended to be directly used
305     // and instead the logging macros should be used.
306 
307 public:
308     static void LogInModule(const char *aModuleName, LogLevel aLogLevel, const char *aFormat, ...)
309         OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(3, 4);
310 
311     template <LogLevel kLogLevel>
312     static void LogAtLevel(const char *aModuleName, const char *aFormat, ...)
313         OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(2, 3);
314 
315     static void LogVarArgs(const char *aModuleName, LogLevel aLogLevel, const char *aFormat, va_list aArgs);
316 
317 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
318     static void LogOnError(const char *aModuleName, Error aError, const char *aText);
319 #endif
320 
321 #if OPENTHREAD_CONFIG_LOG_PKT_DUMP
322     static constexpr uint8_t kStringLineLength = 80;
323     static constexpr uint8_t kDumpBytesPerLine = 16;
324 
325     template <LogLevel kLogLevel, const char *kModuleName>
Dump(const char * aText,const void * aData,uint16_t aDataLength)326     static void Dump(const char *aText, const void *aData, uint16_t aDataLength)
327     {
328         DumpAtLevel<kLogLevel>(kModuleName, aText, aData, aDataLength);
329     }
330 
331     static void DumpInModule(const char *aModuleName,
332                              LogLevel    aLogLevel,
333                              const char *aText,
334                              const void *aData,
335                              uint16_t    aDataLength);
336 
337     template <LogLevel kLogLevel>
338     static void DumpAtLevel(const char *aModuleName, const char *aText, const void *aData, uint16_t aDataLength);
339 #endif
340 };
341 
342 extern template void Logger::LogAtLevel<kLogLevelNone>(const char *aModuleName, const char *aFormat, ...);
343 extern template void Logger::LogAtLevel<kLogLevelCrit>(const char *aModuleName, const char *aFormat, ...);
344 extern template void Logger::LogAtLevel<kLogLevelWarn>(const char *aModuleName, const char *aFormat, ...);
345 extern template void Logger::LogAtLevel<kLogLevelNote>(const char *aModuleName, const char *aFormat, ...);
346 extern template void Logger::LogAtLevel<kLogLevelInfo>(const char *aModuleName, const char *aFormat, ...);
347 extern template void Logger::LogAtLevel<kLogLevelDebg>(const char *aModuleName, const char *aFormat, ...);
348 
349 #if OPENTHREAD_CONFIG_LOG_PKT_DUMP
350 extern template void Logger::DumpAtLevel<kLogLevelNone>(const char *aModuleName,
351                                                         const char *aText,
352                                                         const void *aData,
353                                                         uint16_t    aDataLength);
354 extern template void Logger::DumpAtLevel<kLogLevelCrit>(const char *aModuleName,
355                                                         const char *aText,
356                                                         const void *aData,
357                                                         uint16_t    aDataLength);
358 extern template void Logger::DumpAtLevel<kLogLevelWarn>(const char *aModuleName,
359                                                         const char *aText,
360                                                         const void *aData,
361                                                         uint16_t    aDataLength);
362 extern template void Logger::DumpAtLevel<kLogLevelNote>(const char *aModuleName,
363                                                         const char *aText,
364                                                         const void *aData,
365                                                         uint16_t    aDataLength);
366 extern template void Logger::DumpAtLevel<kLogLevelInfo>(const char *aModuleName,
367                                                         const char *aText,
368                                                         const void *aData,
369                                                         uint16_t    aDataLength);
370 extern template void Logger::DumpAtLevel<kLogLevelDebg>(const char *aModuleName,
371                                                         const char *aText,
372                                                         const void *aData,
373                                                         uint16_t    aDataLength);
374 #endif // OPENTHREAD_CONFIG_LOG_PKT_DUMP
375 #endif // OT_SHOULD_LOG
376 
377 typedef otLogHexDumpInfo HexDumpInfo; ///< Represents the hex dump info.
378 
379 /**
380  * Generates the next hex dump line.
381  *
382  * Can call this method back-to-back to generate the hex dump output line by line. On the first call the `mIterator`
383  * field in @p aInfo MUST be set to zero.
384  *
385  * Here is an example of the generated hex dump output:
386  *
387  *  "==========================[{mTitle} len=070]============================"
388  *  "| 41 D8 87 34 12 FF FF 25 | 4C 57 DA F2 FB 2F 62 7F | A..4...%LW.../b. |"
389  *  "| 3B 01 F0 4D 4C 4D 4C 54 | 4F 00 15 15 00 00 00 00 | ;..MLMLTO....... |"
390  *  "| 00 00 00 01 80 DB 60 82 | 7E 33 72 3B CC B3 A1 84 | ......`.~3r;.... |"
391  *  "| 3B E6 AD B2 0B 45 E7 45 | C5 B9 00 1A CB 2D 6D 1C | ;....E.E.....-m. |"
392  *  "| 10 3E 3C F5 D3 70       |                         | .><..p           |"
393  *  "------------------------------------------------------------------------"
394  *
395  * @param[in,out] aInfo    A reference to a `LogHexDumpInfo` to use to generate hex dump.
396  *
397  * @retval kErrorNone      Successfully generated the next line, `mLine` field in @p aInfo is updated.
398  * @retval kErrorNotFound  Reached the end and no more line to generate.
399  */
400 Error GenerateNextHexDumpLine(HexDumpInfo &aInfo);
401 
402 } // namespace ot
403 
404 #endif // LOG_HPP_
405