diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ce050b3b..06ec3cf98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,7 +56,7 @@ option(WITH_TESTSCRIPTS "Set to ON to run CMakeLists.txt in testscripts" option(WITH_GPROF "Set -pg to compile flags" OFF) option(WITH_DLTTEST "Set to ON to build with modifications to test User-Daemon communication with corrupt messages" OFF) option(WITH_DLT_SHM_ENABLE "EXPERIMENTAL! Set to ON to use shared memory as IPC. EXPERIMENTAL!" OFF) -option(WITH_DLT_ADAPTOR "Set to ON to build src/adaptor binaries" OFF) +option(WITH_DLT_ADAPTOR "Set to ON to build src/adaptor binaries" OFF) option(WITH_DLT_ADAPTOR_STDIN "Set to ON to build src/adaptor/stdin binaries" OFF) option(WITH_DLT_ADAPTOR_UDP "Set to ON to build src/adaptor/udp binaries" OFF) option(WITH_DLT_CONSOLE "Set to ON to build src/console binaries" ON) @@ -76,6 +76,7 @@ option(WITH_DLT_UNIT_TESTS "Set to ON to build gtest framework and tests/bina option(WITH_DLT_QNX_SYSTEM "Set to ON to build QNX system binary dlt-qnx-system" OFF) option(WITH_DLT_FILE_LOGGING_SYSLOG_FALLBACK "Set to ON to enable fallback to syslog if dlt logging to file fails" OFF) option(WITH_DLT_NETWORK_TRACE "Set to ON to enable network trace (if message queue is supported)" ON) +option(WITH_DLT_LOG_LEVEL_APP_CONFIG "Set to ON to enable default log levels based on application ids" OFF) set(DLT_IPC "FIFO" CACHE STRING "UNIX_SOCKET,FIFO") set(DLT_USER "genivi" CACHE STRING "Set user for process not run as root") @@ -295,6 +296,10 @@ else() set(DLT_JSON_LIBRARY "") endif() +if (WITH_DLT_LOG_LEVEL_APP_CONFIG) + add_definitions(-DDLT_LOG_LEVEL_APP_CONFIG) +endif() + add_subdirectory(doc) add_subdirectory(src) add_subdirectory(include) @@ -365,6 +370,7 @@ message(STATUS "WITH_LEGACY_INCLUDE_PATH = ${WITH_LEGACY_INCLUDE_PATH}") message(STATUS "WITH_EXTENDED_FILTERING = ${WITH_EXTENDED_FILTERING}") message(STATUS "WITH_DLT_DISABLE_MACRO = ${WITH_DLT_DISABLE_MACRO}") message(STATUS "WITH_DLT_FILE_LOGGING_SYSLOG_FALLBACK = ${WITH_DLT_FILE_LOGGING_SYSLOG_FALLBACK}" ) +message(STATUS "WITH_DLT_LOG_LEVEL_APP_CONFIG = ${WITH_DLT_LOG_LEVEL_APP_CONFIG}" ) message(STATUS "Change a value with: cmake -D=") message(STATUS "-------------------------------------------------------------------------------") message(STATUS) diff --git a/doc/dlt-daemon.1.md b/doc/dlt-daemon.1.md index 30fbbf14c..e30405ad4 100644 --- a/doc/dlt-daemon.1.md +++ b/doc/dlt-daemon.1.md @@ -6,7 +6,7 @@ # SYNOPSIS -**dlt-daemon** \[**-h**\] \[**-d**\] \[**-c** filename\] \[**-t** directory\] \[**-p** port\] +**dlt-daemon** \[**-h**\] \[**-d**\] \[**-c** filename\] \[**-t** directory\] \[**-p** port\] \[**-a** filename\] # DESCRIPTION @@ -41,6 +41,12 @@ GENIVI system or more likely on a external tester device. port need to be started with the environment variable DLT_DAEMON_TCP_PORT set appropriately. +-a + +: Load an alternative configuration for app id log level defaults. + By default, the configuration file /etc/dlt-log-levels.conf is loaded. + + # EXAMPLES Start DLT daemon in background mode: diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index c58587542..b8b480a2e 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -98,3 +98,8 @@ INSTALL(FILES dlt.conf DESTINATION ${CONFIGURATION_FILES_DIR} COMPONENT base) +if (WITH_DLT_LOG_LEVEL_APP_CONFIG) + INSTALL(FILES dlt-log-levels.conf + DESTINATION ${CONFIGURATION_FILES_DIR} + COMPONENT base) +endif() diff --git a/src/daemon/dlt-daemon.c b/src/daemon/dlt-daemon.c index e56381b7a..e5093479c 100644 --- a/src/daemon/dlt-daemon.c +++ b/src/daemon/dlt-daemon.c @@ -205,6 +205,11 @@ void usage() printf(" (Applications wanting to connect to a daemon using a custom\n"); printf(" port need to be started with the environment variable\n"); printf(" DLT_DAEMON_TCP_PORT set appropriately)\n"); +#ifdef DLT_LOG_LEVEL_APP_CONFIG + printf(" -a filename The filename for load default app id log levels (Default: " CONFIGURATION_FILES_DIR "/dlt-log-levels.conf)\n"); +#endif + +# } /* usage() */ /** @@ -213,6 +218,10 @@ void usage() int option_handling(DltDaemonLocal *daemon_local, int argc, char *argv[]) { int c; + char options[255]; + memset(options, 0, sizeof options); + const char *const default_options = "hdc:t:p:"; + strcpy(options, default_options); if (daemon_local == 0) { fprintf (stderr, "Invalid parameter passed to option_handling()\n"); @@ -236,12 +245,12 @@ int option_handling(DltDaemonLocal *daemon_local, int argc, char *argv[]) opterr = 0; #ifdef DLT_SHM_ENABLE - - while ((c = getopt (argc, argv, "hdc:t:s:p:")) != -1) -#else - - while ((c = getopt (argc, argv, "hdc:t:p:")) != -1) + strcpy(options + strlen(options), "s:"); #endif +#ifdef DLT_LOG_LEVEL_APP_CONFIG + strcpy(options + strlen(options), "a:"); +#endif + while ((c = getopt(argc, argv, options)) != -1) switch (c) { case 'd': { @@ -253,6 +262,13 @@ int option_handling(DltDaemonLocal *daemon_local, int argc, char *argv[]) strncpy(daemon_local->flags.cvalue, optarg, NAME_MAX); break; } +#ifdef DLT_LOG_LEVEL_APP_CONFIG + case 'a': + { + strncpy(daemon_local->flags.avalue, optarg, NAME_MAX); + break; + } +#endif #ifdef DLT_DAEMON_USE_FIFO_IPC case 't': { @@ -286,7 +302,11 @@ int option_handling(DltDaemonLocal *daemon_local, int argc, char *argv[]) } case '?': { - if ((optopt == 'c') || (optopt == 't') || (optopt == 'p')) + if ((optopt == 'c') || (optopt == 't') || (optopt == 'p') + #ifdef DLT_LOG_LEVEL_APP_CONFIG + || (optopt == 'a') + #endif + ) fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); @@ -835,6 +855,171 @@ int option_file_parser(DltDaemonLocal *daemon_local) return 0; } +#ifdef DLT_LOG_LEVEL_APP_CONFIG +/** + * Load configuration file parser + */ + +static int compare_app_id_conf(const void *lhs, const void *rhs) +{ + return strncmp(((DltDaemonContextLogSettings *)lhs)->apid, + ((DltDaemonContextLogSettings *)rhs)->apid, DLT_ID_SIZE); +} + +int app_id_default_log_level_config_parser(DltDaemon *daemon, + DltDaemonLocal *daemon_local) { + FILE *pFile; + char line[value_length - 1]; + char app_id_value[value_length]; + char ctx_id_value[value_length]; + DltLogLevelType log_level_value; + + char *pch; + const char *filename; + + /* open configuration file */ + filename = daemon_local->flags.avalue[0] + ? daemon_local->flags.avalue + : CONFIGURATION_FILES_DIR "/dlt-log-levels.conf"; + + pFile = fopen(filename, "r"); + if (pFile == NULL) { + dlt_vlog(LOG_WARNING, "Cannot open app log level configuration%s\n", filename); + return -errno; + } + + /* fetch lines from configuration file */ + while (fgets(line, value_length - 1, pFile) != NULL) { + pch = strtok(line, " "); + memset(app_id_value, 0, value_length); + memset(ctx_id_value, 0, value_length); + log_level_value = DLT_LOG_MAX; + + /* ignore comments and new lines*/ + if (strncmp(pch, "#", 1) == 0 || strncmp(pch, "\n", 1) == 0 + || strlen(pch) < 1) + continue; + + strncpy(app_id_value, pch, sizeof(app_id_value) - 1); + app_id_value[sizeof(app_id_value) - 1] = 0; + if (strlen(app_id_value) == 0 || strlen(app_id_value) > DLT_ID_SIZE) { + if (app_id_value[strlen(app_id_value) - 1] == '\n') { + dlt_vlog(LOG_WARNING, "Missing log level for apid %s in log settings\n", + app_id_value); + } else { + dlt_vlog(LOG_WARNING, + "Invalid apid for log settings settings: app id: %s\n", + app_id_value); + } + + continue; + } + + char *pch_next1 = strtok(NULL, " "); + char *pch_next2 = strtok(NULL, " "); + char *log_level; + /* no context id given, log level is next token */ + if (pch_next2 == NULL) { + log_level = pch_next1; + } else { + /* context id is given, log level is second to next token */ + log_level = pch_next2; + + /* next token is token id */ + strncpy(ctx_id_value, pch_next1, sizeof(ctx_id_value) - 1); + if (strlen(ctx_id_value) == 0 || strlen(app_id_value) > DLT_ID_SIZE) { + dlt_vlog(LOG_WARNING, + "Invalid ctxid for log settings: app id: %s " + "(skipping line)\n", + app_id_value); + continue; + } + + ctx_id_value[sizeof(ctx_id_value) - 1] = 0; + } + + errno = 0; + log_level_value = strtol(log_level, NULL, 10); + if (errno != 0 || log_level_value >= DLT_LOG_MAX || + log_level_value <= DLT_LOG_DEFAULT) { + dlt_vlog(LOG_WARNING, + "Invalid log level (%i), app id %s, conversion error: %s\n", + log_level_value, app_id_value, strerror(errno)); + continue; + } + + DltDaemonContextLogSettings *settings = + dlt_daemon_find_configured_app_id_ctx_id_settings( + daemon, app_id_value, NULL); + + if (settings != NULL && + strncmp(settings->ctid, ctx_id_value, DLT_ID_SIZE) == 0) { + if (strlen(ctx_id_value) > 0) { + dlt_vlog(LOG_WARNING, + "Appid %s with ctxid %s is already configured, skipping " + "duplicated entry\n", + app_id_value, ctx_id_value); + } else { + dlt_vlog(LOG_WARNING, + "Appid %s is already configured, skipping duplicated entry\n", + app_id_value); + } + + continue; + } + + /* allocate one more element in the trace load settings */ + DltDaemonContextLogSettings *tmp = + realloc(daemon->app_id_log_level_settings, + (++daemon->num_app_id_log_level_settings) * + sizeof(DltDaemonContextLogSettings)); + + if (tmp == NULL) { + dlt_log(LOG_CRIT, "Failed to allocate memory for app load settings\n"); + continue; + } + + daemon->app_id_log_level_settings = tmp; + + /* update newly created entry */ + settings = &daemon->app_id_log_level_settings + [daemon->num_app_id_log_level_settings -1]; + + memset(settings, 0, sizeof(DltDaemonContextLogSettings)); + memcpy(settings->apid, app_id_value, DLT_ID_SIZE); + memcpy(settings->ctid, ctx_id_value, DLT_ID_SIZE); + settings->log_level = log_level_value; + + /* make sure ids are 0 terminated for printing */ + char apid_buf[DLT_ID_SIZE + 1] = {0}; + char ctid_buf[DLT_ID_SIZE + 1] = {0}; + memcpy(apid_buf, app_id_value, DLT_ID_SIZE); + memcpy(ctid_buf, ctx_id_value, DLT_ID_SIZE); + + + /* list must be sorted to speed up dlt_daemon_find_configured_app_id_ctx_id_settings */ + qsort(daemon->app_id_log_level_settings, + daemon->num_app_id_log_level_settings, + sizeof(DltDaemonContextLogSettings), compare_app_id_conf); + + /* log with or without context id */ + if (strlen(ctid_buf) > 0) { + dlt_vlog( + LOG_INFO, + "Configured trace limits for app id %s, context id %s, level %u\n", + apid_buf, ctid_buf, log_level_value); + } else { + dlt_vlog(LOG_INFO, "Configured trace limits for app id %s, level %u\n", + apid_buf, log_level_value); + } + + } /* while */ + fclose(pFile); + + return 0; +} +#endif + static int dlt_mkdir_recursive(const char *dir) { int ret = 0; @@ -1042,6 +1227,15 @@ int main(int argc, char *argv[]) return -1; } +#ifdef DLT_LOG_LEVEL_APP_CONFIG + /* Load control app id level configuration file without setting `back` to + * prevent exit if file is missing */ + if (app_id_default_log_level_config_parser(&daemon, &daemon_local) < 0) { + dlt_vlog(LOG_WARNING, "app_id_default_log_level_config_parser() failed, " + "no app specific log levels will be configured\n"); + } +#endif + /* --- Daemon init phase 2 end --- */ if (daemon_local.flags.offlineLogstorageDirPath[0]) @@ -3223,8 +3417,19 @@ int dlt_daemon_process_user_message_log(DltDaemon *daemon, return DLT_DAEMON_ERROR_UNKNOWN; } +#ifdef DLT_LOG_LEVEL_APP_CONFIG + DltDaemonApplication *app = dlt_daemon_application_find( + daemon, daemon_local->msg.extendedheader->apid, daemon->ecuid, verbose); +#endif + /* discard non-allowed levels if enforcement is on */ - bool keep_message = enforce_context_ll_and_ts_keep_message(daemon_local); + bool keep_message = enforce_context_ll_and_ts_keep_message( + daemon_local +#ifdef DLT_LOG_LEVEL_APP_CONFIG + , app +#endif + ); + if (keep_message) dlt_daemon_client_send_message_to_all_client(daemon, daemon_local, verbose); @@ -3253,8 +3458,19 @@ int dlt_daemon_process_user_message_log(DltDaemon *daemon, return DLT_DAEMON_ERROR_UNKNOWN; } +#ifdef DLT_LOG_LEVEL_APP_CONFIG + DltDaemonApplication *app = dlt_daemon_application_find( + daemon, daemon_local->msg.extendedheader->apid, daemon->ecuid, verbose); +#endif + /* discard non-allowed levels if enforcement is on */ - bool keep_message = enforce_context_ll_and_ts_keep_message(daemon_local); + bool keep_message = enforce_context_ll_and_ts_keep_message( + daemon_local +#ifdef DLT_LOG_LEVEL_APP_CONFIG + , app +#endif + ); + if (keep_message) dlt_daemon_client_send_message_to_all_client(daemon, daemon_local, verbose); @@ -3276,16 +3492,29 @@ int dlt_daemon_process_user_message_log(DltDaemon *daemon, return DLT_DAEMON_ERROR_OK; } -bool enforce_context_ll_and_ts_keep_message(DltDaemonLocal *daemon_local) { - if (daemon_local->flags.enforceContextLLAndTS && - daemon_local->msg.extendedheader) { - const int mtin = DLT_GET_MSIN_MTIN(daemon_local->msg.extendedheader->msin); - if (mtin > daemon_local->flags.contextLogLevel) { - return false; +bool enforce_context_ll_and_ts_keep_message(DltDaemonLocal *daemon_local +# ifdef DLT_LOG_LEVEL_APP_CONFIG + , DltDaemonApplication *app +# endif +) +{ + if (!daemon_local->flags.enforceContextLLAndTS || + !daemon_local->msg.extendedheader) { + return true; } - } - return true; + const int mtin = DLT_GET_MSIN_MTIN(daemon_local->msg.extendedheader->msin); +#ifdef DLT_LOG_LEVEL_APP_CONFIG + if (app->num_context_log_level_settings > 0) { + DltDaemonContextLogSettings *log_settings = + dlt_daemon_find_app_log_level_config(app, daemon_local->msg.extendedheader->ctid); + + if (log_settings != NULL) { + return mtin <= log_settings->log_level; + } + } +#endif + return mtin <= daemon_local->flags.contextLogLevel; } int dlt_daemon_process_user_message_set_app_ll_ts(DltDaemon *daemon, diff --git a/src/daemon/dlt-daemon.h b/src/daemon/dlt-daemon.h index cc879cb64..b6274d516 100644 --- a/src/daemon/dlt-daemon.h +++ b/src/daemon/dlt-daemon.h @@ -99,6 +99,9 @@ typedef struct char yvalue[NAME_MAX + 1]; /**< (String: Devicename) Additional support for serial device */ char ivalue[NAME_MAX + 1]; /**< (String: Directory) Directory where to store the persistant configuration (Default: /tmp) */ char cvalue[NAME_MAX + 1]; /**< (String: Directory) Filename of DLT configuration file (Default: /etc/dlt.conf) */ +#ifdef DLT_LOG_LEVEL_APP_CONFIG + char avalue[NAME_MAX + 1]; /**< (String: Directory) Filename of the app id default level config (Default: /etc/dlt-log-levels.conf) */ +#endif int sharedMemorySize; /**< (int) Size of shared memory (Default: 100000) */ int sendMessageTime; /**< (Boolean) Send periodic Message Time if client is connected (Default: 0) */ char offlineTraceDirectory[DLT_DAEMON_FLAG_MAX]; /**< (String: Directory) Store DLT messages to local directory (Default: /etc/dlt.conf) */ @@ -255,7 +258,11 @@ int dlt_daemon_process_user_message_log(DltDaemon *daemon, DltReceiver *rec, int verbose); -bool enforce_context_ll_and_ts_keep_message(DltDaemonLocal *daemon_local); +bool enforce_context_ll_and_ts_keep_message(DltDaemonLocal *daemon_local +# ifdef DLT_LOG_LEVEL_APP_CONFIG + ,DltDaemonApplication *app +# endif + ); int dlt_daemon_process_user_message_set_app_ll_ts(DltDaemon *daemon, DltDaemonLocal *daemon_local, diff --git a/src/daemon/dlt-log-levels.conf b/src/daemon/dlt-log-levels.conf new file mode 100644 index 000000000..9bb555afd --- /dev/null +++ b/src/daemon/dlt-log-levels.conf @@ -0,0 +1,13 @@ +# Configuration for default log levels. +# APPIDs in this configuration file overwrite the global ContextLogLevel level from dlt.conf +# It can be used to prevent single applications from logging (for example due to logging sensitive data) +# or to disable file transfers from an application etc. +# Furthermore single applications can use a higher log level than the default. +# If the context id is empty, the configuration will be valid for all app ids +# !!!! +# Note: this file is space separated, and wildcards are not supported +# !!!! +# DLT_LOG_OFF = 0, DLT_LOG_FATAL = 1, DLT_LOG_ERROR = 2, DLT_LOG_WARN = 3, DLT_LOG_INFO = 4, DLT_LOG_DEBUG = 5, DLT_LOG_VERBOSE = 6 +# APID [CTID] LogLevel +FOO BAR 3 +TEST 3 diff --git a/src/daemon/dlt_daemon_client.c b/src/daemon/dlt_daemon_client.c index 9ebbd2390..7e1bb3a35 100644 --- a/src/daemon/dlt_daemon_client.c +++ b/src/daemon/dlt_daemon_client.c @@ -2056,13 +2056,15 @@ void dlt_daemon_control_set_all_log_level(int sock, /* No endianess conversion necessary */ if ((req != NULL) && ((req->log_level <= DLT_LOG_VERBOSE) || (req->log_level == (uint8_t)DLT_LOG_DEFAULT))) { - if (daemon_local->flags.enforceContextLLAndTS) - loglevel = getStatus(req->log_level, daemon_local->flags.contextLogLevel); - else - loglevel = (int8_t) req->log_level; /* No endianess conversion necessary */ + loglevel = (int8_t) req->log_level; /* Send Update to all contexts using the new log level */ - dlt_daemon_user_send_all_log_level_update(daemon, loglevel, verbose); + dlt_daemon_user_send_all_log_level_update( + daemon, + daemon_local->flags.enforceContextLLAndTS, + (int8_t)daemon_local->flags.contextLogLevel, + loglevel, + verbose); dlt_daemon_control_service_response(sock, daemon, daemon_local, id, DLT_SERVICE_RESPONSE_OK, verbose); } diff --git a/src/daemon/dlt_daemon_common.c b/src/daemon/dlt_daemon_common.c index 6ba5935dc..c6ca9040b 100644 --- a/src/daemon/dlt_daemon_common.c +++ b/src/daemon/dlt_daemon_common.c @@ -141,6 +141,92 @@ DltDaemonRegisteredUsers *dlt_daemon_find_users_list(DltDaemon *daemon, dlt_vlog(LOG_ERR, "Cannot find user list for ECU: %4s\n", ecu); return (DltDaemonRegisteredUsers *)NULL; } + +#ifdef DLT_LOG_LEVEL_APP_CONFIG + +static int dlt_daemon_cmp_log_settings(const void *lhs, const void *rhs) { + if ((lhs == NULL) || (rhs == NULL)) + return -1; + + DltDaemonContextLogSettings *settings1 = (DltDaemonContextLogSettings *)lhs; + DltDaemonContextLogSettings *settings2 = (DltDaemonContextLogSettings *)rhs; + + int cmp = memcmp(settings1->apid, settings2->apid, DLT_ID_SIZE); + + if (cmp < 0) + return -1; + else if (cmp == 0) + return memcmp(settings1->ctid, settings2->ctid, DLT_ID_SIZE); + else + return 1; +} + +/** + * Find configuration for app/ctx id specific log settings configuration + * @param daemon pointer to dlt daemon struct + * @param apid application id to use + * @param ctid context id to use, can be NULL + * @return pointer to log settings if found, otherwise NULL + */ +DltDaemonContextLogSettings *dlt_daemon_find_configured_app_id_ctx_id_settings( + const DltDaemon *daemon, const char *apid, const char *ctid) { + DltDaemonContextLogSettings *app_id_settings = NULL; + for (int i = 0; i < daemon->num_app_id_log_level_settings; ++i) { + DltDaemonContextLogSettings *settings = &daemon->app_id_log_level_settings[i]; + + if (strncmp(apid, settings->apid, DLT_ID_SIZE) != 0) { + if (app_id_settings != NULL) + return app_id_settings; + continue; + } + + if (strlen(settings->ctid) == 0) { + app_id_settings = settings; + } + + if (ctid == NULL || strlen(ctid) == 0) { + if (app_id_settings != NULL) { + return app_id_settings; + } + } else { + if (strncmp(ctid, settings->ctid, DLT_ID_SIZE) == 0) { + return settings; + } + } + } + + return app_id_settings; +} + +/** + * Find configured log levels in a given DltDaemonApplication for the passed context id. + * @param app The application settings which contain the previously loaded ap id settings + * @param ctid The context id to find. + * @return Pointer to DltDaemonApplicationLogSettings containing the log level + * for the requested application or NULL if none found. + */ +DltDaemonContextLogSettings *dlt_daemon_find_app_log_level_config( + const DltDaemonApplication *const app, const char *const ctid) { + + if (NULL == ctid) + return NULL; + + DltDaemonContextLogSettings settings; + memcpy(settings.apid, app->apid, DLT_ID_SIZE); + memcpy(settings.ctid, ctid, DLT_ID_SIZE); + + DltDaemonContextLogSettings* log_settings = NULL; + log_settings = + (DltDaemonContextLogSettings *)bsearch( + &settings, app->context_log_level_settings, + (size_t)app->num_context_log_level_settings, + sizeof(DltDaemonContextLogSettings), + dlt_daemon_cmp_log_settings); + return log_settings; +} + +#endif + int dlt_daemon_init_runtime_configuration(DltDaemon *daemon, const char *runtime_directory, int verbose) { PRINT_FUNCTION_VERBOSE(verbose); @@ -270,6 +356,12 @@ int dlt_daemon_free(DltDaemon *daemon, int verbose) free(daemon->user_list); +#ifdef DLT_LOG_LEVEL_APP_CONFIG + if (daemon->app_id_log_level_settings != NULL) { + free(daemon->app_id_log_level_settings); + } +#endif + if (app_recv_buffer) free(app_recv_buffer); @@ -368,6 +460,12 @@ int dlt_daemon_applications_clear(DltDaemon *daemon, char *ecu, int verbose) for (i = 0; i < user_list->num_applications; i++) if (user_list->applications[i].application_description != NULL) { + +#ifdef DLT_LOG_LEVEL_APP_CONFIG + if (user_list->applications[i].context_log_level_settings) + free(user_list->applications[i].context_log_level_settings); +#endif + free(user_list->applications[i].application_description); user_list->applications[i].application_description = NULL; } @@ -568,6 +666,11 @@ DltDaemonApplication *dlt_daemon_application_add(DltDaemon *daemon, application = dlt_daemon_application_find(daemon, apid, ecu, verbose); } +#ifdef DLT_LOG_LEVEL_APP_CONFIG + application->num_context_log_level_settings = 0; + application->context_log_level_settings = NULL; +#endif + return application; } @@ -890,19 +993,53 @@ DltDaemonContext *dlt_daemon_context_add(DltDaemon *daemon, } } +#ifdef DLT_LOG_LEVEL_APP_CONFIG + /* configure initial log level */ + DltDaemonContextLogSettings *settings = NULL; + settings = dlt_daemon_find_configured_app_id_ctx_id_settings( + daemon, context->apid, ctid); + + if (settings != NULL) { + /* set log level */ + log_level = settings->log_level; + + DltDaemonContextLogSettings *ct_settings = NULL; + ct_settings = dlt_daemon_find_app_log_level_config(application, ctid); + + /* ct_settings != null: context and app id combination already exists */ + if (ct_settings == NULL) { + /* copy the configuration into the DltDaemonApplication for faster access later */ + DltDaemonContextLogSettings *tmp = + realloc(application->context_log_level_settings, + (++application->num_context_log_level_settings) * + sizeof(DltDaemonContextLogSettings)); + application->context_log_level_settings = tmp; + + ct_settings = + &application->context_log_level_settings[application->num_context_log_level_settings - 1]; + memcpy(ct_settings, settings, sizeof(DltDaemonContextLogSettings)); + memcpy(ct_settings->ctid, ctid, DLT_ID_SIZE); + } + } +#endif + if ((strncmp(daemon->ecuid, ecu, DLT_ID_SIZE) == 0) && (daemon->force_ll_ts)) { - if (log_level > daemon->default_log_level) - log_level = daemon->default_log_level; +#ifdef DLT_LOG_LEVEL_APP_CONFIG + if (log_level > daemon->default_log_level && settings == NULL) +#else + if (log_level > daemon->default_log_level) +#endif + log_level = daemon->default_log_level; - if (trace_status > daemon->default_trace_status) - trace_status = daemon->default_trace_status; + if (trace_status > daemon->default_trace_status) + trace_status = daemon->default_trace_status; - dlt_vlog(LOG_NOTICE, - "Adapting ll_ts for context: %.4s:%.4s with %i %i\n", - apid, - ctid, - log_level, - trace_status); + dlt_vlog(LOG_NOTICE, + "Adapting ll_ts for context: %.4s:%.4s with %i %i\n", + apid, + ctid, + log_level, + trace_status); } /* Store log level and trace status, @@ -939,6 +1076,45 @@ DltDaemonContext *dlt_daemon_context_add(DltDaemon *daemon, return context; } +#ifdef DLT_LOG_LEVEL_APP_CONFIG +static void dlt_daemon_free_context_log_settings( + DltDaemonApplication *application, + DltDaemonContext *context) +{ + + + DltDaemonContextLogSettings *ct_settings; + int i; + int skipped = 0; + + ct_settings = dlt_daemon_find_app_log_level_config(application, context->ctid); + if (ct_settings == NULL) { + return; + } + + /* move all data forward */ + for (i = 0; i < application->num_context_log_level_settings; ++i) { + /* skip given context to delete it */ + if (i + skipped < application->num_context_log_level_settings && + strncmp(application->context_log_level_settings[i+skipped].ctid, context->ctid, DLT_ID_SIZE) == 0) { + ++skipped; + continue; + } + + memcpy(&application->context_log_level_settings[i-skipped], + &application->context_log_level_settings[i], + sizeof(DltDaemonContextLogSettings)); + } + + application->num_context_log_level_settings -= skipped; + + /* if size is equal to zero, and ptr is not NULL, then realloc is equivalent to free(ptr) */ + application->context_log_level_settings = realloc(application->context_log_level_settings, + sizeof(DltDaemonContextLogSettings) * (application->num_context_log_level_settings)); + +} +#endif + int dlt_daemon_context_del(DltDaemon *daemon, DltDaemonContext *context, char *ecu, @@ -961,6 +1137,9 @@ int dlt_daemon_context_del(DltDaemon *daemon, if (user_list->num_contexts > 0) { application = dlt_daemon_application_find(daemon, context->apid, ecu, verbose); +#ifdef DLT_LOG_LEVEL_APP_CONFIG + dlt_daemon_free_context_log_settings(application, context); +#endif /* Free description of context to be deleted */ if (context->context_description) { free(context->context_description); @@ -1512,7 +1691,11 @@ void dlt_daemon_user_send_default_update(DltDaemon *daemon, int verbose) } } -void dlt_daemon_user_send_all_log_level_update(DltDaemon *daemon, int8_t log_level, int verbose) +void dlt_daemon_user_send_all_log_level_update(DltDaemon *daemon, + int enforce_context_ll_and_ts, + int8_t context_log_level, + int8_t log_level, + int verbose) { int32_t count = 0; DltDaemonContext *context = NULL; @@ -1535,6 +1718,22 @@ void dlt_daemon_user_send_all_log_level_update(DltDaemon *daemon, int8_t log_lev if (context->user_handle >= DLT_FD_MINIMUM) { context->log_level = log_level; + if (enforce_context_ll_and_ts) { +#ifdef DLT_LOG_LEVEL_APP_CONFIG + DltDaemonContextLogSettings *settings = + dlt_daemon_find_configured_app_id_ctx_id_settings( + daemon, context->apid, context->ctid); + if (settings != NULL) { + if (log_level > settings->log_level) { + context->log_level = settings->log_level; + } + } else +#endif + if (log_level > context_log_level) { + context->log_level = (int8_t)context_log_level; + } + } + if (dlt_daemon_user_send_log_level(daemon, context, verbose) == -1) diff --git a/src/daemon/dlt_daemon_common.h b/src/daemon/dlt_daemon_common.h index f650ce31e..1f8f13a35 100644 --- a/src/daemon/dlt_daemon_common.h +++ b/src/daemon/dlt_daemon_common.h @@ -125,6 +125,18 @@ typedef enum DLT_DAEMON_STATE_SEND_DIRECT = 4 /**< External logger is connected or internal logging is active, and buffer is empty */ } DltDaemonState; +#ifdef DLT_LOG_LEVEL_APP_CONFIG +/* + * The parameter of level per app and context id settings + */ +typedef struct +{ + char apid[DLT_ID_SIZE]; /**< Application id for which the settings are valid */ + char ctid[DLT_ID_SIZE]; /**< Context id for which the settings are valid, empty if valid for all ap ids */ + DltLogLevelType log_level; /**< Log level to use */ +} DltDaemonContextLogSettings; +#endif + /** * The parameters of a daemon application. */ @@ -136,6 +148,10 @@ typedef struct bool owns_user_handle; /**< user_handle should be closed when reset */ char *application_description; /**< context description */ int num_contexts; /**< number of contexts for this application */ +#ifdef DLT_LOG_LEVEL_APP_CONFIG + DltDaemonContextLogSettings *context_log_level_settings; + int num_context_log_level_settings; +#endif } DltDaemonApplication; /** @@ -191,6 +207,10 @@ typedef struct DltDaemonState state; /**< the current logging state of dlt daemon. */ DltLogStorage *storage_handle; int maintain_logstorage_loglevel; /* Permission to maintain the logstorage loglevel*/ +#ifdef DLT_LOG_LEVEL_APP_CONFIG + DltDaemonContextLogSettings *app_id_log_level_settings; /**< Settings for app id specific log levels */ + int num_app_id_log_level_settings; /** < count of log level settings */ +#endif } DltDaemon; /** @@ -246,6 +266,32 @@ int dlt_daemon_init_user_information(DltDaemon *daemon, DltDaemonRegisteredUsers *dlt_daemon_find_users_list(DltDaemon *daemon, char *ecu, int verbose); + +#ifdef DLT_LOG_LEVEL_APP_CONFIG + +/** + * Find configuration for app/ctx id specific log settings configuration + * @param daemon pointer to dlt daemon struct + * @param apid application id to use + * @param ctid context id to use, can be NULL + * @return pointer to log settings if found, otherwise NULL + */ +DltDaemonContextLogSettings *dlt_daemon_find_configured_app_id_ctx_id_settings( + const DltDaemon *daemon, const char *apid, const char *ctid); + + +/** + * Find configured log levels in a given DltDaemonApplication for the passed context id. + * @param app The application settings which contain the previously loaded ap id settings + * @param ctid The context id to find. + * @return Pointer to DltDaemonApplicationLogSettings containing the log level + * for the requested application or NULL if none found. + */ +DltDaemonContextLogSettings *dlt_daemon_find_app_log_level_config( + const DltDaemonApplication *app, const char *ctid); + +#endif + /** * Init the user saved configurations to daemon. * Since the order of loading runtime config could be different, @@ -472,10 +518,17 @@ void dlt_daemon_user_send_default_update(DltDaemon *daemon, int verbose); /** * Send user messages to all user applications context to update with the new log level * @param daemon pointer to dlt daemon structure + * @param enforce_context_ll_and_ts defines if enforcement of log levels is on + * @param context_log_level the log level of the context * @param log_level new log level to be set * @param verbose if set to true verbose information is printed out. */ -void dlt_daemon_user_send_all_log_level_update(DltDaemon *daemon, int8_t log_level, int verbose); +void dlt_daemon_user_send_all_log_level_update(DltDaemon *daemon, + int enforce_context_ll_and_ts, + int8_t context_log_level, + int8_t log_level, + int verbose); + /** * Send user messages to all user applications context to update with the new trace status