LCOV - code coverage report
Current view: top level - home/runner/zephyrproject/zephyr/subsys/logging - log_output.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 44 184 23.9 %
Date: 2024-11-24 18:13:42 Functions: 5 18 27.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 11 74 14.9 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2018 Nordic Semiconductor ASA
       3                 :            :  *
       4                 :            :  * SPDX-License-Identifier: Apache-2.0
       5                 :            :  */
       6                 :            : 
       7                 :            : #undef _POSIX_C_SOURCE
       8                 :            : #define _POSIX_C_SOURCE 200809L
       9                 :            : #include <zephyr/logging/log_output.h>
      10                 :            : #include <zephyr/logging/log_ctrl.h>
      11                 :            : #include <zephyr/logging/log_output_custom.h>
      12                 :            : #include <zephyr/logging/log.h>
      13                 :            : #include <zephyr/sys/__assert.h>
      14                 :            : #include <zephyr/sys/cbprintf.h>
      15                 :            : #include <ctype.h>
      16                 :            : #include <time.h>
      17                 :            : #include <stdio.h>
      18                 :            : #include <stdbool.h>
      19                 :            : 
      20                 :            : #define LOG_COLOR_CODE_DEFAULT "\x1B[0m"
      21                 :            : #define LOG_COLOR_CODE_RED     "\x1B[1;31m"
      22                 :            : #define LOG_COLOR_CODE_GREEN   "\x1B[1;32m"
      23                 :            : #define LOG_COLOR_CODE_YELLOW  "\x1B[1;33m"
      24                 :            : #define LOG_COLOR_CODE_BLUE    "\x1B[1;34m"
      25                 :            : 
      26                 :            : #define HEXDUMP_BYTES_IN_LINE 16
      27                 :            : 
      28                 :            : #define  DROPPED_COLOR_PREFIX \
      29                 :            :         COND_CODE_1(CONFIG_LOG_BACKEND_SHOW_COLOR, (LOG_COLOR_CODE_RED), ())
      30                 :            : 
      31                 :            : #define DROPPED_COLOR_POSTFIX \
      32                 :            :         COND_CODE_1(CONFIG_LOG_BACKEND_SHOW_COLOR, (LOG_COLOR_CODE_DEFAULT), ())
      33                 :            : 
      34                 :            : static const char *const severity[] = {
      35                 :            :         NULL,
      36                 :            :         "err",
      37                 :            :         "wrn",
      38                 :            :         "inf",
      39                 :            :         "dbg"
      40                 :            : };
      41                 :            : 
      42                 :            : static const char *const colors[] = {
      43                 :            :         NULL,
      44                 :            :         IS_ENABLED(CONFIG_LOG_BACKEND_SHOW_COLOR) ? LOG_COLOR_CODE_RED : NULL,    /* err */
      45                 :            :         IS_ENABLED(CONFIG_LOG_BACKEND_SHOW_COLOR) ? LOG_COLOR_CODE_YELLOW : NULL, /* warn */
      46                 :            :         IS_ENABLED(CONFIG_LOG_INFO_COLOR_GREEN) ? LOG_COLOR_CODE_GREEN : NULL,   /* info */
      47                 :            :         IS_ENABLED(CONFIG_LOG_DBG_COLOR_BLUE) ? LOG_COLOR_CODE_BLUE : NULL,   /* dbg */
      48                 :            : };
      49                 :            : 
      50                 :            : static uint32_t freq;
      51                 :            : static log_timestamp_t timestamp_div;
      52                 :            : 
      53                 :            : #define SECONDS_IN_DAY                  86400U
      54                 :            : 
      55                 :            : static uint32_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 31,
      56                 :            :                                                                         31, 30, 31, 30, 31};
      57                 :            : 
      58                 :            : struct YMD_date {
      59                 :            :         uint32_t year;
      60                 :            :         uint32_t month;
      61                 :            :         uint32_t day;
      62                 :            : };
      63                 :            : 
      64                 :            : /* The RFC 5424 allows very flexible mapping and suggest the value 0 being the
      65                 :            :  * highest severity and 7 to be the lowest (debugging level) severity.
      66                 :            :  *
      67                 :            :  *    0   Emergency      System is unusable
      68                 :            :  *    1   Alert          Action must be taken immediately
      69                 :            :  *    2   Critical       Critical conditions
      70                 :            :  *    3   Error          Error conditions
      71                 :            :  *    4   Warning        Warning conditions
      72                 :            :  *    5   Notice         Normal but significant condition
      73                 :            :  *    6   Informational  Informational messages
      74                 :            :  *    7   Debug          Debug-level messages
      75                 :            :  */
      76                 :            : static int level_to_rfc5424_severity(uint32_t level)
      77                 :            : {
      78                 :            :         uint8_t ret;
      79                 :            : 
      80                 :            :         switch (level) {
      81                 :            :         case LOG_LEVEL_NONE:
      82                 :            :                 ret = 7U;
      83                 :            :                 break;
      84                 :            :         case LOG_LEVEL_ERR:
      85                 :            :                 ret =  3U;
      86                 :            :                 break;
      87                 :            :         case LOG_LEVEL_WRN:
      88                 :            :                 ret =  4U;
      89                 :            :                 break;
      90                 :            :         case LOG_LEVEL_INF:
      91                 :            :                 ret =  6U;
      92                 :            :                 break;
      93                 :            :         case LOG_LEVEL_DBG:
      94                 :            :                 ret = 7U;
      95                 :            :                 break;
      96                 :            :         default:
      97                 :            :                 ret = 7U;
      98                 :            :                 break;
      99                 :            :         }
     100                 :            : 
     101                 :            :         return ret;
     102                 :            : }
     103                 :            : 
     104                 :       8820 : static int out_func(int c, void *ctx)
     105                 :            : {
     106                 :       8820 :         const struct log_output *out_ctx = (const struct log_output *)ctx;
     107                 :       8820 :         int idx;
     108                 :            : 
     109                 :       8820 :         if (IS_ENABLED(CONFIG_LOG_MODE_IMMEDIATE)) {
     110                 :            :                 /* Backend must be thread safe in synchronous operation. */
     111                 :            :                 /* Need that step for big endian */
     112                 :       8820 :                 char x = (char)c;
     113                 :            : 
     114                 :       8820 :                 out_ctx->func((uint8_t *)&x, 1, out_ctx->control_block->ctx);
     115                 :       8820 :                 return 0;
     116                 :            :         }
     117                 :            : 
     118                 :            :         if (out_ctx->control_block->offset == out_ctx->size) {
     119                 :            :                 log_output_flush(out_ctx);
     120                 :            :         }
     121                 :            : 
     122                 :            :         idx = atomic_inc(&out_ctx->control_block->offset);
     123                 :            :         out_ctx->buf[idx] = (uint8_t)c;
     124                 :            : 
     125                 :            :         __ASSERT_NO_MSG(out_ctx->control_block->offset <= out_ctx->size);
     126                 :            : 
     127                 :            :         return 0;
     128                 :            : }
     129                 :            : 
     130                 :       8640 : static int cr_out_func(int c, void *ctx)
     131                 :            : {
     132         [ +  + ]:       8640 :         if (c == '\n') {
     133                 :        180 :                 out_func((int)'\r', ctx);
     134                 :            :         }
     135                 :       8640 :         out_func(c, ctx);
     136                 :            : 
     137                 :       8640 :         return 0;
     138                 :            : }
     139                 :            : 
     140                 :          0 : static int print_formatted(const struct log_output *output,
     141                 :            :                            const char *fmt, ...)
     142                 :            : {
     143                 :          0 :         va_list args;
     144                 :          0 :         int length = 0;
     145                 :            : 
     146                 :          0 :         va_start(args, fmt);
     147                 :          0 :         length = cbvprintf(out_func, (void *)output, fmt, args);
     148                 :          0 :         va_end(args);
     149                 :            : 
     150                 :          0 :         return length;
     151                 :            : }
     152                 :            : 
     153                 :            : static inline bool is_leap_year(uint32_t year)
     154                 :            : {
     155                 :            :         return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
     156                 :            : }
     157                 :            : 
     158                 :            : static void __attribute__((unused)) get_YMD_from_seconds(uint64_t seconds,
     159                 :            :                         struct YMD_date *output_date)
     160                 :            : {
     161                 :            :         uint64_t tmp;
     162                 :            :         int i;
     163                 :            : 
     164                 :            :         output_date->year = 1970;
     165                 :            :         output_date->month = 1;
     166                 :            :         output_date->day = 1;
     167                 :            : 
     168                 :            :         /* compute the proper year */
     169                 :            :         while (1) {
     170                 :            :                 tmp = (is_leap_year(output_date->year)) ?
     171                 :            :                                         366*SECONDS_IN_DAY : 365*SECONDS_IN_DAY;
     172                 :            :                 if (tmp > seconds) {
     173                 :            :                         break;
     174                 :            :                 }
     175                 :            :                 seconds -= tmp;
     176                 :            :                 output_date->year++;
     177                 :            :         }
     178                 :            :         /* compute the proper month */
     179                 :            :         for (i = 0; i < ARRAY_SIZE(days_in_month); i++) {
     180                 :            :                 tmp = ((i == 1) && is_leap_year(output_date->year)) ?
     181                 :            :                                         ((uint64_t)days_in_month[i] + 1) * SECONDS_IN_DAY :
     182                 :            :                                         (uint64_t)days_in_month[i] * SECONDS_IN_DAY;
     183                 :            :                 if (tmp > seconds) {
     184                 :            :                         output_date->month += i;
     185                 :            :                         break;
     186                 :            :                 }
     187                 :            :                 seconds -= tmp;
     188                 :            :         }
     189                 :            : 
     190                 :            :         output_date->day += seconds / SECONDS_IN_DAY;
     191                 :            : }
     192                 :            : 
     193                 :          0 : static int timestamp_print(const struct log_output *output,
     194                 :            :                            uint32_t flags, log_timestamp_t timestamp)
     195                 :            : {
     196                 :          0 :         int length;
     197                 :          0 :         bool format =
     198                 :            :                 (flags & LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP) |
     199                 :            :                 (flags & LOG_OUTPUT_FLAG_FORMAT_SYSLOG) |
     200                 :          0 :                 IS_ENABLED(CONFIG_LOG_OUTPUT_FORMAT_LINUX_TIMESTAMP) |
     201                 :            :                 IS_ENABLED(CONFIG_LOG_OUTPUT_FORMAT_CUSTOM_TIMESTAMP);
     202                 :            : 
     203                 :            : 
     204         [ #  # ]:          0 :         if (!format) {
     205                 :            : #ifndef CONFIG_LOG_TIMESTAMP_64BIT
     206                 :          0 :                 length = print_formatted(output, "[%08lu] ", timestamp);
     207                 :            : #else
     208                 :            :                 length = print_formatted(output, "[%016llu] ", timestamp);
     209                 :            : #endif
     210         [ #  # ]:          0 :         } else if (freq != 0U) {
     211                 :            : #ifndef CONFIG_LOG_TIMESTAMP_64BIT
     212                 :          0 :                 uint32_t total_seconds;
     213                 :            : #else
     214                 :            :                 uint64_t total_seconds;
     215                 :            : #endif
     216                 :          0 :                 uint32_t remainder;
     217                 :          0 :                 uint32_t seconds;
     218                 :          0 :                 uint32_t hours;
     219                 :          0 :                 uint32_t mins;
     220                 :          0 :                 uint32_t ms;
     221                 :          0 :                 uint32_t us;
     222                 :            : 
     223                 :          0 :                 timestamp /= timestamp_div;
     224                 :          0 :                 total_seconds = timestamp / freq;
     225                 :          0 :                 seconds = total_seconds;
     226                 :          0 :                 hours = seconds / 3600U;
     227                 :          0 :                 seconds -= hours * 3600U;
     228                 :          0 :                 mins = seconds / 60U;
     229                 :          0 :                 seconds -= mins * 60U;
     230                 :            : 
     231                 :          0 :                 remainder = timestamp % freq;
     232                 :          0 :                 ms = (remainder * 1000U) / freq;
     233                 :          0 :                 us = (1000 * (remainder * 1000U - (ms * freq))) / freq;
     234                 :            : 
     235                 :          0 :                 if (IS_ENABLED(CONFIG_LOG_BACKEND_NET) && flags & LOG_OUTPUT_FLAG_FORMAT_SYSLOG) {
     236                 :            : #if defined(CONFIG_REQUIRES_FULL_LIBC)
     237                 :            :                         char time_str[sizeof("1970-01-01T00:00:00")];
     238                 :            :                         struct tm tm_timestamp = {0};
     239                 :            :                         time_t time_seconds = total_seconds;
     240                 :            : 
     241                 :            :                         gmtime_r(&time_seconds, &tm_timestamp);
     242                 :            : 
     243                 :            :                         strftime(time_str, sizeof(time_str), "%FT%T", &tm_timestamp);
     244                 :            : 
     245                 :            :                         length = print_formatted(output, "%s.%06uZ ",
     246                 :            :                                                  time_str, ms * 1000U + us);
     247                 :            : #else
     248                 :            :                         struct YMD_date date;
     249                 :            : 
     250                 :            :                         get_YMD_from_seconds(total_seconds, &date);
     251                 :            :                         hours = hours % 24;
     252                 :            :                         length = print_formatted(output,
     253                 :            :                                         "%04u-%02u-%02uT%02u:%02u:%02u.%06uZ ",
     254                 :            :                                         date.year, date.month, date.day,
     255                 :            :                                         hours, mins, seconds, ms * 1000U + us);
     256                 :            : #endif
     257                 :          0 :                 } else if (IS_ENABLED(CONFIG_LOG_OUTPUT_FORMAT_CUSTOM_TIMESTAMP)) {
     258                 :            :                         length = log_custom_timestamp_print(output, timestamp, print_formatted);
     259                 :            :                 } else {
     260                 :          0 :                         if (IS_ENABLED(CONFIG_LOG_OUTPUT_FORMAT_LINUX_TIMESTAMP)) {
     261                 :            :                                 length = print_formatted(output,
     262                 :            : #if defined(CONFIG_LOG_TIMESTAMP_64BIT)
     263                 :            :                                                         "[%5llu.%06d] ",
     264                 :            : #else
     265                 :            :                                                         "[%5lu.%06d] ",
     266                 :            : #endif
     267                 :            :                                                         total_seconds, ms * 1000U + us);
     268                 :          0 :                         } else if (IS_ENABLED(CONFIG_LOG_OUTPUT_FORMAT_DATE_TIMESTAMP)) {
     269                 :            : #if defined(CONFIG_REQUIRES_FULL_LIBC)
     270                 :            :                                 char time_str[sizeof("1970-01-01 00:00:00")];
     271                 :            :                                 struct tm tm_timestamp = {0};
     272                 :            :                                 time_t time_seconds = total_seconds;
     273                 :            : 
     274                 :            :                                 gmtime_r(&time_seconds, &tm_timestamp);
     275                 :            : 
     276                 :            :                                 strftime(time_str, sizeof(time_str), "%F %T", &tm_timestamp);
     277                 :            : 
     278                 :            :                                 length = print_formatted(output, "[%s.%03u,%03u] ", time_str, ms,
     279                 :            :                                                          us);
     280                 :            : #else
     281                 :            :                                 struct YMD_date date;
     282                 :            : 
     283                 :            :                                 get_YMD_from_seconds(total_seconds, &date);
     284                 :            :                                 hours = hours % 24;
     285                 :            :                                 length = print_formatted(
     286                 :            :                                         output, "[%04u-%02u-%02u %02u:%02u:%02u.%03u,%03u] ",
     287                 :            :                                         date.year, date.month, date.day, hours, mins, seconds, ms,
     288                 :            :                                         us);
     289                 :            : #endif
     290                 :          0 :                         } else if (IS_ENABLED(CONFIG_LOG_OUTPUT_FORMAT_ISO8601_TIMESTAMP)) {
     291                 :            : #if defined(CONFIG_REQUIRES_FULL_LIBC)
     292                 :            :                                 char time_str[sizeof("1970-01-01T00:00:00")];
     293                 :            :                                 struct tm tm_timestamp = {0};
     294                 :            :                                 time_t time_seconds = total_seconds;
     295                 :            : 
     296                 :            :                                 gmtime_r(&time_seconds, &tm_timestamp);
     297                 :            : 
     298                 :            :                                 strftime(time_str, sizeof(time_str), "%FT%T", &tm_timestamp);
     299                 :            : 
     300                 :            :                                 length = print_formatted(output, "[%s,%06uZ] ", time_str,
     301                 :            :                                                          ms * 1000U + us);
     302                 :            : #else
     303                 :            :                                 struct YMD_date date;
     304                 :            : 
     305                 :            :                                 get_YMD_from_seconds(total_seconds, &date);
     306                 :            :                                 hours = hours % 24;
     307                 :            :                                 length = print_formatted(output,
     308                 :            :                                                          "[%04u-%02u-%02uT%02u:%02u:%02u,%06uZ] ",
     309                 :            :                                                          date.year, date.month, date.day, hours,
     310                 :            :                                                          mins, seconds, ms * 1000U + us);
     311                 :            : #endif
     312                 :            :                         } else {
     313                 :          0 :                                 length = print_formatted(output,
     314                 :            :                                                         "[%02u:%02u:%02u.%03u,%03u] ",
     315                 :            :                                                         hours, mins, seconds, ms, us);
     316                 :            :                         }
     317                 :            :                 }
     318                 :            :         } else {
     319                 :            :                 length = 0;
     320                 :            :         }
     321                 :            : 
     322                 :          0 :         return length;
     323                 :            : }
     324                 :            : 
     325                 :          0 : static void color_print(const struct log_output *output,
     326                 :            :                         bool color, bool start, uint32_t level)
     327                 :            : {
     328         [ #  # ]:          0 :         if (color) {
     329         [ #  # ]:          0 :                 const char *log_color = start && (colors[level] != NULL) ?
     330         [ #  # ]:          0 :                                 colors[level] : LOG_COLOR_CODE_DEFAULT;
     331                 :          0 :                 print_formatted(output, "%s", log_color);
     332                 :            :         }
     333                 :          0 : }
     334                 :            : 
     335                 :          0 : static void color_prefix(const struct log_output *output,
     336                 :            :                          bool color, uint32_t level)
     337                 :            : {
     338                 :          0 :         color_print(output, color, true, level);
     339                 :          0 : }
     340                 :            : 
     341                 :          0 : static void color_postfix(const struct log_output *output,
     342                 :            :                           bool color, uint32_t level)
     343                 :            : {
     344                 :          0 :         color_print(output, color, false, level);
     345                 :          0 : }
     346                 :            : 
     347                 :            : 
     348                 :          0 : static int ids_print(const struct log_output *output,
     349                 :            :                      bool level_on,
     350                 :            :                      bool func_on,
     351                 :            :                      bool thread_on,
     352                 :            :                      const char *domain,
     353                 :            :                      const char *source,
     354                 :            :                      k_tid_t tid,
     355                 :            :                      uint32_t level)
     356                 :            : {
     357                 :          0 :         int total = 0;
     358                 :            : 
     359         [ #  # ]:          0 :         if (level_on) {
     360                 :          0 :                 total += print_formatted(output, "<%s> ", severity[level]);
     361                 :            :         }
     362                 :            : 
     363                 :          0 :         if (IS_ENABLED(CONFIG_LOG_THREAD_ID_PREFIX) && thread_on) {
     364                 :            :                 if (IS_ENABLED(CONFIG_THREAD_NAME)) {
     365                 :            :                         total += print_formatted(output, "[%s] ",
     366                 :            :                                 tid == NULL ? "irq" : k_thread_name_get(tid));
     367                 :            :                 } else {
     368                 :            :                         total += print_formatted(output, "[%p] ", tid);
     369                 :            :                 }
     370                 :            :         }
     371                 :            : 
     372         [ #  # ]:          0 :         if (domain) {
     373                 :          0 :                 total += print_formatted(output, "%s/", domain);
     374                 :            :         }
     375                 :            : 
     376         [ #  # ]:          0 :         if (source) {
     377         [ #  # ]:          0 :                 total += print_formatted(output,
     378                 :          0 :                                 (func_on &&
     379         [ #  # ]:          0 :                                 ((1 << level) & LOG_FUNCTION_PREFIX_MASK)) ?
     380                 :            :                                 "%s." : "%s: ",
     381                 :            :                                 source);
     382                 :            :         }
     383                 :            : 
     384                 :          0 :         return total;
     385                 :            : }
     386                 :            : 
     387                 :          0 : static void newline_print(const struct log_output *ctx, uint32_t flags)
     388                 :            : {
     389                 :          0 :         if (IS_ENABLED(CONFIG_LOG_BACKEND_NET) &&
     390                 :            :             flags & LOG_OUTPUT_FLAG_FORMAT_SYSLOG) {
     391                 :            :                 return;
     392                 :            :         }
     393                 :            : 
     394         [ #  # ]:          0 :         if ((flags & LOG_OUTPUT_FLAG_CRLF_NONE) != 0U) {
     395                 :            :                 return;
     396                 :            :         }
     397                 :            : 
     398         [ #  # ]:          0 :         if ((flags & LOG_OUTPUT_FLAG_CRLF_LFONLY) != 0U) {
     399                 :          0 :                 print_formatted(ctx, "\n");
     400                 :            :         } else {
     401                 :          0 :                 print_formatted(ctx, "\r\n");
     402                 :            :         }
     403                 :            : }
     404                 :            : 
     405                 :          0 : static void hexdump_line_print(const struct log_output *output,
     406                 :            :                                const uint8_t *data, uint32_t length,
     407                 :            :                                int prefix_offset, uint32_t flags)
     408                 :            : {
     409                 :          0 :         newline_print(output, flags);
     410                 :            : 
     411         [ #  # ]:          0 :         for (int i = 0; i < prefix_offset; i++) {
     412                 :          0 :                 print_formatted(output, " ");
     413                 :            :         }
     414                 :            : 
     415         [ #  # ]:          0 :         for (int i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) {
     416   [ #  #  #  # ]:          0 :                 if (i > 0 && !(i % 8)) {
     417                 :          0 :                         print_formatted(output, " ");
     418                 :            :                 }
     419                 :            : 
     420         [ #  # ]:          0 :                 if (i < length) {
     421                 :          0 :                         print_formatted(output, "%02x ", data[i]);
     422                 :            :                 } else {
     423                 :          0 :                         print_formatted(output, "   ");
     424                 :            :                 }
     425                 :            :         }
     426                 :            : 
     427                 :          0 :         print_formatted(output, "|");
     428                 :            : 
     429         [ #  # ]:          0 :         for (int i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) {
     430   [ #  #  #  # ]:          0 :                 if (i > 0 && !(i % 8)) {
     431                 :          0 :                         print_formatted(output, " ");
     432                 :            :                 }
     433                 :            : 
     434         [ #  # ]:          0 :                 if (i < length) {
     435                 :          0 :                         unsigned char c = (unsigned char)data[i];
     436                 :            : 
     437                 :          0 :                         print_formatted(output, "%c",
     438         [ #  # ]:          0 :                               isprint((int)c) != 0 ? c : '.');
     439                 :            :                 } else {
     440                 :          0 :                         print_formatted(output, " ");
     441                 :            :                 }
     442                 :            :         }
     443                 :          0 : }
     444                 :            : 
     445                 :          0 : static void log_msg_hexdump(const struct log_output *output,
     446                 :            :                             uint8_t *data, uint32_t len,
     447                 :            :                             int prefix_offset, uint32_t flags)
     448                 :            : {
     449                 :          0 :         size_t length;
     450                 :            : 
     451                 :          0 :         do {
     452                 :          0 :                 length = MIN(len, HEXDUMP_BYTES_IN_LINE);
     453                 :            : 
     454                 :          0 :                 hexdump_line_print(output, data, length,
     455                 :            :                                    prefix_offset, flags);
     456                 :          0 :                 data += length;
     457                 :          0 :                 len -= length;
     458         [ #  # ]:          0 :         } while (len);
     459                 :          0 : }
     460                 :            : 
     461                 :            : #if defined(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_SEQID)
     462                 :            : static int32_t get_sequence_id(void)
     463                 :            : {
     464                 :            :         static int32_t id;
     465                 :            : 
     466                 :            :         if (++id < 0) {
     467                 :            :                 id = 1;
     468                 :            :         }
     469                 :            : 
     470                 :            :         return id;
     471                 :            : }
     472                 :            : #endif
     473                 :            : 
     474                 :            : #if defined(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_TZKNOWN)
     475                 :            : static bool is_tzknown(void)
     476                 :            : {
     477                 :            :         /* TODO: use proper implementation */
     478                 :            :         return false;
     479                 :            : }
     480                 :            : #endif
     481                 :            : 
     482                 :            : #if defined(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_ISSYNCED)
     483                 :            : static bool is_synced(void)
     484                 :            : {
     485                 :            :         /* TODO: use proper implementation */
     486                 :            :         return IS_ENABLED(CONFIG_SNTP);
     487                 :            : }
     488                 :            : #endif
     489                 :            : 
     490                 :            : static int syslog_print(const struct log_output *output,
     491                 :            :                         bool level_on,
     492                 :            :                         bool func_on,
     493                 :            :                         bool *thread_on,
     494                 :            :                         const char *domain,
     495                 :            :                         const char *source,
     496                 :            :                         k_tid_t tid,
     497                 :            :                         uint32_t level,
     498                 :            :                         uint32_t length)
     499                 :            : {
     500                 :            :         uint32_t len = length;
     501                 :            : 
     502                 :            :         /* The syslog output format is:
     503                 :            :          * HOSTNAME SP APP-NAME SP PROCID SP MSGID SP STRUCTURED-DATA
     504                 :            :          */
     505                 :            : 
     506                 :            :         /* First HOSTNAME */
     507                 :            :         len += print_formatted(output, "%s ",
     508                 :            :                                output->control_block->hostname ?
     509                 :            :                                output->control_block->hostname :
     510                 :            :                                "zephyr");
     511                 :            : 
     512                 :            :         /* Then APP-NAME. We use the thread name here. It should not
     513                 :            :          * contain any space characters.
     514                 :            :          */
     515                 :            :         if (*thread_on) {
     516                 :            :                 if (IS_ENABLED(CONFIG_THREAD_NAME)) {
     517                 :            :                         if (strstr(k_thread_name_get(tid), " ") != NULL) {
     518                 :            :                                 goto do_not_print_name;
     519                 :            :                         }
     520                 :            : 
     521                 :            :                         len += print_formatted(output, "%s ",
     522                 :            :                                                tid == NULL ?
     523                 :            :                                                "irq" :
     524                 :            :                                                k_thread_name_get(tid));
     525                 :            :                 } else {
     526                 :            : do_not_print_name:
     527                 :            :                         len += print_formatted(output, "%p ", tid);
     528                 :            :                 }
     529                 :            : 
     530                 :            :                 /* Do not print thread id in the message as it was already
     531                 :            :                  * printed above.
     532                 :            :                  */
     533                 :            :                 *thread_on = false;
     534                 :            :         } else {
     535                 :            :                 /* No APP-NAME */
     536                 :            :                 len += print_formatted(output, "- ");
     537                 :            :         }
     538                 :            : 
     539                 :            :         if (!IS_ENABLED(CONFIG_LOG_BACKEND_NET_RFC5424_STRUCTURED_DATA)) {
     540                 :            :                 /* No PROCID, MSGID or STRUCTURED-DATA */
     541                 :            :                 len += print_formatted(output, "- - - ");
     542                 :            : 
     543                 :            :                 return len;
     544                 :            :         }
     545                 :            : 
     546                 :            : 
     547                 :            : #if defined(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_SOFTWARE) || \
     548                 :            :         defined(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_SOFTWARE_VERSION)
     549                 :            : #define STRUCTURED_DATA_ORIGIN_START      "[origin"
     550                 :            : #define STRUCTURED_DATA_ORIGIN_SW         " software=\"%s\""
     551                 :            : #define STRUCTURED_DATA_ORIGIN_SW_VERSION " swVersion=\"%u\""
     552                 :            : #define STRUCTURED_DATA_ORIGIN_END        "]"
     553                 :            : #define STRUCTURED_DATA_ORIGIN                                                \
     554                 :            :             STRUCTURED_DATA_ORIGIN_START                                      \
     555                 :            :             COND_CODE_1(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_SOFTWARE,        \
     556                 :            :                         (STRUCTURED_DATA_ORIGIN_SW), ("%s"))                \
     557                 :            :             COND_CODE_1(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_SOFTWARE_VERSION,\
     558                 :            :                         (STRUCTURED_DATA_ORIGIN_SW_VERSION), ("%s"))        \
     559                 :            :             STRUCTURED_DATA_ORIGIN_END
     560                 :            : #else
     561                 :            : #define STRUCTURED_DATA_ORIGIN "%s%s"
     562                 :            : #endif
     563                 :            : 
     564                 :            : #if defined(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_SEQID) || \
     565                 :            :         defined(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_UPTIME)
     566                 :            : #define STRUCTURED_DATA_META_START  "[meta"
     567                 :            : #define STRUCTURED_DATA_META_SEQID  " sequenceId=\"%d\""
     568                 :            : #define STRUCTURED_DATA_META_UPTIME " sysUpTime=\"%d\""
     569                 :            : #define STRUCTURED_DATA_META_END    "]"
     570                 :            : #define STRUCTURED_DATA_META                                            \
     571                 :            :             STRUCTURED_DATA_META_START                                  \
     572                 :            :             COND_CODE_1(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_SEQID,     \
     573                 :            :                         (STRUCTURED_DATA_META_SEQID), ("%s"))         \
     574                 :            :             COND_CODE_1(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_UPTIME,    \
     575                 :            :                         (STRUCTURED_DATA_META_UPTIME), ("%s"))                \
     576                 :            :             STRUCTURED_DATA_META_END
     577                 :            : #else
     578                 :            : #define STRUCTURED_DATA_META "%s%s"
     579                 :            : #endif
     580                 :            : 
     581                 :            : #if defined(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_TZKNOWN) || \
     582                 :            :         defined(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_ISSYNCED)
     583                 :            : #define STRUCTURED_DATA_TIMEQUALITY_START    "[timeQuality"
     584                 :            : #define STRUCTURED_DATA_TIMEQUALITY_TZKNOWN  " tzKnown=\"%d\""
     585                 :            : #define STRUCTURED_DATA_TIMEQUALITY_ISSYNCED " isSynced=\"%d\""
     586                 :            : #define STRUCTURED_DATA_TIMEQUALITY_END      "]"
     587                 :            : #define STRUCTURED_DATA_TIMEQUALITY                                     \
     588                 :            :             STRUCTURED_DATA_TIMEQUALITY_START                           \
     589                 :            :             COND_CODE_1(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_TZKNOWN,   \
     590                 :            :                         (STRUCTURED_DATA_TIMEQUALITY_TZKNOWN), ("%s"))        \
     591                 :            :             COND_CODE_1(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_ISSYNCED,  \
     592                 :            :                         (STRUCTURED_DATA_TIMEQUALITY_ISSYNCED), ("%s"))       \
     593                 :            :             STRUCTURED_DATA_TIMEQUALITY_END
     594                 :            : #else
     595                 :            : #define STRUCTURED_DATA_TIMEQUALITY "%s%s"
     596                 :            : #endif
     597                 :            : 
     598                 :            :         /* No PROCID or MSGID, but there is structured data.
     599                 :            :          */
     600                 :            :         len += print_formatted(output,
     601                 :            :                 "- - "
     602                 :            :                 STRUCTURED_DATA_META
     603                 :            :                 STRUCTURED_DATA_ORIGIN
     604                 :            :                 STRUCTURED_DATA_TIMEQUALITY,
     605                 :            :                 COND_CODE_1(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_SEQID,
     606                 :            :                             (get_sequence_id()), ("")),
     607                 :            :                 COND_CODE_1(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_UPTIME,
     608                 :            :                             /* in hundredths of a sec */
     609                 :            :                             (k_uptime_get_32() / 10), ("")),
     610                 :            :                 COND_CODE_1(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_SOFTWARE,
     611                 :            :                             (CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_SOFTWARE_VALUE),
     612                 :            :                             ("")),
     613                 :            :                 COND_CODE_1(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_SOFTWARE_VERSION,
     614                 :            :                             (sys_kernel_version_get()), ("")),
     615                 :            :                 COND_CODE_1(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_TZKNOWN,
     616                 :            :                             (is_tzknown()), ("")),
     617                 :            :                 COND_CODE_1(CONFIG_LOG_BACKEND_NET_RFC5424_SDATA_ISSYNCED,
     618                 :            :                             (is_synced()), (""))
     619                 :            :                 );
     620                 :            : 
     621                 :            :         return len;
     622                 :            : }
     623                 :            : 
     624                 :          0 : static uint32_t prefix_print(const struct log_output *output,
     625                 :            :                              uint32_t flags,
     626                 :            :                              bool func_on,
     627                 :            :                              log_timestamp_t timestamp,
     628                 :            :                              const char *domain,
     629                 :            :                              const char *source,
     630                 :            :                              k_tid_t tid,
     631                 :            :                              uint8_t level)
     632                 :            : {
     633         [ #  # ]:          0 :         __ASSERT_NO_MSG(level <= LOG_LEVEL_DBG);
     634                 :          0 :         uint32_t length = 0U;
     635                 :            : 
     636                 :          0 :         bool stamp = flags & LOG_OUTPUT_FLAG_TIMESTAMP;
     637                 :          0 :         bool colors_on = flags & LOG_OUTPUT_FLAG_COLORS;
     638                 :          0 :         bool level_on = flags & LOG_OUTPUT_FLAG_LEVEL;
     639                 :          0 :         bool thread_on = IS_ENABLED(CONFIG_LOG_THREAD_ID_PREFIX) &&
     640                 :            :                          (flags & LOG_OUTPUT_FLAG_THREAD);
     641                 :          0 :         bool source_off = flags & LOG_OUTPUT_FLAG_SKIP_SOURCE;
     642                 :          0 :         const char *tag = IS_ENABLED(CONFIG_LOG) ? z_log_get_tag() : NULL;
     643                 :            : 
     644                 :          0 :         if (IS_ENABLED(CONFIG_LOG_BACKEND_NET) &&
     645                 :            :             flags & LOG_OUTPUT_FLAG_FORMAT_SYSLOG) {
     646                 :            :                 /* TODO: As there is no way to figure out the
     647                 :            :                  * facility at this point, use a pre-defined value.
     648                 :            :                  * Change this to use the real facility of the
     649                 :            :                  * logging call when that info is available.
     650                 :            :                  */
     651                 :            :                 static const int facility = 16; /* local0 */
     652                 :            : 
     653                 :            :                 length += print_formatted(
     654                 :            :                         output,
     655                 :            :                          /* <PRI>VERSION */
     656                 :            :                         "<%d>1 ",
     657                 :            :                         facility * 8 +
     658                 :            :                         level_to_rfc5424_severity(level));
     659                 :            :         }
     660                 :            : 
     661         [ #  # ]:          0 :         if (tag) {
     662                 :          0 :                 length += print_formatted(output, "%s ", tag);
     663                 :            :         }
     664                 :            : 
     665         [ #  # ]:          0 :         if (stamp) {
     666                 :          0 :                 length += timestamp_print(output, flags, timestamp);
     667                 :            :         }
     668                 :            : 
     669                 :          0 :         if (IS_ENABLED(CONFIG_LOG_BACKEND_NET) &&
     670                 :            :             flags & LOG_OUTPUT_FLAG_FORMAT_SYSLOG) {
     671                 :            :                 length += syslog_print(output, level_on, func_on, &thread_on, domain,
     672                 :            :                                        source_off ? NULL : source, tid, level, length);
     673                 :            :         } else {
     674                 :          0 :                 color_prefix(output, colors_on, level);
     675                 :            :         }
     676                 :            : 
     677         [ #  # ]:          0 :         length += ids_print(output, level_on, func_on, thread_on, domain,
     678                 :            :                             source_off ? NULL : source, tid, level);
     679                 :            : 
     680                 :          0 :         return length;
     681                 :            : }
     682                 :            : 
     683                 :          0 : static void postfix_print(const struct log_output *output,
     684                 :            :                           uint32_t flags, uint8_t level)
     685                 :            : {
     686                 :          0 :         color_postfix(output, (flags & LOG_OUTPUT_FLAG_COLORS),
     687                 :            :                               level);
     688                 :          0 :         newline_print(output, flags);
     689                 :          0 : }
     690                 :            : 
     691                 :        177 : void log_output_process(const struct log_output *output,
     692                 :            :                         log_timestamp_t timestamp,
     693                 :            :                         const char *domain,
     694                 :            :                         const char *source,
     695                 :            :                         k_tid_t tid,
     696                 :            :                         uint8_t level,
     697                 :            :                         const uint8_t *package,
     698                 :            :                         const uint8_t *data,
     699                 :            :                         size_t data_len,
     700                 :            :                         uint32_t flags)
     701                 :            : {
     702                 :        177 :         bool raw_string = (level == LOG_LEVEL_INTERNAL_RAW_STRING);
     703                 :        177 :         uint32_t prefix_offset;
     704                 :        177 :         cbprintf_cb cb;
     705                 :            : 
     706         [ -  + ]:        177 :         if (!raw_string) {
     707                 :          0 :                 prefix_offset = prefix_print(output, flags, 0, timestamp,
     708                 :            :                                              domain, source, tid, level);
     709                 :          0 :                 cb = out_func;
     710                 :            :         } else {
     711                 :        177 :                 prefix_offset = 0;
     712                 :            :                 /* source set to 1 indicates raw string and contrary to printk
     713                 :            :                  * case it should not append anything to the output (printk is
     714                 :            :                  * appending <CR> to the new line character).
     715                 :            :                  */
     716         [ +  - ]:        177 :                 cb = ((uintptr_t)source == 1) ? out_func : cr_out_func;
     717                 :            :         }
     718                 :            : 
     719         [ +  - ]:        177 :         if (package) {
     720                 :        177 :                 int err = cbpprintf(cb, (void *)output, (void *)package);
     721                 :            : 
     722                 :        177 :                 (void)err;
     723         [ -  + ]:        177 :                 __ASSERT_NO_MSG(err >= 0);
     724                 :            :         }
     725                 :            : 
     726         [ -  + ]:        177 :         if (data_len) {
     727                 :          0 :                 log_msg_hexdump(output, (uint8_t *)data, data_len, prefix_offset, flags);
     728                 :            :         }
     729                 :            : 
     730         [ -  + ]:        177 :         if (!raw_string) {
     731                 :          0 :                 postfix_print(output, flags, level);
     732                 :            :         }
     733                 :            : 
     734                 :        177 :         log_output_flush(output);
     735                 :        177 : }
     736                 :            : 
     737                 :        177 : void log_output_msg_process(const struct log_output *output,
     738                 :            :                             struct log_msg *msg, uint32_t flags)
     739                 :            : {
     740                 :        177 :         log_timestamp_t timestamp = log_msg_get_timestamp(msg);
     741                 :        177 :         uint8_t level = log_msg_get_level(msg);
     742                 :        177 :         uint8_t domain_id = log_msg_get_domain(msg);
     743                 :        177 :         int16_t source_id = log_msg_get_source_id(msg);
     744                 :            : 
     745         [ -  + ]:        177 :         const char *sname = source_id >= 0 ? log_source_name_get(domain_id, source_id) : NULL;
     746                 :        177 :         size_t plen, dlen;
     747                 :        177 :         uint8_t *package = log_msg_get_package(msg, &plen);
     748                 :        177 :         uint8_t *data = log_msg_get_data(msg, &dlen);
     749                 :            : 
     750                 :        177 :         log_output_process(output, timestamp, NULL, sname, (k_tid_t)log_msg_get_tid(msg), level,
     751         [ -  + ]:        177 :                            plen > 0 ? package : NULL, data, dlen, flags);
     752                 :        177 : }
     753                 :            : 
     754                 :          0 : void log_output_dropped_process(const struct log_output *output, uint32_t cnt)
     755                 :            : {
     756                 :          0 :         char buf[5];
     757                 :          0 :         int len;
     758                 :          0 :         static const char prefix[] = DROPPED_COLOR_PREFIX "--- ";
     759                 :          0 :         static const char postfix[] =
     760                 :            :                         " messages dropped ---\r\n" DROPPED_COLOR_POSTFIX;
     761                 :          0 :         log_output_func_t outf = output->func;
     762                 :            : 
     763                 :          0 :         cnt = MIN(cnt, 9999);
     764                 :          0 :         len = snprintk(buf, sizeof(buf), "%d", cnt);
     765                 :            : 
     766                 :          0 :         log_output_write(outf, (uint8_t *)prefix, sizeof(prefix) - 1, output->control_block->ctx);
     767                 :          0 :         log_output_write(outf, buf, len, output->control_block->ctx);
     768                 :          0 :         log_output_write(outf, (uint8_t *)postfix, sizeof(postfix) - 1, output->control_block->ctx);
     769                 :          0 : }
     770                 :            : 
     771                 :          1 : void log_output_timestamp_freq_set(uint32_t frequency)
     772                 :            : {
     773                 :          1 :         timestamp_div = 1U;
     774                 :            :         /* There is no point to have frequency higher than 1MHz (ns are not
     775                 :            :          * printed) and too high frequency leads to overflows in calculations.
     776                 :            :          */
     777         [ -  + ]:          1 :         while (frequency > 1000000) {
     778                 :          0 :                 frequency /= 2U;
     779                 :          0 :                 timestamp_div *= 2U;
     780                 :            :         }
     781                 :            : 
     782                 :          1 :         freq = frequency;
     783                 :          1 : }
     784                 :            : 
     785                 :          0 : uint64_t log_output_timestamp_to_us(log_timestamp_t timestamp)
     786                 :            : {
     787                 :          0 :         timestamp /= timestamp_div;
     788                 :            : 
     789                 :          0 :         return ((uint64_t) timestamp * 1000000U) / freq;
     790                 :            : }

Generated by: LCOV version 1.14