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 * This macro 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 * This enumeration 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 * This macro registers log module name. 82 * 83 * This macro 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 * This macro emits a log message at critical log level. 106 * 107 * @param[in] ... Arguments for the format specification. 108 * 109 */ 110 #define LogCrit(...) Logger::Log<kLogLevelCrit, kLogModuleName>(__VA_ARGS__) 111 #else 112 #define LogCrit(...) 113 #endif 114 115 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN) 116 /** 117 * This macro emits a log message at warning log level. 118 * 119 * @param[in] ... Arguments for the format specification. 120 * 121 */ 122 #define LogWarn(...) Logger::Log<kLogLevelWarn, kLogModuleName>(__VA_ARGS__) 123 #else 124 #define LogWarn(...) 125 #endif 126 127 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE) 128 /** 129 * This macro emits a log message at note log level. 130 * 131 * @param[in] ... Arguments for the format specification. 132 * 133 */ 134 #define LogNote(...) Logger::Log<kLogLevelNote, kLogModuleName>(__VA_ARGS__) 135 #else 136 #define LogNote(...) 137 #endif 138 139 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) 140 /** 141 * This macro emits a log message at info log level. 142 * 143 * @param[in] ... Arguments for the format specification. 144 * 145 */ 146 #define LogInfo(...) Logger::Log<kLogLevelInfo, kLogModuleName>(__VA_ARGS__) 147 #else 148 #define LogInfo(...) 149 #endif 150 151 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_DEBG) 152 /** 153 * This macro emits a log message at debug log level. 154 * 155 * @param[in] ... Arguments for the format specification. 156 * 157 */ 158 #define LogDebg(...) Logger::Log<kLogLevelDebg, kLogModuleName>(__VA_ARGS__) 159 #else 160 #define LogDebg(...) 161 #endif 162 163 #if OT_SHOULD_LOG 164 /** 165 * This macro 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 * This macro 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 * This macro 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 * This macro 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 * This macro 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 * This macro 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 * This macro 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 * This macro 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 * This macro 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 * This macro 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 template <LogLevel kLogLevel, const char *kModuleName, typename... Args> Log(const char * aFormat,Args...aArgs)309 static void Log(const char *aFormat, Args... aArgs) 310 { 311 LogAtLevel<kLogLevel>(kModuleName, aFormat, aArgs...); 312 } 313 314 static void LogInModule(const char *aModuleName, LogLevel aLogLevel, const char *aFormat, ...); 315 316 template <LogLevel kLogLevel> static void LogAtLevel(const char *aModuleName, const char *aFormat, ...); 317 static void LogVarArgs(const char *aModuleName, LogLevel aLogLevel, const char *aFormat, va_list aArgs); 318 319 #if OPENTHREAD_CONFIG_LOG_PKT_DUMP 320 static constexpr uint8_t kStringLineLength = 80; 321 static constexpr uint8_t kDumpBytesPerLine = 16; 322 323 template <LogLevel kLogLevel, const char *kModuleName> Dump(const char * aText,const void * aData,uint16_t aDataLength)324 static void Dump(const char *aText, const void *aData, uint16_t aDataLength) 325 { 326 DumpAtLevel<kLogLevel>(kModuleName, aText, aData, aDataLength); 327 } 328 329 static void DumpInModule(const char *aModuleName, 330 LogLevel aLogLevel, 331 const char *aText, 332 const void *aData, 333 uint16_t aDataLength); 334 335 template <LogLevel kLogLevel> 336 static void DumpAtLevel(const char *aModuleName, const char *aText, const void *aData, uint16_t aDataLength); 337 338 static void DumpLine(const char *aModuleName, LogLevel aLogLevel, const uint8_t *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 } // namespace ot 378 379 #endif // LOG_HPP_ 380