logging: log_output: Add optional tid formatting
Add option to prefix log message with thread ID or thread name. Align tests and add test case to the log_output test. Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
70dce83f14
commit
cebd140bee
|
@ -33,6 +33,10 @@ static inline uint32_t log_backend_std_get_flags(void)
|
|||
flags |= LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_LOG_THREAD_ID_PREFIX)) {
|
||||
flags |= LOG_OUTPUT_FLAG_THREAD;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <zephyr/sys/util.h>
|
||||
#include <stdarg.h>
|
||||
#include <zephyr/sys/atomic.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -50,6 +51,9 @@ extern "C" {
|
|||
*/
|
||||
#define LOG_OUTPUT_FLAG_FORMAT_SYSLOG BIT(6)
|
||||
|
||||
/** @brief Flag thread id or name prefix. */
|
||||
#define LOG_OUTPUT_FLAG_THREAD BIT(7)
|
||||
|
||||
/**@} */
|
||||
|
||||
/** @brief Supported backend logging format types for use
|
||||
|
@ -144,6 +148,7 @@ void log_output_msg_process(const struct log_output *log_output,
|
|||
* @param timestamp Timestamp.
|
||||
* @param domain Domain name string. Can be NULL.
|
||||
* @param source Source name string. Can be NULL.
|
||||
* @param tid Thread ID.
|
||||
* @param level Criticality level.
|
||||
* @param package Cbprintf package with a logging message string.
|
||||
* @param data Data passed to hexdump API. Can bu NULL.
|
||||
|
@ -154,6 +159,7 @@ void log_output_process(const struct log_output *log_output,
|
|||
log_timestamp_t timestamp,
|
||||
const char *domain,
|
||||
const char *source,
|
||||
const k_tid_t tid,
|
||||
uint8_t level,
|
||||
const uint8_t *package,
|
||||
const uint8_t *data,
|
||||
|
|
|
@ -325,8 +325,10 @@ static void color_postfix(const struct log_output *output,
|
|||
static int ids_print(const struct log_output *output,
|
||||
bool level_on,
|
||||
bool func_on,
|
||||
bool thread_on,
|
||||
const char *domain,
|
||||
const char *source,
|
||||
const k_tid_t tid,
|
||||
uint32_t level)
|
||||
{
|
||||
int total = 0;
|
||||
|
@ -335,6 +337,15 @@ static int ids_print(const struct log_output *output,
|
|||
total += print_formatted(output, "<%s> ", severity[level]);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_LOG_THREAD_ID_PREFIX) && thread_on) {
|
||||
if (IS_ENABLED(CONFIG_THREAD_NAME)) {
|
||||
total += print_formatted(output, "[%s] ",
|
||||
tid == NULL ? "irq" : k_thread_name_get(tid));
|
||||
} else {
|
||||
total += print_formatted(output, "[%p] ", tid);
|
||||
}
|
||||
}
|
||||
|
||||
if (domain) {
|
||||
total += print_formatted(output, "%s/", domain);
|
||||
}
|
||||
|
@ -430,6 +441,7 @@ static uint32_t prefix_print(const struct log_output *output,
|
|||
log_timestamp_t timestamp,
|
||||
const char *domain,
|
||||
const char *source,
|
||||
const k_tid_t tid,
|
||||
uint8_t level)
|
||||
{
|
||||
__ASSERT_NO_MSG(level <= LOG_LEVEL_DBG);
|
||||
|
@ -438,6 +450,8 @@ static uint32_t prefix_print(const struct log_output *output,
|
|||
bool stamp = flags & LOG_OUTPUT_FLAG_TIMESTAMP;
|
||||
bool colors_on = flags & LOG_OUTPUT_FLAG_COLORS;
|
||||
bool level_on = flags & LOG_OUTPUT_FLAG_LEVEL;
|
||||
bool thread_on = IS_ENABLED(CONFIG_LOG_THREAD_ID_PREFIX) &&
|
||||
(flags & LOG_OUTPUT_FLAG_THREAD);
|
||||
const char *tag = IS_ENABLED(CONFIG_LOG) ? z_log_get_tag() : NULL;
|
||||
|
||||
if (IS_ENABLED(CONFIG_LOG_BACKEND_NET) &&
|
||||
|
@ -475,7 +489,7 @@ static uint32_t prefix_print(const struct log_output *output,
|
|||
color_prefix(output, colors_on, level);
|
||||
}
|
||||
|
||||
length += ids_print(output, level_on, func_on, domain, source, level);
|
||||
length += ids_print(output, level_on, func_on, thread_on, domain, source, tid, level);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
@ -492,6 +506,7 @@ void log_output_process(const struct log_output *output,
|
|||
log_timestamp_t timestamp,
|
||||
const char *domain,
|
||||
const char *source,
|
||||
const k_tid_t tid,
|
||||
uint8_t level,
|
||||
const uint8_t *package,
|
||||
const uint8_t *data,
|
||||
|
@ -503,7 +518,8 @@ void log_output_process(const struct log_output *output,
|
|||
cbprintf_cb cb;
|
||||
|
||||
if (!raw_string) {
|
||||
prefix_offset = prefix_print(output, flags, 0, timestamp, domain, source, level);
|
||||
prefix_offset = prefix_print(output, flags, 0, timestamp,
|
||||
domain, source, tid, level);
|
||||
cb = out_func;
|
||||
} else {
|
||||
prefix_offset = 0;
|
||||
|
@ -560,7 +576,7 @@ void log_output_msg_process(const struct log_output *output,
|
|||
uint8_t *package = log_msg_get_package(msg, &plen);
|
||||
uint8_t *data = log_msg_get_data(msg, &dlen);
|
||||
|
||||
log_output_process(output, timestamp, NULL, sname, level,
|
||||
log_output_process(output, timestamp, NULL, sname, (k_tid_t)log_msg_get_tid(msg), level,
|
||||
plen > 0 ? package : NULL, data, dlen, flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ ZTEST(test_log_output, test_no_flags)
|
|||
err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
|
||||
zassert_true(err > 0);
|
||||
|
||||
log_output_process(&log_output, 0, NULL, SNAME, LOG_LEVEL_INF, package, NULL, 0, 0);
|
||||
log_output_process(&log_output, 0, NULL, SNAME, NULL, LOG_LEVEL_INF, package, NULL, 0, 0);
|
||||
|
||||
mock_buffer[mock_len] = '\0';
|
||||
zassert_equal(strcmp(exp_str, mock_buffer), 0);
|
||||
|
@ -69,7 +69,7 @@ ZTEST(test_log_output, test_raw)
|
|||
err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
|
||||
zassert_true(err > 0);
|
||||
|
||||
log_output_process(&log_output, 0, NULL, SNAME, LOG_LEVEL_INTERNAL_RAW_STRING,
|
||||
log_output_process(&log_output, 0, NULL, SNAME, NULL, LOG_LEVEL_INTERNAL_RAW_STRING,
|
||||
package, NULL, 0, 0);
|
||||
|
||||
mock_buffer[mock_len] = '\0';
|
||||
|
@ -85,7 +85,7 @@ ZTEST(test_log_output, test_no_flags_dname)
|
|||
err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
|
||||
zassert_true(err > 0);
|
||||
|
||||
log_output_process(&log_output, 0, DNAME, SNAME, LOG_LEVEL_INF, package, NULL, 0, 0);
|
||||
log_output_process(&log_output, 0, DNAME, SNAME, NULL, LOG_LEVEL_INF, package, NULL, 0, 0);
|
||||
|
||||
mock_buffer[mock_len] = '\0';
|
||||
zassert_equal(strcmp(exp_str, mock_buffer), 0);
|
||||
|
@ -101,7 +101,7 @@ ZTEST(test_log_output, test_level_flag)
|
|||
err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
|
||||
zassert_true(err > 0);
|
||||
|
||||
log_output_process(&log_output, 0, DNAME, SNAME, LOG_LEVEL_INF,
|
||||
log_output_process(&log_output, 0, DNAME, SNAME, NULL, LOG_LEVEL_INF,
|
||||
package, NULL, 0, flags);
|
||||
|
||||
mock_buffer[mock_len] = '\0';
|
||||
|
@ -120,7 +120,7 @@ ZTEST(test_log_output, test_ts_flag)
|
|||
err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
|
||||
zassert_true(err > 0);
|
||||
|
||||
log_output_process(&log_output, 0, DNAME, SNAME, LOG_LEVEL_INF,
|
||||
log_output_process(&log_output, 0, DNAME, SNAME, NULL, LOG_LEVEL_INF,
|
||||
package, NULL, 0, flags);
|
||||
|
||||
mock_buffer[mock_len] = '\0';
|
||||
|
@ -140,7 +140,7 @@ ZTEST(test_log_output, test_format_ts)
|
|||
err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
|
||||
zassert_true(err > 0);
|
||||
|
||||
log_output_process(&log_output, 1000000, DNAME, SNAME, LOG_LEVEL_INF,
|
||||
log_output_process(&log_output, 1000000, DNAME, SNAME, NULL, LOG_LEVEL_INF,
|
||||
package, NULL, 0, flags);
|
||||
|
||||
mock_buffer[mock_len] = '\0';
|
||||
|
@ -178,7 +178,7 @@ ZTEST(test_log_output, test_levels)
|
|||
for (int i = 0; i < ARRAY_SIZE(exp_strs); i++) {
|
||||
reset_mock_buffer();
|
||||
|
||||
log_output_process(&log_output, 0, NULL, SNAME, levels[i],
|
||||
log_output_process(&log_output, 0, NULL, SNAME, NULL, levels[i],
|
||||
package, NULL, 0, flags);
|
||||
|
||||
mock_buffer[mock_len] = '\0';
|
||||
|
@ -210,7 +210,7 @@ ZTEST(test_log_output, test_colors)
|
|||
for (int i = 0; i < ARRAY_SIZE(exp_strs); i++) {
|
||||
reset_mock_buffer();
|
||||
|
||||
log_output_process(&log_output, 0, NULL, SNAME, levels[i],
|
||||
log_output_process(&log_output, 0, NULL, SNAME, NULL, levels[i],
|
||||
package, NULL, 0, flags);
|
||||
|
||||
mock_buffer[mock_len] = '\0';
|
||||
|
@ -218,6 +218,35 @@ ZTEST(test_log_output, test_colors)
|
|||
}
|
||||
}
|
||||
|
||||
ZTEST(test_log_output, test_thread_id)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_LOG_THREAD_ID_PREFIX)) {
|
||||
return;
|
||||
}
|
||||
|
||||
char exp_str[256];
|
||||
char package[256];
|
||||
|
||||
if (IS_ENABLED(CONFIG_THREAD_NAME)) {
|
||||
sprintf(exp_str, "<err> [%s] src: Test\r\n", k_thread_name_get(k_current_get()));
|
||||
} else {
|
||||
sprintf(exp_str, "<err> [%p] src: Test\r\n", k_current_get());
|
||||
}
|
||||
|
||||
uint32_t flags = LOG_OUTPUT_FLAG_LEVEL | LOG_OUTPUT_FLAG_THREAD;
|
||||
int err;
|
||||
|
||||
err = cbprintf_package(package, sizeof(package), 0, "Test");
|
||||
zassert_true(err > 0);
|
||||
|
||||
log_output_process(&log_output, 0, NULL, SNAME, k_current_get(), 1,
|
||||
package, NULL, 0, flags);
|
||||
|
||||
mock_buffer[mock_len] = '\0';
|
||||
printk("%s", mock_buffer);
|
||||
zassert_equal(strcmp(exp_str, mock_buffer), 0);
|
||||
}
|
||||
|
||||
static void before(void *notused)
|
||||
{
|
||||
reset_mock_buffer();
|
||||
|
|
|
@ -15,3 +15,9 @@ tests:
|
|||
- logging
|
||||
extra_configs:
|
||||
- CONFIG_LOG_TIMESTAMP_64BIT=y
|
||||
logging.log_output.thread_id:
|
||||
tags:
|
||||
- log_output
|
||||
- logging
|
||||
extra_configs:
|
||||
- CONFIG_LOG_THREAD_ID_PREFIX=y
|
||||
|
|
|
@ -71,7 +71,7 @@ ZTEST(test_timestamp, test_custom_timestamp)
|
|||
err = cbprintf_package(package, sizeof(package), 0, TEST_STR);
|
||||
zassert_true(err > 0);
|
||||
|
||||
log_output_process(&log_output, 1, DNAME, SNAME, LOG_LEVEL_INF,
|
||||
log_output_process(&log_output, 1, DNAME, SNAME, NULL, LOG_LEVEL_INF,
|
||||
package, NULL, 0, flags);
|
||||
|
||||
mock_buffer[mock_len] = '\0';
|
||||
|
|
Loading…
Reference in a new issue