[logging] update OT logging (use functions) (#5674)

This commit updates and enhances OT logging by implementing some of
more common operations as functions (instead of macros) and preparing
the entire log line (appending log level and/or log region to the log
string if the corresponding OT config options are enabled) before
passing it to platform layer.

The OT logging previously used macro definitions all the way to
platform layer call to `otPlatLog` (which itself can be defined as a
macro through an OT config). This model was adopted to address a
restriction/requirement on certain platforms (e.g., platforms that
required to enable/use log tokenization). However, using macros adds
an overhead on all other platforms that do not have such a
requirement.

This commit adds `OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY` which
when enabled (set to 1) keeps the implementation as before (i.e.,
macros are used in the logging module). By default this is disabled
which enables the new implementation added from this commit.

This commit also adds `OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME` which
replaces the previous `OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION_NAME`. This
config is used to override the `otPlatLog` and define it as a macro. A
build-time check is added in the `config-check.h` to help any project
that is integrating OT and may be using the macro name override
behavior to detect the change from this commit and update its config
definitions.

Finally, this commit updates `check-simulation-build-autotools` script
to add a build with `OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY`
enabled.
This commit is contained in:
Abtin Keshavarzian
2020-10-21 12:16:53 -07:00
committed by GitHub
parent 5f956cfe95
commit 8787cc106c
6 changed files with 561 additions and 344 deletions
+3
View File
@@ -99,6 +99,9 @@ build_all_features()
reset_source
make -f examples/Makefile-simulation FULL_LOGS=1
export CPPFLAGS="${options[*]} -DOPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY=1"
make -f examples/Makefile-simulation FULL_LOGS=1
export CPPFLAGS="${options[*]} ${options_1_2[*]} -DOPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_NONE"
reset_source
make -f examples/Makefile-simulation THREAD_VERSION=1.2
+189 -46
View File
@@ -46,14 +46,186 @@
#error OPENTHREAD_CONFIG_ENABLE_DEBUG_UART_LOG requires OPENTHREAD_CONFIG_ENABLE_DEBUG_UART
#endif
#define otLogDump(aFormat, ...) _otDynamicLog(aLogLevel, aLogRegion, aFormat OPENTHREAD_CONFIG_LOG_SUFFIX, __VA_ARGS__)
#ifdef __cplusplus
extern "C" {
#endif
#if !OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
static void Log(otLogLevel aLogLevel,
otLogRegion aLogRegion,
const char *aRegionPrefix,
const char *aFormat,
va_list aArgs)
{
ot::String<OPENTHREAD_CONFIG_LOG_MAX_SIZE> logString;
#if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
VerifyOrExit(otLoggingGetLevel() >= aLogLevel);
#endif
#if OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL
{
const char *levelStr = "";
switch (aLogLevel)
{
case OT_LOG_LEVEL_CRIT:
levelStr = _OT_LEVEL_CRIT_PREFIX;
break;
case OT_LOG_LEVEL_WARN:
levelStr = _OT_LEVEL_WARN_PREFIX;
break;
case OT_LOG_LEVEL_NOTE:
levelStr = _OT_LEVEL_NOTE_PREFIX;
break;
case OT_LOG_LEVEL_INFO:
levelStr = _OT_LEVEL_INFO_PREFIX;
break;
case OT_LOG_LEVEL_DEBG:
levelStr = _OT_LEVEL_DEBG_PREFIX;
break;
case OT_LOG_LEVEL_NONE:
default:
levelStr = _OT_LEVEL_NONE_PREFIX;
break;
}
#if OPENTHREAD_CONFIG_LOG_PREPEND_REGION
IgnoreError(logString.Append("[%s]", levelStr));
#endif
}
#endif // OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL
IgnoreError(logString.Append("%s", aRegionPrefix));
VerifyOrExit(logString.AppendVarArgs(aFormat, aArgs) != OT_ERROR_INVALID_ARGS);
otPlatLog(aLogLevel, aLogRegion, "%s" OPENTHREAD_CONFIG_LOG_SUFFIX, logString.AsCString());
exit:
return;
}
#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_CRIT
void otLogCrit(otLogRegion aRegion, const char *aRegionPrefix, const char *aFormat, ...)
{
va_list args;
va_start(args, aFormat);
Log(OT_LOG_LEVEL_CRIT, aRegion, aRegionPrefix, aFormat, args);
va_end(args);
}
#endif
#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_WARN
void otLogWarn(otLogRegion aRegion, const char *aRegionPrefix, const char *aFormat, ...)
{
va_list args;
va_start(args, aFormat);
Log(OT_LOG_LEVEL_WARN, aRegion, aRegionPrefix, aFormat, args);
va_end(args);
}
#endif
#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE
void otLogNote(otLogRegion aRegion, const char *aRegionPrefix, const char *aFormat, ...)
{
va_list args;
va_start(args, aFormat);
Log(OT_LOG_LEVEL_NOTE, aRegion, aRegionPrefix, aFormat, args);
va_end(args);
}
#endif
#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO
void otLogInfo(otLogRegion aRegion, const char *aRegionPrefix, const char *aFormat, ...)
{
va_list args;
va_start(args, aFormat);
Log(OT_LOG_LEVEL_INFO, aRegion, aRegionPrefix, aFormat, args);
va_end(args);
}
#endif
#if OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_DEBG
void otLogDebg(otLogRegion aRegion, const char *aRegionPrefix, const char *aFormat, ...)
{
va_list args;
va_start(args, aFormat);
Log(OT_LOG_LEVEL_DEBG, aRegion, aRegionPrefix, aFormat, args);
va_end(args);
}
#endif
#if OPENTHREAD_CONFIG_LOG_MAC
void otLogMac(otLogLevel aLogLevel, const char *aFormat, ...)
{
va_list args;
VerifyOrExit(otLoggingGetLevel() >= aLogLevel);
va_start(args, aFormat);
Log(aLogLevel, OT_LOG_REGION_MAC, _OT_REGION_MAC_PREFIX, aFormat, args);
va_end(args);
exit:
return;
}
#endif
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
void otLogCertMeshCoP(const char *aFormat, ...)
{
va_list args;
va_start(args, aFormat);
Log(OT_LOG_LEVEL_NONE, OT_LOG_REGION_MESH_COP, _OT_REGION_MESH_COP_PREFIX, aFormat, args);
va_end(args);
}
#endif
#if OPENTHREAD_CONFIG_OTNS_ENABLE
void otLogOtns(const char *aFormat, ...)
{
va_list args;
va_start(args, aFormat);
Log(OT_LOG_LEVEL_NONE, OT_LOG_REGION_CORE, _OT_REGION_CORE_PREFIX, aFormat, args);
va_end(args);
}
#endif
#endif // #if !OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
#if OPENTHREAD_CONFIG_LOG_PKT_DUMP
#if OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
#define otLogDump(aLogLevel, aLogRegion, aFormat, ...) \
_otDynamicLog(aLogLevel, aLogRegion, aFormat OPENTHREAD_CONFIG_LOG_SUFFIX, __VA_ARGS__)
#else
static void otLogDump(otLogLevel aLogLevel, otLogRegion aRegion, const char *aFormat, ...)
{
va_list args;
VerifyOrExit(otLoggingGetLevel() >= aLogLevel);
va_start(args, aFormat);
Log(aLogLevel, aRegion, "", aFormat, args);
va_end(args);
exit:
return;
}
#endif
enum : uint8_t
{
kStringLineLength = 80,
@@ -100,7 +272,7 @@ static void DumpLine(otLogLevel aLogLevel, otLogRegion aLogRegion, const uint8_t
IgnoreError(string.Append("%c", c));
}
otLogDump("%s", string.AsCString());
otLogDump(aLogLevel, aLogRegion, "%s", string.AsCString());
}
void otDump(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aId, const void *aBuf, const size_t aLength)
@@ -125,7 +297,7 @@ void otDump(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aId, const
IgnoreError(string.Append("="));
}
otLogDump("%s", string.AsCString());
otLogDump(aLogLevel, aLogRegion, "%s", string.AsCString());
for (size_t i = 0; i < aLength; i += kDumpBytesPerLine)
{
@@ -140,7 +312,7 @@ void otDump(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aId, const
IgnoreError(string.Append("-"));
}
otLogDump("%s", string.AsCString());
otLogDump(aLogLevel, aLogRegion, "%s", string.AsCString());
}
#else // OPENTHREAD_CONFIG_LOG_PKT_DUMP
void otDump(otLogLevel, otLogRegion, const char *, const void *, const size_t)
@@ -190,55 +362,26 @@ static const char *const sThreadErrorStrings[OT_NUM_ERRORS] = {
const char *otThreadErrorToString(otError aError)
{
const char *retval;
if (aError < OT_ARRAY_LENGTH(sThreadErrorStrings))
{
retval = sThreadErrorStrings[aError];
}
else
{
retval = "UnknownErrorType";
}
return retval;
return aError < OT_ARRAY_LENGTH(sThreadErrorStrings) ? sThreadErrorStrings[aError] : "UnknownErrorType";
}
#if OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
const char *otLogLevelToPrefixString(otLogLevel aLogLevel)
{
const char *retval = "";
static const char *const kLevelStrings[] = {
_OT_LEVEL_NONE_PREFIX, _OT_LEVEL_CRIT_PREFIX, _OT_LEVEL_WARN_PREFIX,
_OT_LEVEL_NOTE_PREFIX, _OT_LEVEL_INFO_PREFIX, _OT_LEVEL_DEBG_PREFIX,
};
switch (aLogLevel)
{
case OT_LOG_LEVEL_NONE:
retval = _OT_LEVEL_NONE_PREFIX;
break;
case OT_LOG_LEVEL_CRIT:
retval = _OT_LEVEL_CRIT_PREFIX;
break;
case OT_LOG_LEVEL_WARN:
retval = _OT_LEVEL_WARN_PREFIX;
break;
case OT_LOG_LEVEL_NOTE:
retval = _OT_LEVEL_NOTE_PREFIX;
break;
case OT_LOG_LEVEL_INFO:
retval = _OT_LEVEL_INFO_PREFIX;
break;
case OT_LOG_LEVEL_DEBG:
retval = _OT_LEVEL_DEBG_PREFIX;
break;
}
return retval;
return ((aLogLevel >= 0) && (aLogLevel < static_cast<int>(OT_ARRAY_LENGTH(kLevelStrings))))
? kLevelStrings[aLogLevel]
: "";
}
#endif
#if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_NONE
/* this provides a stub, incase something uses the function */
/* this provides a stub, in case something uses the function */
void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
{
OT_UNUSED_VARIABLE(aLogLevel);
File diff suppressed because it is too large Load Diff
+13
View File
@@ -212,6 +212,19 @@ public:
return error;
}
/**
* This method appends `printf()` style formatted data to the `String` object.
*
* @param[in] aFormat A pointer to the format string.
* @param[in] aArgs Arguments for the format specification (as `va_list`).
*
* @retval OT_ERROR_NONE Updated the string successfully.
* @retval OT_ERROR_NO_BUFS String could not fit in the storage.
* @retval OT_ERROR_INVALID_ARGS Arguments do not match the format string.
*
*/
otError AppendVarArgs(const char *aFormat, va_list aArgs) { return Write(mBuffer, kSize, mLength, aFormat, aArgs); }
/**
* This method appends an array of bytes in hex representation (using "%02x" style) to the `String` object.
*
+29 -4
View File
@@ -341,13 +341,38 @@
#endif
/**
* @def OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION
* @def OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
*
* Defines the name of function/macro used for logging inside OpenThread, by default it is set to `otPlatLog()`.
* Set to 1 to require all the logging related definition to user macro only (up to the call to the platform log API).
* Otherwise the logging implementation uses functions (which is preferred and recommended model).
*
* This is intended for special platform requirements where the logging needs to be defined a macro (e.g., for log
* tokenization or similar features).
*
*/
#ifndef OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION
#define OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION otPlatLog
#ifndef OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY
#define OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY 0
#endif
/**
* @def OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME
*
* Defines the name of macro used for logging inside OpenThread, by default it is set to `otPlatLog()`. This is used
* and applicable only when `OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY` is set to 1.
*
*/
#ifndef OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME
#define OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME otPlatLog
#endif
/**
* @def OPENTHREAD_CONFIG_LOG_MAX_SIZE
*
* The maximum log string size (number of chars).
*
*/
#ifndef OPENTHREAD_CONFIG_LOG_MAX_SIZE
#define OPENTHREAD_CONFIG_LOG_MAX_SIZE 150
#endif
#endif // CONFIG_LOGGING_H_
@@ -541,4 +541,9 @@
#error "OPENTHREAD_CONFIG_LOG_OUTPUT_NCP_SPINEL is removed, use OPENTHREAD_CONFIG_LOG_OUTPUT_APP instead"
#endif
#ifdef OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION
#error "OPENTHREAD_CONFIG_PLAT_LOG_FUNCTION was replaced by OPENTHREAD_CONFIG_PLAT_LOG_MACRO_NAME " \
"(and OPENTHREAD_CONFIG_LOG_DEFINE_AS_MACRO_ONLY)"
#endif
#endif // OPENTHREAD_CORE_CONFIG_CHECK_H_