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 namespace ot { 44 45 /** 46 * @def OT_SHOULD_LOG 47 * 48 * This definition indicates whether or not logging is enabled. 49 * 50 */ 51 #define OT_SHOULD_LOG (OPENTHREAD_CONFIG_LOG_OUTPUT != OPENTHREAD_CONFIG_LOG_OUTPUT_NONE) 52 53 /** 54 * Indicates whether the OpenThread logging is enabled at a given log level. 55 * 56 * @param[in] aLevel The log level to check. 57 * 58 * @returns TRUE if logging is enabled at @p aLevel, FALSE otherwise. 59 * 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 */ 67 enum LogLevel : uint8_t 68 { 69 kLogLevelNone = OT_LOG_LEVEL_NONE, ///< None (disable logs) 70 kLogLevelCrit = OT_LOG_LEVEL_CRIT, ///< Critical log level 71 kLogLevelWarn = OT_LOG_LEVEL_WARN, ///< Warning log level 72 kLogLevelNote = OT_LOG_LEVEL_NOTE, ///< Note log level 73 kLogLevelInfo = OT_LOG_LEVEL_INFO, ///< Info log level 74 kLogLevelDebg = OT_LOG_LEVEL_DEBG, ///< Debug log level 75 }; 76 77 constexpr uint8_t kMaxLogModuleNameLength = 14; ///< Maximum module name length 78 79 #if OT_SHOULD_LOG && (OPENTHREAD_CONFIG_LOG_LEVEL != OT_LOG_LEVEL_NONE) 80 /** 81 * Registers log module name. 82 * 83 * Is used in a `cpp` file to register the log module name for that file before using any other logging 84 * functions or macros (e.g., `LogInfo()` or `DumpInfo()`, ...) in the file. 85 * 86 * @param[in] aName The log module name string (MUST be shorter than `kMaxLogModuleNameLength`). 87 * 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 */ 110 #define LogCrit(...) Logger::LogAtLevel<kLogLevelCrit>(kLogModuleName, __VA_ARGS__) 111 #else 112 #define LogCrit(...) 113 #endif 114 115 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN) 116 /** 117 * Emits a log message at warning log level. 118 * 119 * @param[in] ... Arguments for the format specification. 120 * 121 */ 122 #define LogWarn(...) Logger::LogAtLevel<kLogLevelWarn>(kLogModuleName, __VA_ARGS__) 123 #else 124 #define LogWarn(...) 125 #endif 126 127 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) 128 /** 129 * Emits a log message at note log level. 130 * 131 * @param[in] ... Arguments for the format specification. 132 * 133 */ 134 #define LogNote(...) Logger::LogAtLevel<kLogLevelNote>(kLogModuleName, __VA_ARGS__) 135 #else 136 #define LogNote(...) 137 #endif 138 139 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) 140 /** 141 * Emits a log message at info log level. 142 * 143 * @param[in] ... Arguments for the format specification. 144 * 145 */ 146 #define LogInfo(...) Logger::LogAtLevel<kLogLevelInfo>(kLogModuleName, __VA_ARGS__) 147 #else 148 #define LogInfo(...) 149 #endif 150 151 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_DEBG) 152 /** 153 * Emits a log message at debug log level. 154 * 155 * @param[in] ... Arguments for the format specification. 156 * 157 */ 158 #define LogDebg(...) Logger::LogAtLevel<kLogLevelDebg>(kLogModuleName, __VA_ARGS__) 159 #else 160 #define LogDebg(...) 161 #endif 162 163 #if OT_SHOULD_LOG 164 /** 165 * Emits a log message at a given log level. 166 * 167 * @param[in] aLogLevel The log level to use. 168 * @param[in] ... Argument for the format specification. 169 * 170 */ 171 #define LogAt(aLogLevel, ...) Logger::LogInModule(kLogModuleName, aLogLevel, __VA_ARGS__) 172 #else 173 #define LogAt(aLogLevel, ...) 174 #endif 175 176 #if OT_SHOULD_LOG 177 /** 178 * Emits a log message independent of the configured log level. 179 * 180 * @param[in] ... Arguments for the format specification. 181 * 182 */ 183 #define LogAlways(...) Logger::LogInModule("", kLogLevelNone, __VA_ARGS__) 184 #else 185 #define LogAlways(...) 186 #endif 187 188 #if OT_SHOULD_LOG && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 189 /** 190 * Emit a log message for the certification test. 191 * 192 * @param[in] ... Arguments for the format specification. 193 * 194 */ 195 #define LogCert(...) LogAlways(__VA_ARGS__) 196 #else 197 #define LogCert(...) 198 #endif 199 200 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_CRIT) && OPENTHREAD_CONFIG_LOG_PKT_DUMP 201 /** 202 * Generates a memory dump at log level critical. 203 * 204 * @param[in] aText A string that is printed before the bytes. 205 * @param[in] aData A pointer to the data buffer. 206 * @param[in] aDataLength Number of bytes in @p aData. 207 * 208 */ 209 #define DumpCrit(aText, aData, aDataLength) Logger::Dump<kLogLevelCrit, kLogModuleName>(aText, aData, aDataLength) 210 #else 211 #define DumpCrit(aText, aData, aDataLength) 212 #endif 213 214 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN) && OPENTHREAD_CONFIG_LOG_PKT_DUMP 215 /** 216 * Generates a memory dump at log level warning. 217 * 218 * @param[in] aText A string that is printed before the bytes. 219 * @param[in] aData A pointer to the data buffer. 220 * @param[in] aDataLength Number of bytes in @p aData. 221 * 222 */ 223 #define DumpWarn(aText, aData, aDataLength) Logger::Dump<kLogLevelWarn, kLogModuleName>(aText, aData, aDataLength) 224 #else 225 #define DumpWarn(aText, aData, aDataLength) 226 #endif 227 228 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) && OPENTHREAD_CONFIG_LOG_PKT_DUMP 229 /** 230 * Generates a memory dump at log level note. 231 * 232 * @param[in] aText A string that is printed before the bytes. 233 * @param[in] aData A pointer to the data buffer. 234 * @param[in] aDataLength Number of bytes in @p aData. 235 * 236 */ 237 #define DumpNote(aText, aData, aDataLength) Logger::Dump<kLogLevelNote, kLogModuleName>(aText, aData, aDataLength) 238 #else 239 #define DumpNote(aText, aData, aDataLength) 240 #endif 241 242 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) && OPENTHREAD_CONFIG_LOG_PKT_DUMP 243 /** 244 * Generates a memory dump at log level info. 245 * 246 * @param[in] aText A string that is printed before the bytes. 247 * @param[in] aData A pointer to the data buffer. 248 * @param[in] aDataLength Number of bytes in @p aData. 249 * 250 */ 251 #define DumpInfo(aText, aData, aDataLength) Logger::Dump<kLogLevelInfo, kLogModuleName>(aText, aData, aDataLength) 252 #else 253 #define DumpInfo(aText, aData, aDataLength) 254 #endif 255 256 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_DEBG) && OPENTHREAD_CONFIG_LOG_PKT_DUMP 257 /** 258 * Generates a memory dump at log level debug. 259 * 260 * @param[in] aText A string that is printed before the bytes. 261 * @param[in] aData A pointer to the data buffer. 262 * @param[in] aDataLength Number of bytes in @p aData. 263 * 264 */ 265 #define DumpDebg(aText, aData, aDataLength) Logger::Dump<kLogLevelDebg, kLogModuleName>(aText, aData, aDataLength) 266 #else 267 #define DumpDebg(aText, aData, aDataLength) 268 #endif 269 270 #if OT_SHOULD_LOG && OPENTHREAD_CONFIG_LOG_PKT_DUMP 271 /** 272 * Generates a memory dump independent of the configured log level. 273 * 274 * @param[in] aText A string that is printed before the bytes. 275 * @param[in] aData A pointer to the data buffer. 276 * @param[in] aDataLength Number of bytes in @p aData. 277 * 278 */ 279 #define DumpAlways(aText, aData, aDataLength) Logger::DumpInModule("", kLogLevelNone, aText, aData, aDataLength) 280 #endif 281 282 #if OT_SHOULD_LOG && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE && OPENTHREAD_CONFIG_LOG_PKT_DUMP 283 /** 284 * Generates a memory dump for certification test. 285 * 286 * @param[in] aText A string that is printed before the bytes. 287 * @param[in] aData A pointer to the data buffer. 288 * @param[in] aDataLength Number of bytes in @p aData. 289 * 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 OPENTHREAD_CONFIG_LOG_PKT_DUMP 318 static constexpr uint8_t kStringLineLength = 80; 319 static constexpr uint8_t kDumpBytesPerLine = 16; 320 321 template <LogLevel kLogLevel, const char *kModuleName> Dump(const char * aText,const void * aData,uint16_t aDataLength)322 static void Dump(const char *aText, const void *aData, uint16_t aDataLength) 323 { 324 DumpAtLevel<kLogLevel>(kModuleName, aText, aData, aDataLength); 325 } 326 327 static void DumpInModule(const char *aModuleName, 328 LogLevel aLogLevel, 329 const char *aText, 330 const void *aData, 331 uint16_t aDataLength); 332 333 template <LogLevel kLogLevel> 334 static void DumpAtLevel(const char *aModuleName, const char *aText, const void *aData, uint16_t aDataLength); 335 336 static void DumpLine(const char *aModuleName, LogLevel aLogLevel, const uint8_t *aData, uint16_t aDataLength); 337 #endif 338 }; 339 340 extern template void Logger::LogAtLevel<kLogLevelNone>(const char *aModuleName, const char *aFormat, ...); 341 extern template void Logger::LogAtLevel<kLogLevelCrit>(const char *aModuleName, const char *aFormat, ...); 342 extern template void Logger::LogAtLevel<kLogLevelWarn>(const char *aModuleName, const char *aFormat, ...); 343 extern template void Logger::LogAtLevel<kLogLevelNote>(const char *aModuleName, const char *aFormat, ...); 344 extern template void Logger::LogAtLevel<kLogLevelInfo>(const char *aModuleName, const char *aFormat, ...); 345 extern template void Logger::LogAtLevel<kLogLevelDebg>(const char *aModuleName, const char *aFormat, ...); 346 347 #if OPENTHREAD_CONFIG_LOG_PKT_DUMP 348 extern template void Logger::DumpAtLevel<kLogLevelNone>(const char *aModuleName, 349 const char *aText, 350 const void *aData, 351 uint16_t aDataLength); 352 extern template void Logger::DumpAtLevel<kLogLevelCrit>(const char *aModuleName, 353 const char *aText, 354 const void *aData, 355 uint16_t aDataLength); 356 extern template void Logger::DumpAtLevel<kLogLevelWarn>(const char *aModuleName, 357 const char *aText, 358 const void *aData, 359 uint16_t aDataLength); 360 extern template void Logger::DumpAtLevel<kLogLevelNote>(const char *aModuleName, 361 const char *aText, 362 const void *aData, 363 uint16_t aDataLength); 364 extern template void Logger::DumpAtLevel<kLogLevelInfo>(const char *aModuleName, 365 const char *aText, 366 const void *aData, 367 uint16_t aDataLength); 368 extern template void Logger::DumpAtLevel<kLogLevelDebg>(const char *aModuleName, 369 const char *aText, 370 const void *aData, 371 uint16_t aDataLength); 372 #endif // OPENTHREAD_CONFIG_LOG_PKT_DUMP 373 #endif // OT_SHOULD_LOG 374 375 } // namespace ot 376 377 #endif // LOG_HPP_ 378