summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorStefan Vacek <stefan.vacek@intel.com>2015-08-26 17:28:54 +0200
committerAlexander Wenzel <Alexander.AW.Wenzel@bmw.de>2015-10-07 10:35:41 +0200
commitc3b53f8805236cb7c72eb62ef04866f34de33103 (patch)
tree956eec44e2d0b2ec309904f15321565a3fae4e3d /src/lib
parent2f334a851fa1b39cab74724f3d0a0565f86c27b4 (diff)
downloadDLT-daemon-c3b53f8805236cb7c72eb62ef04866f34de33103.tar.gz
Add env-var to set initial log-levels
name of environment variable: DLT_INITIAL_LOG_LEVEL Syntax: <apid1>:<ctid1>:<loglevel1>;<apid2>:<ctid2>:<loglevel2>;... apid: application id (up to 4 chars), if empty all applications will match ctid: context id (up to 4 chars), if empty all contexts will match loglevel: either -1..6 or a symbolic name (default, off, fatal, error, warning, info, debug, verbose) Examples: DLT_INITIAL_LOG_LEVEL=TEST:LOG:0 -> turn off logging for appid TEST and contextid LOG DLT_INITIAL_LOG_LEVEL=:LOG:warn -> for contexts with name "LOG" set log-level to warning (3) DLT_INITIAL_LOG_LEVEL=::VERBOSE -> set log-level of all contexts to VERBOSE DLT_INITIAL_LOG_LEVEL=::VERBOSE;TEST:LOG:3 -> set log-level of all contexts to VERBOSE except TEST:LOG, set this to WARNING dlt-example-user: add option -l to specify log-level to be used when sending messages Signed-off-by: Stefan Vacek <stefan.vacek@intel.com>
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/CMakeLists.txt2
-rw-r--r--src/lib/dlt_env_ll.c560
-rw-r--r--src/lib/dlt_user.c42
3 files changed, 583 insertions, 21 deletions
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index 11f314b..02b39fe 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -15,7 +15,7 @@
# @licence end@
#######
-set(dlt_LIB_SRCS dlt_user dlt_client dlt_filetransfer ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c)
+set(dlt_LIB_SRCS dlt_user dlt_client dlt_filetransfer dlt_env_ll ${CMAKE_SOURCE_DIR}/src/shared/dlt_common.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_user_shared.c ${CMAKE_SOURCE_DIR}/src/shared/dlt_shm.c)
add_library(dlt ${dlt_LIB_SRCS})
target_link_libraries(dlt rt ${CMAKE_THREAD_LIBS_INIT})
diff --git a/src/lib/dlt_env_ll.c b/src/lib/dlt_env_ll.c
new file mode 100644
index 0000000..d2ef7b1
--- /dev/null
+++ b/src/lib/dlt_env_ll.c
@@ -0,0 +1,560 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2015 Intel Corporation
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ * Contributions are licensed to the GENIVI Alliance under one or more
+ * Contribution License Agreements.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Stefan Vacek <stefan.vacek@intel.com> Intel Corporation
+ *
+ * \file dlt_env_ll.c
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+#include "dlt_user.h"
+#include <string.h>
+#include <stdlib.h>
+
+#define DLT_ENV_LL_SET_INCREASE 10
+
+
+/* a generic entry looks like:
+ * ll_item ::= apid:ctid:ll
+ * ll_set ::= ll_item |
+ * ll_set;ll_item
+ */
+
+/**
+ * @brief extract id out of given string
+ *
+ * Extract 4-byte string out of given environment string, the pointer of the
+ * environment string is moved to the next un-used character and the extracted
+ * id is copied into \param id
+ *
+ * Example:
+ * env[] = "abcd:1234:3"
+ * char res[4u];
+ * char * tmp = &env[0];
+ * int ret = extract_id(&tmp, res);
+ * assert(ret == 0);
+ * assert(*tmp == ':');
+ * assert(res[3] == 'd');
+ *
+ * @return 0 if successful, -1 else
+ */
+int dlt_env_extract_id(char ** const env, char * id)
+{
+ int i;
+ if (!env || !id)
+ {
+ return -1;
+ }
+
+ if (!(*env))
+ {
+ return -1;
+ }
+
+ memset(id, 0, 4);
+
+ for (i = 0; (i<4) && (**env != ':') && (**env != 0); ++i)
+ {
+ *id++ = *((*env)++);
+ }
+
+ /* the next/last character must be ':' */
+ if ((0 != **env) && (':' == **env))
+ {
+ return 0;
+ }
+
+ return -1;
+}
+
+
+/**
+ * @brief convert a given string to lower-case
+ *
+ * Stops end of string or if ';' is detected
+ */
+int dlt_env_helper_to_lower(char ** const env, char *result, int const res_len)
+{
+ int count = 0;
+ char ch = *(*env);
+
+ if (!env || !result)
+ {
+ return -1;
+ }
+
+ if (!(*env))
+ {
+ return -1;
+ }
+
+ count = 0;
+ ch = *(*env);
+ while (ch && (count < res_len-1) && (ch != ';'))
+ {
+ if (ch >= 'A' && ch <= 'Z')
+ {
+ result[count] = ch + 'a' - 'A';
+ }
+ else
+ {
+ result[count] = ch;
+ }
+ ch = *(++(*env));
+ ++count;
+ }
+
+ result[count] = 0;
+ if (!ch || (ch == ';')) /* full input was parsed */
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+
+int dlt_env_extract_symbolic_ll(char ** const env, int8_t * ll)
+{
+ char result[strlen("verbose")+1];
+ if (!env || !ll)
+ {
+ return -1;
+ }
+
+ if (!(*env))
+ {
+ return -1;
+ }
+
+ if (dlt_env_helper_to_lower(env, &result[0], sizeof(result)) == 0)
+ {
+ if (strncmp("default", result, sizeof(result)) == 0)
+ {
+ *ll = -1;
+ }
+ else if (strncmp("off", result, sizeof(result)) == 0)
+ {
+ *ll = 0;
+ }
+ else if (strncmp("fatal", result, sizeof(result)) == 0)
+ {
+ *ll = 1;
+ }
+ else if (strncmp("error", result, sizeof(result)) == 0)
+ {
+ *ll = 2;
+ }
+ else if (strncmp("warning", result, sizeof(result)) == 0)
+ {
+ *ll = 3;
+ }
+ else if (strncmp("info", result, sizeof(result)) == 0)
+ {
+ *ll = 4;
+ }
+ else if (strncmp("debug", result, sizeof(result)) == 0)
+ {
+ *ll = 5;
+ }
+ else if (strncmp("verbose", result, sizeof(result)) == 0)
+ {
+ *ll = 6;
+ }
+ else
+ {
+ return -1;
+ }
+
+ if (**env != 0)
+ {
+ (*env)++;
+ }
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+
+}
+
+
+/**
+ * @brief extract log-level out of given string
+ *
+ * A valid log-level is a numeric value in the range of -1 .. 6, with:
+ * -1: default
+ * 0: off
+ * 1: fatal
+ * 2: error
+ * 3: warning
+ * 4: info
+ * 5: debug
+ * 6: verbose
+ * During parsing, the environment string is moved to the next un-used character and the extracted
+ * log-level is written into \param ll
+ *
+ * Example:
+ * env[] = "abcd:1234:6"
+ * int ll;
+ * char ** tmp = &env[10]; // tmp points to '6'!
+ * int ret = extract_ll(&tmp, &ll);
+ * assert(ret == 0);
+ * assert(*tmp == NULL);
+ * assert(ll == 6);
+ *
+ * @return 0 if successful, -1 else
+ */
+int dlt_env_extract_ll(char ** const env, int8_t * ll)
+{
+ if (!env || !ll)
+ {
+ return -1;
+ }
+
+ if (!(*env))
+ {
+ return -1;
+ }
+
+ /* extract number */
+ if (**env == '-')
+ {
+ (*env)++;
+ if (**env == '1')
+ {
+ *ll = -1;
+ (*env)++;
+ }
+ }
+ else
+ {
+ if ((**env >= '0') && (**env < '7'))
+ {
+ *ll = **env - '0';
+ (*env)++;
+ }
+ else
+ {
+ if (dlt_env_extract_symbolic_ll(env, ll) != 0)
+ {
+ return -1;
+ }
+ }
+ }
+
+ /* check end, either next char is NULL or ';' */
+ if ((**env == ';') || (**env == 0))
+ {
+ return 0;
+ }
+
+ return -1;
+}
+
+
+/**
+ * @brief extract one item out of string
+ *
+ * @return 0 if successful, -1 else
+ */
+int dlt_env_extract_ll_item(char ** const env, dlt_env_ll_item * const item)
+{
+ int ret = -1;
+ if (!env || !item)
+ {
+ return -1;
+ }
+
+ if (!(*env))
+ {
+ return -1;
+ }
+
+ memset(item, 0, sizeof(dlt_env_ll_item));
+ ret = dlt_env_extract_id(env, item->appId);
+ if (ret == -1)
+ {
+ return -1;
+ }
+
+ (*env)++;
+ ret = dlt_env_extract_id(env, item->ctxId);
+ if (ret == -1)
+ {
+ return -1;
+ }
+
+ (*env)++;
+ ret = dlt_env_extract_ll(env, &item->ll);
+ if (ret == -1)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/**
+ * @brief initialize ll_set
+ *
+ * Must call release_ll_set before exit to release all memory
+ *
+ * @return -1 if memory could not be allocated
+ * @return 0 on success
+ */
+int dlt_env_init_ll_set(dlt_env_ll_set * const ll_set)
+{
+ if (!ll_set)
+ {
+ return -1;
+ }
+
+ ll_set->array_size = DLT_ENV_LL_SET_INCREASE;
+ ll_set->item = (dlt_env_ll_item *)malloc(sizeof(dlt_env_ll_item) * ll_set->array_size);
+ if (!ll_set->item)
+ {
+ /* should trigger a warning: no memory left */
+ ll_set->array_size = 0;
+ return -1;
+ }
+ ll_set->num_elem = 0u;
+ return 0;
+}
+
+
+/**
+ * @brief release ll_set
+ */
+void dlt_env_free_ll_set(dlt_env_ll_set * const ll_set)
+{
+ if (!ll_set)
+ {
+ return;
+ }
+
+ free(ll_set->item);
+ ll_set->item = NULL;
+ ll_set->array_size = 0u;
+ ll_set->num_elem = 0u;
+}
+
+
+/**
+ * @brief increase size of ll_set by LL_SET_INCREASE elements
+ *
+ * @return -1 if memory could not be allocated
+ * @return 0 on success
+ */
+int dlt_env_increase_ll_set(dlt_env_ll_set * const ll_set)
+{
+ dlt_env_ll_item * old_set;
+ size_t old_size;
+
+ if (!ll_set)
+ {
+ return -1;
+ }
+
+ old_set = ll_set->item;
+ old_size = ll_set->array_size;
+
+ ll_set->array_size += DLT_ENV_LL_SET_INCREASE;
+ ll_set->item = (dlt_env_ll_item *)malloc(sizeof(dlt_env_ll_item) * ll_set->array_size);
+ if (!ll_set->item)
+ {
+ /* should trigger a warning: no memory left */
+ ll_set->array_size -= DLT_ENV_LL_SET_INCREASE;
+ return -1;
+ }
+ else
+ {
+ memcpy(ll_set->item, old_set, sizeof(dlt_env_ll_item)*old_size);
+ free(old_set);
+ return 0;
+ }
+}
+
+
+/**
+ * @brief extract all items out of string
+ *
+ * The given set is initialized within this function (memory is allocated).
+ * Make sure, that the caller frees this memory when it is no longer needed!
+ *
+ * @return 0 if successful, -1 else
+ */
+int dlt_env_extract_ll_set(char ** const env, dlt_env_ll_set * const ll_set)
+{
+ if (!env || !ll_set)
+ {
+ return -1;
+ }
+
+ if (!(*env))
+ {
+ return -1;
+ }
+
+ if (dlt_env_init_ll_set(ll_set) == -1)
+ {
+ return -1;
+ }
+
+ do
+ {
+ if (ll_set->num_elem == ll_set->array_size)
+ {
+ if (dlt_env_increase_ll_set(ll_set) == -1)
+ {
+ return -1;
+ }
+ }
+
+ if (dlt_env_extract_ll_item(env, &ll_set->item[ll_set->num_elem++]) == -1)
+ {
+ return -1;
+ }
+ if (**env == ';')
+ {
+ (*env)++;
+ }
+ } while (**env != 0);
+
+ return 0;
+}
+
+
+/**
+ * @brief check if two ids match
+ *
+ * @return 1 if matching, 0 if not
+ */
+int dlt_env_ids_match(char const * const a, char const * const b)
+{
+ if (a[0] != b[0])
+ {
+ return 0;
+ }
+ if (a[1] != b[1])
+ {
+ return 0;
+ }
+ if (a[2] != b[2])
+ {
+ return 0;
+ }
+ if (a[3] != b[3])
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+
+/**
+ * @brief check if (and how) apid and ctid match with given item
+ *
+ * Resulting priorities:
+ * - no apid, no ctid only ll given in item: use ll with prio 1
+ * - no apid, ctid matches: use ll with prio 2
+ * - no ctid, apid matches: use ll with prio 3
+ * - apid, ctid matches: use ll with prio 4
+ *
+ * In case of error, -1 is returned.
+ */
+int dlt_env_ll_item_get_matching_prio(dlt_env_ll_item const * const item, char const * const apid, char const * const ctid)
+{
+ if ((!item) || (!apid) || (!ctid))
+ {
+ return -1;
+ }
+
+ if (item->appId[0] == 0)
+ {
+ if (item->ctxId[0] == 0)
+ {
+ return 1;
+ }
+ else
+ {
+ if (dlt_env_ids_match(item->ctxId, ctid))
+ {
+ return 2;
+ }
+ }
+ }
+ else
+ {
+ if (dlt_env_ids_match(item->appId, apid))
+ {
+ if (item->ctxId[0] == 0)
+ {
+ return 3;
+ }
+ else if (dlt_env_ids_match(item->ctxId, ctid))
+ {
+ return 4;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+/**
+ * @brief adjust log-level based on values given through environment
+ *
+ * Iterate over the set of items, and find the best match (\see ll_item_get_matching_prio)
+ * For any item that matches, the one with the highest priority is selected and that
+ * log-level is returned.
+ *
+ * If no item matches or in case of error, the original log-level (\param ll) is returned
+ */
+int dlt_env_adjust_ll_from_env(dlt_env_ll_set const * const ll_set, char const * const apid, char const * const ctid, int const ll)
+{
+ if ((!ll_set) || (!apid) || (!ctid))
+ {
+ return ll;
+ }
+
+ int res = ll;
+ int prio = 0; /* no match so far */
+ size_t i;
+ for (i = 0; i<ll_set->num_elem; ++i)
+ {
+ int p = dlt_env_ll_item_get_matching_prio(&ll_set->item[i], apid, ctid);
+ if (p > prio)
+ {
+ prio = p;
+ res = ll_set->item[i].ll;
+ if (p == 4) /* maximum reached, immediate return */
+ {
+ return res;
+ }
+ }
+ }
+
+ return res;
+}
+
+
diff --git a/src/lib/dlt_user.c b/src/lib/dlt_user.c
index e1f46ca..e4d13bb 100644
--- a/src/lib/dlt_user.c
+++ b/src/lib/dlt_user.c
@@ -411,6 +411,7 @@ int dlt_init_message_queue(void)
int dlt_init_common(void)
{
char *env_local_print;
+ char * env_initial_log_level;
/* Binary semaphore for threads */
if (sem_init(&dlt_mutex, 0, 1)==-1)
@@ -467,6 +468,16 @@ int dlt_init_common(void)
}
}
+ env_initial_log_level = getenv("DLT_INITIAL_LOG_LEVEL");
+ if( env_initial_log_level != NULL )
+ {
+ if (dlt_env_extract_ll_set(&env_initial_log_level, &dlt_user.initial_ll_set) != 0)
+ {
+ snprintf(str, DLT_USER_BUFFER_LENGTH, "Unable to parse initial set of log-levels from environment! Env:\n%s\n", getenv("DLT_INITIAL_LOG_LEVEL"));
+ dlt_log(LOG_WARNING, str);
+ }
+ }
+
/* Initialize LogLevel/TraceStatus field */
DLT_SEM_LOCK();
dlt_user.dlt_ll_ts = 0;
@@ -650,6 +661,8 @@ int dlt_free(void)
dlt_user.dlt_ll_ts_max_num_entries = 0;
dlt_user.dlt_ll_ts_num_entries = 0;
}
+
+ dlt_env_free_ll_set(&dlt_user.initial_ll_set);
DLT_SEM_FREE();
char queue_name[NAME_MAX];
@@ -982,9 +995,13 @@ int dlt_register_context_ll_ts(DltContext *handle, const char *contextid, const
}
if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
- {
- dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level = loglevel;
- }
+ {
+ dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level = dlt_env_adjust_ll_from_env(&dlt_user.initial_ll_set, dlt_user.appID, contextid, loglevel);
+ }
+ else
+ {
+ dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level = dlt_env_adjust_ll_from_env(&dlt_user.initial_ll_set, dlt_user.appID, contextid, dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level);
+ }
if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
{
@@ -1004,23 +1021,8 @@ int dlt_register_context_ll_ts(DltContext *handle, const char *contextid, const
*(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr) = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level;
*(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr) = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status = tracestatus;
- if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
- {
- log.log_level = loglevel;
- }
- else
- {
- log.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
- }
-
- if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
- {
- log.trace_status = tracestatus;
- }
- else
- {
- log.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
- }
+ log.log_level = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level;
+ log.trace_status = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status;
dlt_user.dlt_ll_ts_num_entries++;