logging: Add frontend support to v2

Extended logging v2 to support frontend api. Contrary to v1,
it is possible to have frontend and backends in the system.

Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
Krzysztof Chruscinski 2022-01-25 09:10:15 +01:00 committed by Anas Nashif
commit 7c72b78660
12 changed files with 95 additions and 24 deletions

View file

@ -287,7 +287,9 @@ void z_log_vprintk(const char *fmt, va_list ap);
char *z_log_strdup(const char *str);
static inline char *log_strdup(const char *str)
{
if (IS_ENABLED(CONFIG_LOG_MODE_MINIMAL) || IS_ENABLED(CONFIG_LOG2)) {
if (IS_ENABLED(CONFIG_LOG_MODE_MINIMAL) ||
IS_ENABLED(CONFIG_LOG_FRONTEND) ||
IS_ENABLED(CONFIG_LOG2)) {
return (char *)str;
}

View file

@ -201,7 +201,9 @@ extern "C" {
#define Z_LOG_INTERNAL2(is_user_context, _src_level, ...) do { \
if (is_user_context) { \
if (!IS_ENABLED(CONFIG_LOG_FRONTEND)) { \
log_from_user(_src_level, __VA_ARGS__); \
} \
} else if (IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE)) { \
log_string_sync(_src_level, __VA_ARGS__); \
} else { \
@ -334,8 +336,8 @@ static inline char z_log_minimal_level_to_char(int level)
bool is_user_context = k_is_user_context(); \
uint32_t filters = IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) ? \
(_dsource)->filters : 0;\
if (IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) && !is_user_context && \
_level > Z_LOG_RUNTIME_FILTER(filters)) { \
if (!IS_ENABLED(CONFIG_LOG_FRONTEND) && IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) && \
!is_user_context && _level > Z_LOG_RUNTIME_FILTER(filters)) { \
break; \
} \
if (IS_ENABLED(CONFIG_LOG2)) { \
@ -414,8 +416,8 @@ static inline char z_log_minimal_level_to_char(int level)
(const char *)_data, _len);\
break; \
} \
if (IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) && !is_user_context && \
_level > Z_LOG_RUNTIME_FILTER(filters)) { \
if (!IS_ENABLED(CONFIG_LOG_FRONTEND) && IS_ENABLED(CONFIG_LOG_RUNTIME_FILTERING) && \
!is_user_context && _level > Z_LOG_RUNTIME_FILTER(filters)) { \
break; \
} \
if (IS_ENABLED(CONFIG_LOG2)) { \
@ -440,8 +442,9 @@ static inline char z_log_minimal_level_to_char(int level)
.source_id = src_id, \
}; \
if (is_user_context) { \
log_hexdump_from_user(src_level, _str, \
(const char *)_data, _len); \
if (!IS_ENABLED(CONFIG_LOG_FRONTEND)) { \
log_hexdump_from_user(src_level, _str, (const char *)_data, _len); \
} \
} else if (IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE)) { \
log_hexdump_sync(src_level, _str, (const char *)_data, _len); \
} else { \

View file

@ -263,7 +263,7 @@ int log_mem_get_usage(uint32_t *buf_size, uint32_t *usage);
*/
int log_mem_get_max_usage(uint32_t *max);
#if defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_MINIMAL)
#if defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_MINIMAL) && !defined(CONFIG_LOG_FRONTEND_ONLY)
#define LOG_CORE_INIT() log_core_init()
#define LOG_INIT() log_init()
#define LOG_PANIC() log_panic()

View file

@ -79,5 +79,27 @@ void log_frontend_hexdump(const char *str,
uint32_t length,
struct log_msg_ids src_level);
/** @brief Log message.
*
* Message details does not contain timestamp. Since function is called in the
* context of log message call, implementation can use its own timestamping scheme.
*
* @param source Pointer to a structure associated with given source. It points to
* static structure or dynamic structure if runtime filtering is enabled.
* @ref log_const_source_id or @ref log_dynamic_source_id can be used to determine
* source id.
*
* @param desc Message descriptor.
*
* @param package Cbprintf package containing logging formatted string. Length s in @p desc.
*
* @param data Hexdump data. Length is in @p desc.
*/
void log_frontend_msg(const void *source,
const struct log_msg2_desc desc,
uint8_t *package, const void *data);
/** @brief Panic state notification. */
void log_frontend_panic(void);
#endif /* LOG_FRONTEND_H_ */

View file

@ -14,7 +14,7 @@ rsource "Kconfig.mode"
rsource "Kconfig.filtering"
if !LOG_FRONTEND && !LOG_MODE_MINIMAL
if !LOG_FRONTEND_ONLY && !LOG_MODE_MINIMAL
rsource "Kconfig.formatting"
@ -22,7 +22,7 @@ rsource "Kconfig.processing"
rsource "Kconfig.backends"
endif # !LOG_FRONTEND && !LOG_MODE_MINIMAL
endif # !LOG_FRONTEND_ONLY && !LOG_MODE_MINIMAL
rsource "Kconfig.misc"

View file

@ -5,7 +5,7 @@ menu "Logging levels filtering"
config LOG_RUNTIME_FILTERING
bool "Runtime filtering reconfiguration"
depends on !LOG_FRONTEND && !LOG_MODE_MINIMAL
depends on !LOG_FRONTEND_ONLY && !LOG_MODE_MINIMAL
help
Allow runtime configuration of maximal, independent severity
level for instance.

View file

@ -4,7 +4,7 @@
menu "Output Formatting"
menu "Prepend non-hexdump log message with function name"
depends on !LOG_FRONTEND
depends on !LOG_FRONTEND_ONLY
config LOG_FUNC_NAME_PREFIX_ERR
bool "Error messages prepended"

View file

@ -14,7 +14,7 @@ config LOG_DOMAIN_ID
config LOG_CMDS
bool "Shell commands"
depends on SHELL
depends on !LOG_FRONTEND && !LOG_MODE_MINIMAL
depends on !LOG_FRONTEND_ONLY && !LOG_MODE_MINIMAL
default y if SHELL
config LOG_TEST_CLEAR_MESSAGE_SPACE

View file

@ -40,16 +40,23 @@ config LOG_MODE_MINIMAL
colors, or asynchronous logging, and all messages are simply
sent to printk().
endchoice
config LOG_FRONTEND
bool "Frontend"
depends on !LOG2_MODE_DEFERRED
depends on !LOG2_MODE_IMMEDIATE
help
When enabled, logs are redirected to a custom frontend instead
of being processed by the logger. In this mode runtime filtering and
multiple backends are not used.
When enabled, logs are redirected to a custom frontend which is the
fastest way of getting logs out.
endchoice
config LOG_FRONTEND_ONLY
bool "No backends" if !LOG1
default y if LOG1
depends on LOG_FRONTEND
help
Option indicates that there are no backends intended to be used.
Code asserts if any backend is enabled.
config LOG2_MODE_DEFERRED
bool "Deferred v2 (DEPRECATED)"

View file

@ -164,6 +164,7 @@ config LOG_TIMESTAMP_64BIT
config LOG_SPEED
bool "Prefer performance over size"
depends on LOG_MODE_DEFERRED
depends on !LOG_FRONTEND
help
If enabled, logging may take more code size to get faster logging.
endif # LOG2

View file

@ -60,6 +60,10 @@ LOG_MODULE_REGISTER(log);
#define CONFIG_LOG_BUFFER_SIZE 4
#endif
#ifndef CONFIG_LOG_TAG_MAX_LEN
#define CONFIG_LOG_TAG_MAX_LEN 0
#endif
#ifndef CONFIG_LOG2_ALWAYS_RUNTIME
BUILD_ASSERT(!IS_ENABLED(CONFIG_NO_OPTIMIZATIONS),
"Option must be enabled when CONFIG_NO_OPTIMIZATIONS is set");
@ -687,6 +691,10 @@ void z_impl_log_panic(void)
*/
log_init();
if (IS_ENABLED(CONFIG_LOG_FRONTEND)) {
log_frontend_panic();
}
for (int i = 0; i < log_backend_count_get(); i++) {
backend = log_backend_get(i);

View file

@ -7,6 +7,13 @@
#include <syscall_handler.h>
#include <logging/log_internal.h>
#include <logging/log_ctrl.h>
#include <logging/log_frontend.h>
#include <logging/log_backend.h>
/* Returns true if any backend is in use. */
#define BACKENDS_IN_USE() \
!(IS_ENABLED(CONFIG_LOG_FRONTEND) && \
(IS_ENABLED(CONFIG_LOG_FRONTEND_ONLY) || log_backend_count_get() == 0))
void z_log_msg2_finalize(struct log_msg2 *msg, const void *source,
const struct log_msg2_desc desc, const void *data)
@ -32,6 +39,14 @@ void z_impl_z_log_msg2_static_create(const void *source,
const struct log_msg2_desc desc,
uint8_t *package, const void *data)
{
if (IS_ENABLED(CONFIG_LOG_FRONTEND)) {
log_frontend_msg(source, desc, package, data);
}
if (!BACKENDS_IN_USE()) {
return;
}
uint32_t msg_wlen = log_msg2_get_total_wlen(desc);
struct log_msg2 *msg = z_log_msg2_alloc(msg_wlen);
@ -72,21 +87,34 @@ void z_impl_z_log_msg2_runtime_vcreate(uint8_t domain_id, const void *source,
size_t msg_wlen = Z_LOG_MSG2_ALIGNED_WLEN(plen, dlen);
struct log_msg2 *msg;
uint8_t *pkg;
struct log_msg2_desc desc =
Z_LOG_MSG_DESC_INITIALIZER(domain_id, level, plen, dlen);
if (IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE)) {
msg = alloca(msg_wlen * sizeof(int));
} else {
if (IS_ENABLED(CONFIG_LOG_MODE_DEFERRED) && BACKENDS_IN_USE()) {
msg = z_log_msg2_alloc(msg_wlen);
if (IS_ENABLED(CONFIG_LOG_FRONTEND) && msg == NULL) {
pkg = alloca(plen);
} else {
pkg = msg ? msg->data : NULL;
}
} else {
msg = alloca(msg_wlen * sizeof(int));
pkg = msg->data;
}
if (msg && fmt) {
plen = cbvprintf_package(msg->data, (size_t)plen, package_flags, fmt, ap);
if (pkg && fmt) {
plen = cbvprintf_package(pkg, (size_t)plen, package_flags, fmt, ap);
__ASSERT_NO_MSG(plen >= 0);
}
if (IS_ENABLED(CONFIG_LOG_FRONTEND)) {
log_frontend_msg(source, desc, pkg, data);
}
if (BACKENDS_IN_USE()) {
z_log_msg2_finalize(msg, source, desc, data);
}
}
#ifdef CONFIG_USERSPACE