logging: enable setting custom logging output func
To enable custom formatting of the log output while still using existing backend, this commit adds the `log_output_custom` feature. To use, register a commit with `log_custom_output_msg_set` then set the log backend format set using `log_backend_format_set` with `LOG_OUTPUT_CUSTOM` Signed-off-by: Lucas Denefle <lucas.denefle@converge.io>
This commit is contained in:
parent
4eb7077978
commit
2efc9cc847
10 changed files with 178 additions and 13 deletions
|
@ -61,6 +61,8 @@ extern "C" {
|
||||||
|
|
||||||
#define LOG_OUTPUT_DICT 2
|
#define LOG_OUTPUT_DICT 2
|
||||||
|
|
||||||
|
#define LOG_OUTPUT_CUSTOM 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Prototype of the function processing output data.
|
* @brief Prototype of the function processing output data.
|
||||||
*
|
*
|
||||||
|
|
47
include/zephyr/logging/log_output_custom.h
Normal file
47
include/zephyr/logging/log_output_custom.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Converge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_OUTPUT_CUSTOM_H_
|
||||||
|
#define ZEPHYR_INCLUDE_LOGGING_LOG_OUTPUT_CUSTOM_H_
|
||||||
|
|
||||||
|
#include <zephyr/logging/log_output.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @brief Custom logging output formatting.
|
||||||
|
* @ingroup log_output
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @brief Process log messages from an external output function set with
|
||||||
|
* log_custom_output_msg_set
|
||||||
|
*
|
||||||
|
* Function is using provided context with the buffer and output function to
|
||||||
|
* process formatted string and output the data.
|
||||||
|
*
|
||||||
|
* @param log_output Pointer to the log output instance.
|
||||||
|
* @param msg Log message.
|
||||||
|
* @param flags Optional flags.
|
||||||
|
*/
|
||||||
|
void log_custom_output_msg_process(const struct log_output *log_output,
|
||||||
|
struct log_msg *msg, uint32_t flags);
|
||||||
|
|
||||||
|
/** @brief Set the formatting log function that will be applied with LOG_OUTPUT_CUSTOM
|
||||||
|
*
|
||||||
|
* @param format Pointer to the external formatter function
|
||||||
|
*/
|
||||||
|
void log_custom_output_msg_set(log_format_func_t format);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_OUTPUT_CUSTOM_H_ */
|
|
@ -54,6 +54,10 @@ if(NOT CONFIG_LOG_MODE_MINIMAL)
|
||||||
|
|
||||||
add_subdirectory(backends)
|
add_subdirectory(backends)
|
||||||
|
|
||||||
|
if(CONFIG_LOG_CUSTOM_FORMAT_SUPPORT)
|
||||||
|
zephyr_sources(log_output_custom.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
else()
|
else()
|
||||||
zephyr_sources(log_minimal.c)
|
zephyr_sources(log_minimal.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -104,6 +104,13 @@ config LOG_DICTIONARY_SUPPORT
|
||||||
|
|
||||||
This should be selected by the backend automatically.
|
This should be selected by the backend automatically.
|
||||||
|
|
||||||
|
config LOG_CUSTOM_FORMAT_SUPPORT
|
||||||
|
bool "Custom format support"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable support for custom formatter.
|
||||||
|
Allows custom format callbacks registering for logging backend.
|
||||||
|
|
||||||
config LOG_IMMEDIATE_CLEAN_OUTPUT
|
config LOG_IMMEDIATE_CLEAN_OUTPUT
|
||||||
bool "Clean log output"
|
bool "Clean log output"
|
||||||
depends on LOG_MODE_IMMEDIATE
|
depends on LOG_MODE_IMMEDIATE
|
||||||
|
|
|
@ -22,6 +22,11 @@ config LOG_BACKEND_$(backend)_OUTPUT_DICTIONARY
|
||||||
help
|
help
|
||||||
Backend is in dictionary-based logging output mode.
|
Backend is in dictionary-based logging output mode.
|
||||||
|
|
||||||
|
config LOG_BACKEND_$(backend)_OUTPUT_CUSTOM
|
||||||
|
bool "Extern"
|
||||||
|
help
|
||||||
|
Custom formatting function can be set externally.
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
# The numbering of the format types should be consistent across
|
# The numbering of the format types should be consistent across
|
||||||
|
@ -34,3 +39,4 @@ config LOG_BACKEND_$(backend)_OUTPUT_DEFAULT
|
||||||
default 0 if LOG_BACKEND_$(backend)_OUTPUT_TEXT
|
default 0 if LOG_BACKEND_$(backend)_OUTPUT_TEXT
|
||||||
default 1 if LOG_BACKEND_$(backend)_OUTPUT_SYST
|
default 1 if LOG_BACKEND_$(backend)_OUTPUT_SYST
|
||||||
default 2 if LOG_BACKEND_$(backend)_OUTPUT_DICTIONARY
|
default 2 if LOG_BACKEND_$(backend)_OUTPUT_DICTIONARY
|
||||||
|
default 3 if LOG_BACKEND_$(backend)_OUTPUT_CUSTOM
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <zephyr/logging/log_frontend.h>
|
#include <zephyr/logging/log_frontend.h>
|
||||||
#include <zephyr/syscall_handler.h>
|
#include <zephyr/syscall_handler.h>
|
||||||
#include <zephyr/logging/log_output_dict.h>
|
#include <zephyr/logging/log_output_dict.h>
|
||||||
|
#include <zephyr/logging/log_output_custom.h>
|
||||||
#include <zephyr/linker/utils.h>
|
#include <zephyr/linker/utils.h>
|
||||||
|
|
||||||
LOG_MODULE_REGISTER(log);
|
LOG_MODULE_REGISTER(log);
|
||||||
|
@ -65,7 +66,9 @@ static const log_format_func_t format_table[] = {
|
||||||
[LOG_OUTPUT_SYST] = IS_ENABLED(CONFIG_LOG_MIPI_SYST_ENABLE) ?
|
[LOG_OUTPUT_SYST] = IS_ENABLED(CONFIG_LOG_MIPI_SYST_ENABLE) ?
|
||||||
log_output_msg_syst_process : NULL,
|
log_output_msg_syst_process : NULL,
|
||||||
[LOG_OUTPUT_DICT] = IS_ENABLED(CONFIG_LOG_DICTIONARY_SUPPORT) ?
|
[LOG_OUTPUT_DICT] = IS_ENABLED(CONFIG_LOG_DICTIONARY_SUPPORT) ?
|
||||||
log_dict_output_msg_process : NULL
|
log_dict_output_msg_process : NULL,
|
||||||
|
[LOG_OUTPUT_CUSTOM] = IS_ENABLED(CONFIG_LOG_CUSTOM_FORMAT_SUPPORT) ?
|
||||||
|
log_custom_output_msg_process : NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
log_format_func_t log_format_func_t_get(uint32_t log_type)
|
log_format_func_t log_format_func_t_get(uint32_t log_type)
|
||||||
|
|
22
subsys/logging/log_output_custom.c
Normal file
22
subsys/logging/log_output_custom.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Converge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <zephyr/logging/log_output.h>
|
||||||
|
|
||||||
|
static log_format_func_t log_custom_format_func;
|
||||||
|
|
||||||
|
void log_custom_output_msg_process(const struct log_output *output, struct log_msg *msg,
|
||||||
|
uint32_t flags)
|
||||||
|
{
|
||||||
|
if (log_custom_format_func) {
|
||||||
|
log_custom_format_func(output, msg, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_custom_output_msg_set(log_format_func_t format)
|
||||||
|
{
|
||||||
|
log_custom_format_func = format;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
CONFIG_LOG_CUSTOM_FORMAT_SUPPORT=y
|
|
@ -8,9 +8,11 @@
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
#include "mock_backend.h"
|
#include "mock_backend.h"
|
||||||
#include <zephyr/sys/printk.h>
|
#include <zephyr/sys/printk.h>
|
||||||
|
|
||||||
#include <zephyr/logging/log_ctrl.h>
|
#include <zephyr/logging/log_ctrl.h>
|
||||||
#include <zephyr/logging/log_output.h>
|
#include <zephyr/logging/log_output.h>
|
||||||
#include <zephyr/logging/log_output_dict.h>
|
#include <zephyr/logging/log_output_dict.h>
|
||||||
|
#include <zephyr/logging/log_output_custom.h>
|
||||||
#include <zephyr/ztest.h>
|
#include <zephyr/ztest.h>
|
||||||
|
|
||||||
#define LOG_MODULE_NAME log_switch_format
|
#define LOG_MODULE_NAME log_switch_format
|
||||||
|
@ -24,7 +26,7 @@ void log_msgs(void)
|
||||||
/* standard print */
|
/* standard print */
|
||||||
LOG_ERR("Error message example.");
|
LOG_ERR("Error message example.");
|
||||||
|
|
||||||
#if CONFIG_LOG_MODE_DEFERRED
|
#if CONFIG_LOG_MODE_DEFERRED && !(CONFIG_LOG_CUSTOM_FORMAT_SUPPORT)
|
||||||
/*
|
/*
|
||||||
* When deferred logging is enabled, the work is being performed by
|
* When deferred logging is enabled, the work is being performed by
|
||||||
* another thread. The semaphore my_sem gives that thread time to process
|
* another thread. The semaphore my_sem gives that thread time to process
|
||||||
|
@ -76,7 +78,6 @@ void test_log_switch_format_success_case(void)
|
||||||
|
|
||||||
log_msgs();
|
log_msgs();
|
||||||
validate_log_type(raw_data_str, log_type);
|
validate_log_type(raw_data_str, log_type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_log_switch_format_set(void)
|
void test_log_switch_format_set(void)
|
||||||
|
@ -105,7 +106,6 @@ void test_log_switch_format_set(void)
|
||||||
ret = log_backend_format_set(backend, log_type);
|
ret = log_backend_format_set(backend, log_type);
|
||||||
|
|
||||||
zassert_equal(ret, -EINVAL, "Log type not supported, Invalid value returned");
|
zassert_equal(ret, -EINVAL, "Log type not supported, Invalid value returned");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_log_switch_format_set_all_active_backends(void)
|
void test_log_switch_format_set_all_active_backends(void)
|
||||||
|
@ -127,22 +127,25 @@ void test_log_switch_format_set_all_active_backends(void)
|
||||||
void test_log_switch_format_func_t_get(void)
|
void test_log_switch_format_func_t_get(void)
|
||||||
{
|
{
|
||||||
const log_format_func_t expected_values[] = {
|
const log_format_func_t expected_values[] = {
|
||||||
[LOG_OUTPUT_TEXT] = IS_ENABLED(CONFIG_LOG_OUTPUT) ?
|
[LOG_OUTPUT_TEXT] = IS_ENABLED(CONFIG_LOG_OUTPUT) ? log_output_msg_process : NULL,
|
||||||
log_output_msg_process : NULL,
|
[LOG_OUTPUT_SYST] = IS_ENABLED(CONFIG_LOG_MIPI_SYST_ENABLE)
|
||||||
[LOG_OUTPUT_SYST] = IS_ENABLED(CONFIG_LOG_MIPI_SYST_ENABLE) ?
|
? log_output_msg_syst_process
|
||||||
log_output_msg_syst_process : NULL,
|
: NULL,
|
||||||
[LOG_OUTPUT_DICT] = IS_ENABLED(CONFIG_LOG_DICTIONARY_SUPPORT) ?
|
[LOG_OUTPUT_DICT] = IS_ENABLED(CONFIG_LOG_DICTIONARY_SUPPORT)
|
||||||
log_dict_output_msg_process : NULL
|
? log_dict_output_msg_process
|
||||||
|
: NULL,
|
||||||
|
[LOG_OUTPUT_CUSTOM] = IS_ENABLED(CONFIG_LOG_CUSTOM_FORMAT_SUPPORT)
|
||||||
|
? log_custom_output_msg_process
|
||||||
|
: NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
zassert_equal(log_format_table_size(), ARRAY_SIZE(expected_values),
|
zassert_equal(log_format_table_size(), ARRAY_SIZE(expected_values),
|
||||||
"Update test for expected_values table");
|
"Update test for expected_values table");
|
||||||
|
|
||||||
for (int i = 0; i < ARRAY_SIZE(expected_values); i++) {
|
for (int i = 0; i < ARRAY_SIZE(expected_values); i++) {
|
||||||
zassert_equal(log_format_func_t_get(i), expected_values[i],
|
zassert_equal(log_format_func_t_get(i), expected_values[i],
|
||||||
"Log Format Not supported");
|
"Log Format Not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ZTEST(log_switch_format, test_log_switch_format)
|
ZTEST(log_switch_format, test_log_switch_format)
|
||||||
|
@ -153,4 +156,67 @@ ZTEST(log_switch_format, test_log_switch_format)
|
||||||
test_log_switch_format_func_t_get();
|
test_log_switch_format_func_t_get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_LOG_CUSTOM_FORMAT_SUPPORT
|
||||||
|
void custom_formatting(const struct log_output *output, struct log_msg *msg, uint32_t flags)
|
||||||
|
{
|
||||||
|
uint8_t buffer[] = "Hello world";
|
||||||
|
|
||||||
|
output->func((uint8_t *)buffer, sizeof(buffer), (void *)output);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(log_switch_format, test_log_switch_format_custom_output_handles_null)
|
||||||
|
{
|
||||||
|
const char *backend_name;
|
||||||
|
const struct log_backend *backend;
|
||||||
|
|
||||||
|
backend_name = CONFIG_LOG_BACKEND_DEFAULT;
|
||||||
|
backend = log_backend_get_by_name(backend_name);
|
||||||
|
|
||||||
|
log_backend_format_set(backend, LOG_OUTPUT_CUSTOM);
|
||||||
|
|
||||||
|
log_custom_output_msg_set(NULL);
|
||||||
|
|
||||||
|
log_msgs();
|
||||||
|
|
||||||
|
validate_log_type("", LOG_OUTPUT_CUSTOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(log_switch_format, test_log_switch_format_custom_output_called_when_set)
|
||||||
|
{
|
||||||
|
uint32_t log_type;
|
||||||
|
const char *backend_name;
|
||||||
|
const char *raw_data_str;
|
||||||
|
const char *text_custom_data_str = "Hello world";
|
||||||
|
const struct log_backend *backend;
|
||||||
|
|
||||||
|
backend_name = CONFIG_LOG_BACKEND_DEFAULT;
|
||||||
|
backend = log_backend_get_by_name(backend_name);
|
||||||
|
|
||||||
|
log_backend_format_set(backend, LOG_OUTPUT_CUSTOM);
|
||||||
|
|
||||||
|
log_custom_output_msg_set(custom_formatting);
|
||||||
|
|
||||||
|
log_msgs();
|
||||||
|
|
||||||
|
log_type = LOG_OUTPUT_CUSTOM;
|
||||||
|
raw_data_str = text_custom_data_str;
|
||||||
|
validate_log_type(raw_data_str, log_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(log_switch_format, test_log_switch_format_does_not_log_when_uninit)
|
||||||
|
{
|
||||||
|
const char *backend_name;
|
||||||
|
const struct log_backend *backend;
|
||||||
|
|
||||||
|
backend_name = CONFIG_LOG_BACKEND_DEFAULT;
|
||||||
|
backend = log_backend_get_by_name(backend_name);
|
||||||
|
|
||||||
|
log_backend_format_set(backend, LOG_OUTPUT_CUSTOM);
|
||||||
|
|
||||||
|
log_msgs();
|
||||||
|
|
||||||
|
validate_log_type("", LOG_OUTPUT_CUSTOM);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ZTEST_SUITE(log_switch_format, NULL, NULL, NULL, NULL, NULL);
|
ZTEST_SUITE(log_switch_format, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
|
|
@ -19,3 +19,10 @@ tests:
|
||||||
- qemu_x86
|
- qemu_x86
|
||||||
- sam_e70_xplained
|
- sam_e70_xplained
|
||||||
- qemu_cortex_a53
|
- qemu_cortex_a53
|
||||||
|
logging.log_switch_format.custom_output:
|
||||||
|
extra_args: OVERLAY_CONFIG=overlay_custom_output.conf
|
||||||
|
integration_platforms:
|
||||||
|
- mps2_an385
|
||||||
|
- qemu_x86
|
||||||
|
- sam_e70_xplained
|
||||||
|
- qemu_cortex_a53
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue