mirror of
https://github.com/espressif/openthread.git
synced 2026-06-06 05:24:51 +00:00
[logging] introduce instance-aware platform logging API (#12737)
This commit adds `otPlatLogOutput()`, a new platform logging API that provides the `otInstance` pointer along with a pre-formatted log string. This addresses the limitation of the existing `otPlatLog()` in multi-instance builds, where the function cannot reliably determine which OpenThread instance generated the log. `OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE`, is introduced to enable this behavior. When enabled, `Logger::Log()` resolves the active instance (via a tracked global pointer `gActiveInstance`) and passes it to `otPlatLogOutput()`. To support tracking the active instance context, `UpdateActiveInstance()` is added and called during standard instance retrieval paths, such as `Locator::GetInstance()` and `Message::GetInstance()`. The TCP endpoints and listeners are also updated to track the active instance when their `GetInstance()` methods are invoked. The Nexus testing platform is updated to enable this configuration and implement `otPlatLogOutput()` to print the instance ID alongside the log line, simplifying log tracing in multi-node simulations.
This commit is contained in:
committed by
GitHub
parent
52551d8ff0
commit
b35cb137d5
@@ -52,7 +52,7 @@ extern "C" {
|
||||
*
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (583)
|
||||
#define OPENTHREAD_API_VERSION (584)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#ifndef OPENTHREAD_PLATFORM_LOGGING_H_
|
||||
#define OPENTHREAD_PLATFORM_LOGGING_H_
|
||||
|
||||
#include <openthread/instance.h>
|
||||
#include <openthread/platform/toolchain.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -140,6 +141,9 @@ typedef enum otLogRegion
|
||||
/**
|
||||
* Outputs logs.
|
||||
*
|
||||
* This platform API is used to output logs when the configuration `OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE`
|
||||
* is disabled. When the configuration is enabled, `otPlatLogOutput()` is used instead.
|
||||
*
|
||||
* Note that the support for log region is removed. The OT core will always emit all logs with `OT_LOG_REGION_CORE`
|
||||
* as @p aLogRegion.
|
||||
*
|
||||
@@ -151,6 +155,23 @@ typedef enum otLogRegion
|
||||
void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
|
||||
OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(3, 4);
|
||||
|
||||
/**
|
||||
* Outputs a log line.
|
||||
*
|
||||
* This platform API is an alternative to `otPlatLog()` and is used when the configuration
|
||||
* `OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE` is enabled.
|
||||
*
|
||||
* Unlike `otPlatLog()`, this API also provides a pointer to the OpenThread instance (`otInstance*`) from which the
|
||||
* log is generated. This is particularly helpful in a multi-instance setup to distinguish logs from different
|
||||
* instances. Additionally, it provides the log line as a fully formatted null-terminated string instead of
|
||||
* a format string and variable arguments.
|
||||
*
|
||||
* @param[in] aInstance A pointer to the OpenThread instance.
|
||||
* @param[in] aLogLevel The log level.
|
||||
* @param[in] aLogLine A pointer to the null-terminated string containing the log line.
|
||||
*/
|
||||
void otPlatLogOutput(otInstance *aInstance, otLogLevel aLogLevel, const char *aLogLine);
|
||||
|
||||
/**
|
||||
* Handles OpenThread log level changes.
|
||||
*
|
||||
|
||||
@@ -48,6 +48,13 @@ class Instance;
|
||||
extern uint64_t gInstanceRaw[];
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE
|
||||
extern Instance *gActiveInstance;
|
||||
inline Instance *UpdateActiveInstance(Instance *aInstance) { return gActiveInstance = aInstance; }
|
||||
#else
|
||||
inline Instance *UpdateActiveInstance(Instance *aInstance) { return aInstance; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup core-locator
|
||||
*
|
||||
@@ -117,7 +124,7 @@ public:
|
||||
* @returns A reference to the parent otInstance.
|
||||
*/
|
||||
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
|
||||
Instance &GetInstance(void) const { return *mInstance; }
|
||||
Instance &GetInstance(void) const { return *UpdateActiveInstance(mInstance); }
|
||||
#else
|
||||
Instance &GetInstance(void) const { return GetSingleInstance(); }
|
||||
#endif
|
||||
|
||||
@@ -166,7 +166,23 @@ void Logger::Log(const char *aModuleName, LogLevel aLogLevel, Error aError, cons
|
||||
}
|
||||
|
||||
logString.Append("%s", OPENTHREAD_CONFIG_LOG_SUFFIX);
|
||||
|
||||
#if OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE
|
||||
{
|
||||
Instance *instance;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
|
||||
instance = Instance::GetActiveInstance();
|
||||
VerifyOrExit(instance != nullptr);
|
||||
#else
|
||||
instance = &Instance::Get();
|
||||
#endif
|
||||
|
||||
otPlatLogOutput(instance, aLogLevel, logString.AsCString());
|
||||
}
|
||||
#else
|
||||
otPlatLog(aLogLevel, OT_LOG_REGION_CORE, "%s", logString.AsCString());
|
||||
#endif
|
||||
|
||||
ExitNow();
|
||||
|
||||
|
||||
@@ -476,7 +476,7 @@ public:
|
||||
* @returns A reference to the `Instance`.
|
||||
*/
|
||||
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
|
||||
Instance &GetInstance(void) const { return *GetMetadata().mInstance; }
|
||||
Instance &GetInstance(void) const { return *UpdateActiveInstance(GetMetadata().mInstance); }
|
||||
#else
|
||||
Instance &GetInstance(void) const { return GetSingleInstance(); }
|
||||
#endif
|
||||
|
||||
@@ -77,6 +77,20 @@
|
||||
/** Log output is handled by a platform defined function */
|
||||
#define OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED 3
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE
|
||||
*
|
||||
* Define to 1 to enable the instance-aware platform logging API.
|
||||
*
|
||||
* When this configuration is enabled, OpenThread logging will track the OpenThread instance (`otInstance`) from which
|
||||
* a log is generated. The core will use the `otPlatLogOutput()` platform API instead of `otPlatLog()`. The new
|
||||
* platform API provides the `otInstance` pointer along with the log as a fully formatted string, which is particularly
|
||||
* useful in multi-instance setups to distinguish logs from different OpenThread instances.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE
|
||||
#define OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_LEVEL
|
||||
*
|
||||
|
||||
@@ -51,6 +51,11 @@ OT_DEFINE_ALIGNED_VAR(gInstanceRaw, sizeof(Instance), uint64_t);
|
||||
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE
|
||||
// The currently active instance
|
||||
Instance *gActiveInstance = nullptr;
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE
|
||||
|
||||
#define INSTANCE_SIZE_ALIGNED OT_ALIGNED_VAR_SIZE(sizeof(ot::Instance), uint64_t)
|
||||
@@ -411,6 +416,10 @@ exit:
|
||||
return instance;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE
|
||||
Instance *Instance::GetActiveInstance(void) { return gActiveInstance; }
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
|
||||
|
||||
void Instance::Reset(void) { otPlatReset(this); }
|
||||
|
||||
@@ -429,6 +429,17 @@ public:
|
||||
*/
|
||||
template <typename Type> inline Type &Get(void);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE
|
||||
/**
|
||||
* Gets the currently active OpenThread instance.
|
||||
*
|
||||
* It is used to determine the active instance primarily for logging purposes.
|
||||
*
|
||||
* @returns A pointer to the active OpenThread instance, or `nullptr` if not known.
|
||||
*/
|
||||
static Instance *GetActiveInstance(void);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_PLATFORM_NEXUS
|
||||
/**
|
||||
* Constructor to initialize an `Instance`
|
||||
|
||||
@@ -109,7 +109,10 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Instance &Tcp::Endpoint::GetInstance(void) const { return AsNonConst(AsCoreType(GetTcb().instance)); }
|
||||
Instance &Tcp::Endpoint::GetInstance(void) const
|
||||
{
|
||||
return *UpdateActiveInstance(&AsNonConst(AsCoreType(GetTcb().instance)));
|
||||
}
|
||||
|
||||
const SockAddr &Tcp::Endpoint::GetLocalAddress(void) const
|
||||
{
|
||||
@@ -547,7 +550,10 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Instance &Tcp::Listener::GetInstance(void) const { return AsNonConst(AsCoreType(GetTcbListen().instance)); }
|
||||
Instance &Tcp::Listener::GetInstance(void) const
|
||||
{
|
||||
return *UpdateActiveInstance(&AsNonConst(AsCoreType(GetTcbListen().instance)));
|
||||
}
|
||||
|
||||
Error Tcp::Listener::Listen(const SockAddr &aSockName)
|
||||
{
|
||||
|
||||
@@ -83,7 +83,6 @@
|
||||
#define OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_JOINER_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_INFO
|
||||
|
||||
#define OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_LOG_LEVEL_INIT OT_LOG_LEVEL_CRIT
|
||||
#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED
|
||||
@@ -91,6 +90,7 @@
|
||||
#define OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL 1
|
||||
#define OPENTHREAD_CONFIG_LOG_PREPEND_UPTIME 0
|
||||
#define OPENTHREAD_CONFIG_LOG_SUFFIX ""
|
||||
#define OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_MAC_FILTER_ENABLE 1
|
||||
|
||||
@@ -39,8 +39,7 @@
|
||||
namespace ot {
|
||||
namespace Nexus {
|
||||
|
||||
static void LogVarArgs(Node *aActiveNode, const char *aFormat, va_list aArgs)
|
||||
OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(2, 0);
|
||||
static void LogTime(void);
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -57,16 +56,18 @@ void otTaskletsSignalPending(otInstance *aInstance)
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// otPlatLog
|
||||
|
||||
void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
|
||||
void otPlatLogOutput(otInstance *aInstance, otLogLevel aLogLevel, const char *aLogLine)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aLogLevel);
|
||||
OT_UNUSED_VARIABLE(aLogRegion);
|
||||
|
||||
va_list args;
|
||||
VerifyOrExit(aInstance != nullptr);
|
||||
|
||||
va_start(args, aFormat);
|
||||
LogVarArgs(Core::Get().GetActiveNode(), aFormat, args);
|
||||
va_end(args);
|
||||
LogTime();
|
||||
printf("%03u %s\n", AsNode(aInstance).GetId(), aLogLine);
|
||||
fflush(stdout);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
@@ -136,29 +137,25 @@ void otPlatWakeHost(void) {}
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// Log related function
|
||||
|
||||
static void LogTime(void)
|
||||
{
|
||||
uint32_t now = Core::Get().GetNow().GetValue();
|
||||
|
||||
printf("%02u:%02u:%02u.%03u ", now / 3600000, (now / 60000) % 60, (now / 1000) % 60, now % 1000);
|
||||
}
|
||||
|
||||
void Log(const char *aFormat, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, aFormat);
|
||||
LogVarArgs(nullptr, aFormat, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void LogVarArgs(Node *aActiveNode, const char *aFormat, va_list aArgs)
|
||||
{
|
||||
uint32_t now = Core::Get().GetNow().GetValue();
|
||||
|
||||
printf("%02u:%02u:%02u.%03u ", now / 3600000, (now / 60000) % 60, (now / 1000) % 60, now % 1000);
|
||||
|
||||
if (aActiveNode != nullptr)
|
||||
{
|
||||
printf("%03u ", aActiveNode->GetInstance().GetId());
|
||||
}
|
||||
|
||||
vprintf(aFormat, aArgs);
|
||||
LogTime();
|
||||
vprintf(aFormat, args);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
} // namespace Nexus
|
||||
|
||||
Reference in New Issue
Block a user