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: 54 197 27.4 %
Date: 2024-09-16 20:15:30 Functions: 7 20 35.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 12 76 15.8 %

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

Generated by: LCOV version 1.14