logging: Extend log_output to support raw data
Added functions for processing log string and hexdump. Details are passed as function parameters and not as log_msg. Those functions can be used when logger works in synchronous mode and log messages are not created. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
1d9e5ee108
commit
08e5103105
2 changed files with 217 additions and 118 deletions
|
@ -98,6 +98,42 @@ void log_output_msg_process(const struct log_output *log_output,
|
||||||
struct log_msg *msg,
|
struct log_msg *msg,
|
||||||
u32_t flags);
|
u32_t flags);
|
||||||
|
|
||||||
|
/** @brief Process log string
|
||||||
|
*
|
||||||
|
* Function is formatting provided string adding optional prefixes and
|
||||||
|
* postfixes.
|
||||||
|
*
|
||||||
|
* @param log_output Pointer to log_output instance.
|
||||||
|
* @param src_level Log source and level structure.
|
||||||
|
* @param timestamp Timestamp.
|
||||||
|
* @param fmt String.
|
||||||
|
* @param ap String arguments.
|
||||||
|
* @param flags Optional flags.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void log_output_string(const struct log_output *log_output,
|
||||||
|
struct log_msg_ids src_level, u32_t timestamp,
|
||||||
|
const char *fmt, va_list ap, u32_t flags);
|
||||||
|
|
||||||
|
/** @brief Process log hexdump
|
||||||
|
*
|
||||||
|
* Function is formatting provided hexdump adding optional prefixes and
|
||||||
|
* postfixes.
|
||||||
|
*
|
||||||
|
* @param log_output Pointer to log_output instance.
|
||||||
|
* @param src_level Log source and level structure.
|
||||||
|
* @param timestamp Timestamp.
|
||||||
|
* @param metadata String.
|
||||||
|
* @param data Data.
|
||||||
|
* @param length Data length.
|
||||||
|
* @param flags Optional flags.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void log_output_hexdump(const struct log_output *log_output,
|
||||||
|
struct log_msg_ids src_level, u32_t timestamp,
|
||||||
|
const char *metadata, const u8_t *data,
|
||||||
|
u32_t length, u32_t flags);
|
||||||
|
|
||||||
/** @brief Process dropped messages indication.
|
/** @brief Process dropped messages indication.
|
||||||
*
|
*
|
||||||
* Function prints error message indicating lost log messages.
|
* Function prints error message indicating lost log messages.
|
||||||
|
|
|
@ -145,12 +145,10 @@ void log_output_flush(const struct log_output *log_output)
|
||||||
log_output->control_block->offset = 0;
|
log_output->control_block->offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int timestamp_print(struct log_msg *msg,
|
static int timestamp_print(const struct log_output *log_output,
|
||||||
const struct log_output *log_output,
|
u32_t flags, u32_t timestamp)
|
||||||
u32_t flags)
|
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
u32_t timestamp = log_msg_timestamp_get(msg);
|
|
||||||
bool format =
|
bool format =
|
||||||
(flags & LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP) |
|
(flags & LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP) |
|
||||||
(flags & LOG_OUTPUT_FLAG_FORMAT_SYSLOG);
|
(flags & LOG_OUTPUT_FLAG_FORMAT_SYSLOG);
|
||||||
|
@ -208,44 +206,32 @@ static int timestamp_print(struct log_msg *msg,
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void color_print(struct log_msg *msg,
|
static void color_print(const struct log_output *log_output,
|
||||||
const struct log_output *log_output,
|
bool color, bool start, u32_t level)
|
||||||
bool color,
|
|
||||||
bool start)
|
|
||||||
{
|
{
|
||||||
if (color) {
|
if (color) {
|
||||||
u32_t level = log_msg_level_get(msg);
|
const char *color = start && (colors[level] != NULL) ?
|
||||||
|
colors[level] : LOG_COLOR_CODE_DEFAULT;
|
||||||
if (colors[level] != NULL) {
|
print_formatted(log_output, "%s", color);
|
||||||
const char *color = start ?
|
|
||||||
colors[level] : LOG_COLOR_CODE_DEFAULT;
|
|
||||||
|
|
||||||
print_formatted(log_output, "%s", color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void color_prefix(struct log_msg *msg,
|
static void color_prefix(const struct log_output *log_output,
|
||||||
const struct log_output *log_output,
|
bool color, u32_t level)
|
||||||
bool color)
|
|
||||||
{
|
{
|
||||||
color_print(msg, log_output, color, true);
|
color_print(log_output, color, true, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void color_postfix(struct log_msg *msg,
|
static void color_postfix(const struct log_output *log_output,
|
||||||
const struct log_output *log_output,
|
bool color, u32_t level)
|
||||||
bool color)
|
|
||||||
{
|
{
|
||||||
color_print(msg, log_output, color, false);
|
color_print(log_output, color, false, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int ids_print(struct log_msg *msg, const struct log_output *log_output,
|
static int ids_print(const struct log_output *log_output, bool level_on,
|
||||||
bool level_on, bool func_on)
|
bool func_on, u32_t domain_id, u32_t source_id, u32_t level)
|
||||||
{
|
{
|
||||||
u32_t domain_id = log_msg_domain_id_get(msg);
|
|
||||||
u32_t source_id = log_msg_source_id_get(msg);
|
|
||||||
u32_t level = log_msg_level_get(msg);
|
|
||||||
int total = 0;
|
int total = 0;
|
||||||
|
|
||||||
if (level_on) {
|
if (level_on) {
|
||||||
|
@ -368,46 +354,36 @@ static void std_print(struct log_msg *msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32_t hexdump_line_print(struct log_msg *msg,
|
static void hexdump_line_print(const struct log_output *log_output,
|
||||||
const struct log_output *log_output,
|
const u8_t *data, u32_t length,
|
||||||
int prefix_offset,
|
int prefix_offset, u32_t flags)
|
||||||
u32_t offset, u32_t flags)
|
|
||||||
{
|
{
|
||||||
u8_t buf[HEXDUMP_BYTES_IN_LINE];
|
newline_print(log_output, flags);
|
||||||
size_t length = sizeof(buf);
|
|
||||||
|
|
||||||
log_msg_hexdump_data_get(msg, buf, &length, offset);
|
for (int i = 0; i < prefix_offset; i++) {
|
||||||
|
print_formatted(log_output, " ");
|
||||||
|
}
|
||||||
|
|
||||||
if (length > 0) {
|
for (int i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) {
|
||||||
newline_print(log_output, flags);
|
if (i < length) {
|
||||||
|
print_formatted(log_output, "%02x ", data[i]);
|
||||||
for (int i = 0; i < prefix_offset; i++) {
|
} else {
|
||||||
print_formatted(log_output, " ");
|
print_formatted(log_output, " ");
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) {
|
|
||||||
if (i < length) {
|
|
||||||
print_formatted(log_output, "%02x ", buf[i]);
|
|
||||||
} else {
|
|
||||||
print_formatted(log_output, " ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print_formatted(log_output, "|");
|
|
||||||
|
|
||||||
for (int i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) {
|
|
||||||
if (i < length) {
|
|
||||||
char c = (char)buf[i];
|
|
||||||
|
|
||||||
print_formatted(log_output, "%c",
|
|
||||||
isprint((int)c) ? c : '.');
|
|
||||||
} else {
|
|
||||||
print_formatted(log_output, " ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return length;
|
print_formatted(log_output, "|");
|
||||||
|
|
||||||
|
for (int i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) {
|
||||||
|
if (i < length) {
|
||||||
|
char c = (char)data[i];
|
||||||
|
|
||||||
|
print_formatted(log_output, "%c",
|
||||||
|
isprint((int)c) ? c : '.');
|
||||||
|
} else {
|
||||||
|
print_formatted(log_output, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hexdump_print(struct log_msg *msg,
|
static void hexdump_print(struct log_msg *msg,
|
||||||
|
@ -415,19 +391,22 @@ static void hexdump_print(struct log_msg *msg,
|
||||||
int prefix_offset, u32_t flags)
|
int prefix_offset, u32_t flags)
|
||||||
{
|
{
|
||||||
u32_t offset = 0U;
|
u32_t offset = 0U;
|
||||||
u32_t length;
|
u8_t buf[HEXDUMP_BYTES_IN_LINE];
|
||||||
|
size_t length;
|
||||||
|
|
||||||
print_formatted(log_output, "%s", log_msg_str_get(msg));
|
print_formatted(log_output, "%s", log_msg_str_get(msg));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
length = hexdump_line_print(msg, log_output, prefix_offset,
|
length = sizeof(buf);
|
||||||
offset, flags);
|
log_msg_hexdump_data_get(msg, buf, &length, offset);
|
||||||
|
|
||||||
if (length < HEXDUMP_BYTES_IN_LINE) {
|
if (length) {
|
||||||
|
hexdump_line_print(log_output, buf, length,
|
||||||
|
prefix_offset, flags);
|
||||||
|
offset += length;
|
||||||
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += length;
|
|
||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,86 +438,170 @@ static void raw_string_print(struct log_msg *msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int prefix_print(struct log_msg *msg,
|
static u32_t prefix_print(const struct log_output *log_output,
|
||||||
const struct log_output *log_output,
|
u32_t flags, bool func_on, u32_t timestamp, u8_t level,
|
||||||
u32_t flags, bool func_on)
|
u8_t domain_id, u16_t source_id)
|
||||||
{
|
{
|
||||||
int length = 0;
|
u32_t length = 0;
|
||||||
|
|
||||||
if (log_msg_level_get(msg) != LOG_LEVEL_INTERNAL_RAW_STRING) {
|
bool stamp = flags & LOG_OUTPUT_FLAG_TIMESTAMP;
|
||||||
bool stamp = flags & LOG_OUTPUT_FLAG_TIMESTAMP;
|
bool colors_on = flags & LOG_OUTPUT_FLAG_COLORS;
|
||||||
bool colors_on = flags & LOG_OUTPUT_FLAG_COLORS;
|
bool level_on = flags & LOG_OUTPUT_FLAG_LEVEL;
|
||||||
bool level_on = flags & LOG_OUTPUT_FLAG_LEVEL;
|
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_LOG_BACKEND_NET) &&
|
if (IS_ENABLED(CONFIG_LOG_BACKEND_NET) &&
|
||||||
flags & LOG_OUTPUT_FLAG_FORMAT_SYSLOG) {
|
flags & LOG_OUTPUT_FLAG_FORMAT_SYSLOG) {
|
||||||
/* TODO: As there is no way to figure out the
|
/* TODO: As there is no way to figure out the
|
||||||
* facility at this point, use a pre-defined value.
|
* facility at this point, use a pre-defined value.
|
||||||
* Change this to use the real facility of the
|
* Change this to use the real facility of the
|
||||||
* logging call when that info is available.
|
* logging call when that info is available.
|
||||||
*/
|
*/
|
||||||
static const int facility = 16; /* local0 */
|
static const int facility = 16; /* local0 */
|
||||||
|
|
||||||
length += print_formatted(
|
length += print_formatted(
|
||||||
log_output,
|
log_output,
|
||||||
"<%d>1 ",
|
"<%d>1 ",
|
||||||
facility * 8 +
|
facility * 8 +
|
||||||
level_to_rfc5424_severity(
|
level_to_rfc5424_severity(level));
|
||||||
log_msg_level_get(msg)));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (stamp) {
|
if (stamp) {
|
||||||
length += timestamp_print(msg, log_output, flags);
|
length += timestamp_print(log_output, flags, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_LOG_BACKEND_NET) &&
|
if (IS_ENABLED(CONFIG_LOG_BACKEND_NET) &&
|
||||||
flags & LOG_OUTPUT_FLAG_FORMAT_SYSLOG) {
|
flags & LOG_OUTPUT_FLAG_FORMAT_SYSLOG) {
|
||||||
length += print_formatted(
|
length += print_formatted(
|
||||||
log_output, "%s - - - - ",
|
log_output, "%s - - - - ",
|
||||||
log_output->control_block->hostname ?
|
log_output->control_block->hostname ?
|
||||||
log_output->control_block->hostname :
|
log_output->control_block->hostname :
|
||||||
"zephyr");
|
"zephyr");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
color_prefix(msg, log_output, colors_on);
|
color_prefix(log_output, colors_on, level);
|
||||||
length += ids_print(msg, log_output, level_on, func_on);
|
length += ids_print(log_output, level_on, func_on,
|
||||||
}
|
domain_id, source_id, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void postfix_print(struct log_msg *msg,
|
static void postfix_print(const struct log_output *log_output,
|
||||||
const struct log_output *log_output,
|
u32_t flags, u8_t level)
|
||||||
u32_t flags)
|
|
||||||
{
|
{
|
||||||
if (log_msg_level_get(msg) != LOG_LEVEL_INTERNAL_RAW_STRING) {
|
color_postfix(log_output, (flags & LOG_OUTPUT_FLAG_COLORS),
|
||||||
color_postfix(msg, log_output,
|
level);
|
||||||
(flags & LOG_OUTPUT_FLAG_COLORS));
|
newline_print(log_output, flags);
|
||||||
newline_print(log_output, flags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_output_msg_process(const struct log_output *log_output,
|
void log_output_msg_process(const struct log_output *log_output,
|
||||||
struct log_msg *msg,
|
struct log_msg *msg,
|
||||||
u32_t flags)
|
u32_t flags)
|
||||||
{
|
{
|
||||||
int prefix_offset = prefix_print(msg, log_output, flags,
|
bool std_msg = log_msg_is_std(msg);
|
||||||
log_msg_is_std(msg));
|
u32_t timestamp = log_msg_timestamp_get(msg);
|
||||||
|
u8_t level = (u8_t)log_msg_level_get(msg);
|
||||||
|
u8_t domain_id = (u8_t)log_msg_domain_id_get(msg);
|
||||||
|
u16_t source_id = (u16_t)log_msg_source_id_get(msg);
|
||||||
|
bool raw_string = (level == LOG_LEVEL_INTERNAL_RAW_STRING);
|
||||||
|
int prefix_offset;
|
||||||
|
|
||||||
|
prefix_offset = raw_string ?
|
||||||
|
0 : prefix_print(log_output, flags, std_msg, timestamp,
|
||||||
|
level, domain_id, source_id);
|
||||||
|
|
||||||
if (log_msg_is_std(msg)) {
|
if (log_msg_is_std(msg)) {
|
||||||
std_print(msg, log_output);
|
std_print(msg, log_output);
|
||||||
} else if (log_msg_level_get(msg) != LOG_LEVEL_INTERNAL_RAW_STRING) {
|
} else if (raw_string) {
|
||||||
raw_string_print(msg, log_output);
|
raw_string_print(msg, log_output);
|
||||||
} else {
|
} else {
|
||||||
hexdump_print(msg, log_output, prefix_offset, flags);
|
hexdump_print(msg, log_output, prefix_offset, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
postfix_print(msg, log_output, flags);
|
if (!raw_string) {
|
||||||
|
postfix_print(log_output, flags, level);
|
||||||
|
}
|
||||||
|
|
||||||
log_output_flush(log_output);
|
log_output_flush(log_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ends_with_newline(const char *fmt)
|
||||||
|
{
|
||||||
|
char c = '\0';
|
||||||
|
|
||||||
|
while (*fmt != '\0') {
|
||||||
|
c = *fmt;
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (c == '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_output_string(const struct log_output *log_output,
|
||||||
|
struct log_msg_ids src_level, u32_t timestamp,
|
||||||
|
const char *fmt, va_list ap, u32_t flags)
|
||||||
|
{
|
||||||
|
int length;
|
||||||
|
u8_t level = (u8_t)src_level.level;
|
||||||
|
u8_t domain_id = (u8_t)src_level.domain_id;
|
||||||
|
u16_t source_id = (u16_t)src_level.source_id;
|
||||||
|
bool raw_string = (level == LOG_LEVEL_INTERNAL_RAW_STRING);
|
||||||
|
|
||||||
|
if (!raw_string) {
|
||||||
|
prefix_print(log_output, flags, true, timestamp,
|
||||||
|
level, domain_id, source_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(CONFIG_NEWLIB_LIBC) && !defined(CONFIG_ARCH_POSIX)
|
||||||
|
length = _prf(out_func, (void *)log_output, (char *)fmt, ap);
|
||||||
|
#else
|
||||||
|
_vprintk(out_func, (void *)log_output, fmt, ap);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
(void)length;
|
||||||
|
|
||||||
|
if (raw_string) {
|
||||||
|
/* add \r if string ends with newline. */
|
||||||
|
if (ends_with_newline(fmt)) {
|
||||||
|
print_formatted(log_output, "\r");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
postfix_print(log_output, flags, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
log_output_flush(log_output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_output_hexdump(const struct log_output *log_output,
|
||||||
|
struct log_msg_ids src_level, u32_t timestamp,
|
||||||
|
const char *metadata, const u8_t *data,
|
||||||
|
u32_t length, u32_t flags)
|
||||||
|
{
|
||||||
|
u32_t prefix_offset;
|
||||||
|
u8_t level = (u8_t)src_level.level;
|
||||||
|
u8_t domain_id = (u8_t)src_level.domain_id;
|
||||||
|
u16_t source_id = (u16_t)src_level.source_id;
|
||||||
|
|
||||||
|
prefix_offset = prefix_print(log_output, flags, true, timestamp,
|
||||||
|
level, domain_id, source_id);
|
||||||
|
|
||||||
|
/* Print metadata */
|
||||||
|
print_formatted(log_output, "%s", metadata);
|
||||||
|
|
||||||
|
while (length) {
|
||||||
|
u32_t part_len = length > HEXDUMP_BYTES_IN_LINE ?
|
||||||
|
HEXDUMP_BYTES_IN_LINE : length;
|
||||||
|
|
||||||
|
hexdump_line_print(log_output, data, part_len,
|
||||||
|
prefix_offset, flags);
|
||||||
|
|
||||||
|
data += part_len;
|
||||||
|
length -= part_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
postfix_print(log_output, flags, level);
|
||||||
|
log_output_flush(log_output);
|
||||||
|
}
|
||||||
|
|
||||||
void log_output_dropped_process(const struct log_output *log_output, u32_t cnt)
|
void log_output_dropped_process(const struct log_output *log_output, u32_t cnt)
|
||||||
{
|
{
|
||||||
char buf[5];
|
char buf[5];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue