LCOV - code coverage report
Current view: top level - shared - dlt_log.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 88.4 % 129 114
Test Date: 2025-03-25 20:53:42 Functions: 100.0 % 15 15

            Line data    Source code
       1              : /*
       2              :  * SPDX license identifier: MPL-2.0
       3              :  *
       4              :  * Copyright (C) 2024, Mercedes Benz Tech Innovation GmbH
       5              :  *
       6              :  * This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
       7              :  *
       8              :  * This Source Code Form is subject to the terms of the
       9              :  * Mozilla Public License (MPL), v. 2.0.
      10              :  * If a copy of the MPL was not distributed with this file,
      11              :  * You can obtain one at http://mozilla.org/MPL/2.0/.
      12              :  *
      13              :  * For further information see https://www.covesa.global/.
      14              :  */
      15              : 
      16              : /*!
      17              :  * \author
      18              :  * Daniel Weber <daniel.w.weber@mercedes-benz.com>
      19              :  *
      20              :  * \copyright Copyright © 2024 Mercedes Benz Tech Innovation GmbH. \n
      21              :  * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
      22              :  *
      23              :  * \file dlt_log.c
      24              :  */
      25              : 
      26              : #include "dlt_log.h"
      27              : #include "dlt_common.h"
      28              : #include "dlt_multiple_files.h"
      29              : #include <syslog.h>
      30              : #include <errno.h>
      31              : #include <libgen.h>   /* dirname */
      32              : #include <limits.h>   /* for NAME_MAX */
      33              : #include <string.h>   /* for strlen() */
      34              : #include <stdlib.h>   /* for calloc(), free() */
      35              : #include <stdarg.h>   /* va_list, va_start */
      36              : 
      37              : /* internal logging parameters */
      38              : static int logging_level = LOG_INFO;
      39              : static char logging_filename[NAME_MAX + 1] = "";
      40              : DltLoggingMode logging_mode = DLT_LOG_TO_STDERR;
      41              : FILE *logging_handle = NULL;
      42              : 
      43              : //use ohandle as an indicator that multiple files logging is active
      44              : MultipleFilesRingBuffer multiple_files_ring_buffer = {
      45              :         .directory={0},
      46              :         .filename={0},
      47              :         .fileSize=0,
      48              :         .maxSize=0,
      49              :         .filenameTimestampBased=false,
      50              :         .filenameBase={0},
      51              :         .filenameExt={0},
      52              :         .ohandle=-1};
      53              : 
      54              : 
      55           17 : void dlt_log_set_filename(const char *filename)
      56              : {
      57              :     /* check nullpointer */
      58           17 :     if (filename == NULL) {
      59            1 :         dlt_log(LOG_WARNING, "Wrong parameter: filename is NULL\n");
      60            1 :         return;
      61              :     }
      62              : 
      63              :     strncpy(logging_filename, filename, NAME_MAX);
      64           16 :     logging_filename[NAME_MAX] = 0;
      65              : }
      66              : 
      67           19 : void dlt_log_set_level(int level)
      68              : {
      69           19 :     if ((level < 0) || (level > LOG_DEBUG)) {
      70            0 :         if (logging_level < LOG_WARNING)
      71            0 :             logging_level = LOG_WARNING;
      72              : 
      73            0 :         dlt_vlog(LOG_WARNING, "Wrong parameter for level: %d\n", level);
      74              :     }
      75              :     else {
      76           19 :         logging_level = level;
      77              :     }
      78           19 : }
      79              : 
      80           12 : DltReturnValue dlt_log_init(int mode)
      81              : {
      82           12 :     return dlt_log_init_multiple_logfiles_support((DltLoggingMode)mode, false, 0, 0);
      83              : }
      84              : 
      85              : 
      86           26 : DltReturnValue dlt_log_init_multiple_logfiles_support(const DltLoggingMode mode, const bool enable_multiple_logfiles,
      87              :                                                       const int logging_file_size, const int logging_files_max_size)
      88              : {
      89           26 :     if ((mode < DLT_LOG_TO_CONSOLE) || (mode > DLT_LOG_DROPPED)) {
      90            0 :         dlt_vlog(LOG_WARNING, "Wrong parameter for mode: %d\n", mode);
      91            0 :         return DLT_RETURN_WRONG_PARAMETER;
      92              :     }
      93              : 
      94           26 :     logging_mode = mode;
      95              : 
      96           26 :     if (logging_mode != DLT_LOG_TO_FILE) {
      97              :         return DLT_RETURN_OK;
      98              :     }
      99              : 
     100              :     DltReturnValue result;
     101            7 :     if (enable_multiple_logfiles) {
     102            4 :         dlt_user_printf("configure dlt logging using file limits\n");
     103            4 :         result = dlt_log_init_multiple_logfiles(logging_file_size, logging_files_max_size);
     104            4 :         if (result != DLT_RETURN_OK) {
     105            1 :             dlt_user_printf("dlt logging for limits fails with error code=%d, use logging without limits as fallback\n", result);
     106            1 :             result = dlt_log_init_single_logfile();
     107              :         }
     108              :     } else {
     109            3 :         dlt_user_printf("configure dlt logging without file limits\n");
     110            3 :         result = dlt_log_init_single_logfile();
     111              :     }
     112              : 
     113              :     return result;
     114              : }
     115              : 
     116            4 : DltReturnValue dlt_log_init_single_logfile()
     117              : {
     118              :     /* internal logging to file */
     119            4 :     errno = 0;
     120            4 :     logging_handle = fopen(logging_filename, "a");
     121              : 
     122            4 :     if (logging_handle == NULL) {
     123            0 :         dlt_user_printf("Internal log file %s cannot be opened, error: %s\n", logging_filename, strerror(errno));
     124            0 :         return DLT_RETURN_ERROR;
     125              :     }
     126              :     return DLT_RETURN_OK;
     127              : }
     128              : 
     129            4 : DltReturnValue dlt_log_init_multiple_logfiles(const int logging_file_size, const int logging_files_max_size)
     130              : {
     131              :     char path_logging_filename[PATH_MAX + 1];
     132              :     strncpy(path_logging_filename, logging_filename, PATH_MAX);
     133            4 :     path_logging_filename[PATH_MAX] = 0;
     134              : 
     135            4 :     const char *directory = dirname(path_logging_filename);
     136            4 :     if (directory[0]) {
     137              :         char basename_logging_filename[NAME_MAX + 1];
     138              :         strncpy(basename_logging_filename, logging_filename, NAME_MAX);
     139            4 :         basename_logging_filename[NAME_MAX] = 0;
     140              : 
     141            4 :         const char *file_name = basename(basename_logging_filename);
     142              :         char filename_base[NAME_MAX];
     143            4 :         if (!dlt_extract_base_name_without_ext(file_name, filename_base, sizeof(filename_base))) return DLT_RETURN_ERROR;
     144              : 
     145            3 :         const char *filename_ext = get_filename_ext(file_name);
     146            3 :         if (!filename_ext) return DLT_RETURN_ERROR;
     147              : 
     148            3 :         DltReturnValue result = multiple_files_buffer_init(
     149              :                 &multiple_files_ring_buffer,
     150              :                 directory,
     151              :                 logging_file_size,
     152              :                 logging_files_max_size,
     153              :                 false,
     154              :                 true,
     155              :                 filename_base,
     156              :                 filename_ext);
     157              : 
     158            3 :         return result;
     159              :     }
     160              : 
     161              :     return DLT_RETURN_ERROR;
     162              : }
     163              : 
     164         2852 : int dlt_user_printf(const char *format, ...)
     165              : {
     166         2852 :     if (format == NULL) return -1;
     167              : 
     168              :     va_list args;
     169         2852 :     va_start(args, format);
     170              : 
     171              :     int ret = 0;
     172              : 
     173         2852 :     switch (logging_mode) {
     174            8 :         case DLT_LOG_TO_CONSOLE:
     175              :         case DLT_LOG_TO_SYSLOG:
     176              :         case DLT_LOG_TO_FILE:
     177              :         case DLT_LOG_DROPPED:
     178              :         default:
     179            8 :             ret = vfprintf(stdout, format, args);
     180            8 :             break;
     181         2844 :         case DLT_LOG_TO_STDERR:
     182         2844 :             ret = vfprintf(stderr, format, args);
     183         2844 :             break;
     184              :     }
     185              : 
     186         2852 :     va_end(args);
     187              : 
     188         2852 :     return ret;
     189              : }
     190              : 
     191        70317 : DltReturnValue dlt_log(int prio, const char *s)
     192              : {
     193              :     static const char asSeverity[LOG_DEBUG +
     194              :                                  2][11] =
     195              :             { "EMERGENCY", "ALERT    ", "CRITICAL ", "ERROR    ", "WARNING  ", "NOTICE   ", "INFO     ", "DEBUG    ",
     196              :               "         " };
     197              :     static const char sFormatString[] = "[%5u.%06u]~DLT~%5d~%s~%s";
     198              :     struct timespec sTimeSpec;
     199              : 
     200        70317 :     if (s == NULL)
     201              :         return DLT_RETURN_WRONG_PARAMETER;
     202              : 
     203        70316 :     if (logging_level < prio)
     204              :         return DLT_RETURN_OK;
     205              : 
     206        69400 :     if ((prio < 0) || (prio > LOG_DEBUG))
     207              :         prio = LOG_DEBUG + 1;
     208              : 
     209        69400 :     clock_gettime(CLOCK_MONOTONIC, &sTimeSpec);
     210              : 
     211        69396 :     switch (logging_mode) {
     212          525 :         case DLT_LOG_TO_CONSOLE:
     213              :             /* log to stdout */
     214         1050 :             fprintf(stdout, sFormatString,
     215          525 :                     (unsigned int)sTimeSpec.tv_sec,
     216          525 :                     (unsigned int)(sTimeSpec.tv_nsec / 1000),
     217              :                     getpid(),
     218          525 :                     asSeverity[prio],
     219              :                     s);
     220          525 :             fflush(stdout);
     221          525 :             break;
     222        68834 :         case DLT_LOG_TO_STDERR:
     223              :             /* log to stderr */
     224       137671 :             fprintf(stderr, sFormatString,
     225        68837 :                     (unsigned int)sTimeSpec.tv_sec,
     226        68837 :                     (unsigned int)(sTimeSpec.tv_nsec / 1000),
     227              :                     getpid(),
     228        68834 :                     asSeverity[prio],
     229              :                     s);
     230              :             break;
     231            0 :         case DLT_LOG_TO_SYSLOG:
     232              :             /* log to syslog */
     233              : #if !defined (__WIN32__) && !defined(_MSC_VER)
     234            0 :             openlog("DLT", LOG_PID, LOG_DAEMON);
     235            0 :             syslog(prio,
     236              :                    sFormatString,
     237            0 :                    (unsigned int)sTimeSpec.tv_sec,
     238            0 :                    (unsigned int)(sTimeSpec.tv_nsec / 1000),
     239              :                    getpid(),
     240            0 :                    asSeverity[prio],
     241              :                    s);
     242            0 :             closelog();
     243              : #endif
     244            0 :             break;
     245           32 :         case DLT_LOG_TO_FILE:
     246              :             /* log to file */
     247              : 
     248           32 :             if (dlt_is_log_in_multiple_files_active()) {
     249           24 :                 dlt_log_multiple_files_write(sFormatString, (unsigned int)sTimeSpec.tv_sec,
     250           12 :                                              (unsigned int)(sTimeSpec.tv_nsec / 1000), getpid(), asSeverity[prio], s);
     251              :             }
     252           20 :             else if (logging_handle) {
     253           40 :                 fprintf(logging_handle, sFormatString, (unsigned int)sTimeSpec.tv_sec,
     254           20 :                         (unsigned int)(sTimeSpec.tv_nsec / 1000), getpid(), asSeverity[prio], s);
     255           20 :                 fflush(logging_handle);
     256              :             }
     257              : 
     258              :             break;
     259              :         case DLT_LOG_DROPPED:
     260              :         default:
     261              :             break;
     262              :     }
     263              : 
     264              :     return DLT_RETURN_OK;
     265              : }
     266              : 
     267        84208 : DltReturnValue dlt_vlog(int prio, const char *format, ...)
     268              : {
     269        84208 :     char outputString[2048] = { 0 }; /* TODO: what is a reasonable string length here? */
     270              : 
     271              :     va_list args;
     272              : 
     273        84208 :     if (format == NULL)
     274              :         return DLT_RETURN_WRONG_PARAMETER;
     275              : 
     276        84208 :     if (logging_level < prio)
     277              :         return DLT_RETURN_OK;
     278              : 
     279        48109 :     va_start(args, format);
     280              :     vsnprintf(outputString, 2047, format, args);
     281        48109 :     va_end(args);
     282              : 
     283        48109 :     dlt_log(prio, outputString);
     284              : 
     285        48119 :     return DLT_RETURN_OK;
     286              : }
     287              : 
     288        21207 : DltReturnValue dlt_vnlog(int prio, size_t size, const char *format, ...)
     289              : {
     290              :     char *outputString = NULL;
     291              : 
     292              :     va_list args;
     293              : 
     294        21207 :     if (format == NULL)
     295              :         return DLT_RETURN_WRONG_PARAMETER;
     296              : 
     297        21207 :     if ((logging_level < prio) || (size == 0))
     298              :         return DLT_RETURN_OK;
     299              : 
     300        21207 :     if ((outputString = (char *)calloc(size + 1, sizeof(char))) == NULL)
     301              :         return DLT_RETURN_ERROR;
     302              : 
     303        21207 :     va_start(args, format);
     304              :     vsnprintf(outputString, size, format, args);
     305        21207 :     va_end(args);
     306              : 
     307        21207 :     dlt_log(prio, outputString);
     308              : 
     309        21207 :     free(outputString);
     310              :     outputString = NULL;
     311              : 
     312        21207 :     return DLT_RETURN_OK;
     313              : }
     314              : 
     315           12 : void dlt_log_multiple_files_write(const char* format, ...)
     316              : {
     317           12 :     char output_string[2048] = { 0 };
     318              :     va_list args;
     319           12 :     va_start (args, format);
     320              :     vsnprintf(output_string, 2047, format, args);
     321           12 :     va_end (args);
     322           12 :     multiple_files_buffer_write(&multiple_files_ring_buffer, (unsigned char*)output_string, strlen(output_string));
     323           12 : }
     324              : 
     325           15 : void dlt_log_free(void)
     326              : {
     327           15 :     if (logging_mode == DLT_LOG_TO_FILE) {
     328            5 :         if (dlt_is_log_in_multiple_files_active()) {
     329            3 :             dlt_log_free_multiple_logfiles();
     330              :         } else {
     331            2 :             dlt_log_free_single_logfile();
     332              :         }
     333              :     }
     334           15 : }
     335              : 
     336            2 : void dlt_log_free_single_logfile()
     337              : {
     338            2 :     if (logging_handle != NULL) {
     339            2 :         fclose(logging_handle);
     340              :     }
     341            2 : }
     342              : 
     343            3 : void dlt_log_free_multiple_logfiles()
     344              : {
     345            3 :     if (DLT_RETURN_ERROR == multiple_files_buffer_free(&multiple_files_ring_buffer)) return;
     346              : 
     347              :     // reset indicator of multiple files usage
     348            3 :     multiple_files_ring_buffer.ohandle = -1;
     349              : }
     350              : 
     351           37 : bool dlt_is_log_in_multiple_files_active()
     352              : {
     353           37 :     return multiple_files_ring_buffer.ohandle > -1;
     354              : }
        

Generated by: LCOV version 2.0-1