>From 5481d0fcd046ea2aabb8584e9e80597929f00e16 Mon Sep 17 00:00:00 2001
From: Dmitri Pal <dpal@redhat.com>
Date: Sun, 27 Sep 2009 22:16:17 -0400
Subject: [PATCH] ELAPI Resolving message attribute

This patch continues work started
with the previous patch.
It resolves message attribute.
Message attribute is a special attribute
in the event that may contain
references to other attributes in the
event. When message is resolved the
references are replaced with actual
values of the referenced attributes.
---
 common/elapi/Makefile.am                   |    1 +
 common/elapi/elapi_event.h                 |   18 +-
 common/elapi/elapi_priv.h                  |   11 +-
 common/elapi/elapi_resolve.c               |  131 ++++++---
 common/elapi/elapi_subst.c                 |  395 ++++++++++++++++++++++++++++
 common/elapi/elapi_test/Makefile.am        |    1 +
 common/elapi/elapi_test/elapi_ut.c         |   30 ++-
 common/elapi/providers/file/file_fmt_csv.c |    6 +-
 8 files changed, 536 insertions(+), 57 deletions(-)
 create mode 100644 common/elapi/elapi_subst.c

diff --git a/common/elapi/Makefile.am b/common/elapi/Makefile.am
index 08fd2d7..53f2c3e 100644
--- a/common/elapi/Makefile.am
+++ b/common/elapi/Makefile.am
@@ -54,6 +54,7 @@ libelapi_la_SOURCES = \
     elapi_sink.c \
     elapi_resolve.c \
     elapi_async.c \
+    elapi_subst.c \
     elapi_event.h \
     elapi_priv.h \
     elapi_sink.h \
diff --git a/common/elapi/elapi_event.h b/common/elapi/elapi_event.h
index 6a5fe04..3e52dfd 100644
--- a/common/elapi/elapi_event.h
+++ b/common/elapi/elapi_event.h
@@ -22,11 +22,15 @@
 
 #include "collection.h"
 
-/* Possible predefined elements of the event */
-#define E_TIMESTAMP "__stamp__"     /* string - the value is the format for strftime()
+/* Possible predefined elements of the event.
+ * First letter R means that it is a property
+ * resolvable at the logging time.
+ */
+
+#define E_TIMESTAMP "R_stamp__"     /* string - the value is the format for strftime()
                                      * default is standard format for current locale.  */
-#define E_UTCTIME   "__time__"      /* int - UTC time as unix time in seconds since 1970 */
-#define E_OFFSET    "__loco__"      /* int - local time displacement */
+#define E_UTCTIME   "R_time__"      /* int - UTC time as unix time in seconds since 1970 */
+#define E_OFFSET    "R_loco__"      /* int - local time displacement */
 #define E_PID       "__pid__"       /* int - Process ID of the current process */
 #define E_APPNAME   "__appnm__"     /* string - Name of the current application */
 #define E_HOSTNAME  "__host__"      /* string - Name of the current host */
@@ -44,11 +48,11 @@
  * The token %(server) will be replaced by value
  * in the attribute "server" in the event.
  */
-#define E_MESSAGE   "__message__"
+#define E_MESSAGE   "R_message__"
 
 
-/* Standard prefix for internal attributes */
-#define E_PREFIX        "__"
+/* Standard prefix for internal resolvable attributes */
+#define E_PREFIX        "R_"
 #define E_PREFIX_LEN    2
 
 /* Base argument in the template creation function is a bit mask.
diff --git a/common/elapi/elapi_priv.h b/common/elapi/elapi_priv.h
index 27b0079..e7480f9 100644
--- a/common/elapi/elapi_priv.h
+++ b/common/elapi/elapi_priv.h
@@ -24,6 +24,7 @@
 #include <stdarg.h>
 
 #include "collection.h"
+#include "elapi_basic.h"
 #include "elapi_async.h"
 #include "elapi_sink.h"
 
@@ -178,8 +179,8 @@ struct elapi_sink_ctx {
  * needed to resolve the event.
  */
 struct elapi_resolve_data {
-    /* Reference to the event */
-    struct collection_item *event;
+    /* Reference to the message item inside event */
+    struct collection_item *message;
     /* Reference back to dispatcher */
     struct elapi_dispatcher *handle;
     /* Time related data */
@@ -321,6 +322,12 @@ int elapi_resolve_event(struct collection_item **final_event,
                         struct collection_item *event,
                         struct elapi_dispatcher *handle);
 
+/* Function to place the event items into a formatted string */
+int elapi_sprintf(struct elapi_data_out *out_data,
+                  const char *format_str,
+                  struct collection_item *event);
+
+
 /* Send ELAPI config errors into a file */
 void elapi_dump_ini_err(struct collection_item *error_list);
 
diff --git a/common/elapi/elapi_resolve.c b/common/elapi/elapi_resolve.c
index 5570eee..ca2601b 100644
--- a/common/elapi/elapi_resolve.c
+++ b/common/elapi/elapi_resolve.c
@@ -23,17 +23,17 @@
 
 #include "elapi_priv.h"
 #include "elapi_event.h"
-/* #include "elapi_subst.h" */
+#include "elapi_basic.h"
 #include "trace.h"
 #include "config.h"
 
 /*****************************************/
 /* Individual callbacks are defined here */
 /*****************************************/
-/* Timestamp resoltion callback */
-int elapi_timestamp_cb(struct elapi_resolve_data *resolver,
-                       struct collection_item *item,
-                       int *skip)
+/* Timestamp resolution callback */
+static int elapi_timestamp_cb(struct elapi_resolve_data *resolver,
+                              struct collection_item *item,
+                              int *skip)
 {
     int error = EOK;
     char timestamp[TIME_ARRAY_SIZE + 1];
@@ -58,9 +58,9 @@ int elapi_timestamp_cb(struct elapi_resolve_data *resolver,
 }
 
 /* UTC time resolution callback */
-int elapi_utctime_cb(struct elapi_resolve_data *resolver,
-                       struct collection_item *item,
-                       int *skip)
+static int elapi_utctime_cb(struct elapi_resolve_data *resolver,
+                            struct collection_item *item,
+                            int *skip)
 {
     int error = EOK;
 
@@ -76,9 +76,9 @@ int elapi_utctime_cb(struct elapi_resolve_data *resolver,
 }
 
 /* Offset resolution callback */
-int elapi_offset_cb(struct elapi_resolve_data *resolver,
-                       struct collection_item *item,
-                       int *skip)
+static int elapi_offset_cb(struct elapi_resolve_data *resolver,
+                           struct collection_item *item,
+                           int *skip)
 {
     int error = EOK;
 
@@ -93,45 +93,23 @@ int elapi_offset_cb(struct elapi_resolve_data *resolver,
     return error;
 }
 
-
 /* Message resolution callback */
-int elapi_message_cb(struct elapi_resolve_data *resolver,
-                       struct collection_item *item,
-                       int *skip)
+static int elapi_message_cb(struct elapi_resolve_data *resolver,
+                            struct collection_item *item,
+                            int *skip)
 {
-    int error = EOK;
-    /* int length; */
-    /* char *result; */
 
     TRACE_FLOW_STRING("elapi_message_cb", "Entry");
 
-    /* FIXME: Resolve message here */
-    /* Function is not yet implemented ...
-    error = elapi_sprintf(&result,
-                          &length,
-                          (const char *)col_get_item_data(item),
-                          resolver->event);
-    if (error) {
-        TRACE_ERROR_NUMBER("Failed to build message", error);
-        return error;
-    }
+    /* Save pointer to message item */
+    resolver->message = item;
 
-    error = col_modify_str_item(item,
-                                NULL,
-                                result;
-                                length + 1);
-    free(result);
-    if (error) {
-        TRACE_ERROR_NUMBER("Failed to modify message item", error);
-        return error;
-    }
-    */
-
-    TRACE_FLOW_NUMBER("elapi_message_cb. Exit. Returning", error);
-    return error;
+    TRACE_FLOW_NUMBER("elapi_message_cb.", "Exit");
+    return EOK;
 }
 
 
+
 /*****************************************/
 /* Array of structures for resolution of
  * the different event properties.
@@ -172,6 +150,8 @@ static int elapi_resolve_item(struct collection_item *item,
         return EOK;
     }
 
+    TRACE_FLOW_STRING("Item to resolve: ", col_get_item_property(item, NULL));
+
     /* This is an internal field that might need resolution */
     resolver = (struct elapi_resolve_data *)ext_data;
 
@@ -224,6 +204,53 @@ static int elapi_resolve_item(struct collection_item *item,
     return error;
 }
 
+/* Message resolution function */
+int elapi_resolve_message(struct collection_item *item,
+                          struct collection_item *event)
+{
+    int error = EOK;
+    struct elapi_data_out *serialized;
+
+    TRACE_FLOW_STRING("elapi_resolve_message", "Entry");
+
+    /* I prefer to allocate it rather than do it on stack.
+     * The main reason is that I would have to memset
+     * the struct to init it.
+     * So why not just use the interface we already have.
+     */
+    error = elapi_alloc_serialized_data(&serialized);
+    if (error) {
+        TRACE_ERROR_NUMBER("Failed to allocate serialized data", error);
+        return error;
+    }
+
+    /* Call string substitution */
+    error = elapi_sprintf(serialized,
+                          (const char *)col_get_item_data(item),
+                          event);
+    if (error) {
+        TRACE_ERROR_NUMBER("Failed to build message", error);
+        elapi_free_serialized_data(serialized);
+        return error;
+    }
+
+    /* Put the resolved value into the item */
+    error = col_modify_str_item(item,
+                                NULL,
+                                (char *)serialized->buffer,
+                                serialized->length + 1);
+
+    /* Clean data regardless of the result */
+    elapi_free_serialized_data(serialized);
+
+    if (error) {
+        TRACE_ERROR_NUMBER("Failed to modify message item", error);
+        return error;
+    }
+
+    TRACE_FLOW_NUMBER("elapi_resolve_message. Exit. Returning", error);
+    return error;
+}
 
 /* Resolve event */
 int elapi_resolve_event(struct collection_item **final_event,
@@ -238,8 +265,8 @@ int elapi_resolve_event(struct collection_item **final_event,
 
     TRACE_FLOW_STRING("elapi_create_event_ctx", "Entry");
 
-    /* Prepeare the resolver */
-    resolver.event = event;
+    /* Prepare the resolver */
+    resolver.message = NULL;
     resolver.handle = handle;
     /* Get seconds */
     resolver.tm = time(NULL);
@@ -267,6 +294,22 @@ int elapi_resolve_event(struct collection_item **final_event,
         return error;
     }
 
+    if (resolver.message) {
+        /* Now resolve message. We need to do it last since
+         * we do not know the order of the properties
+         * and message can be referencing properties
+         * that are later than message in the list
+         * and have not been resolved yet.
+         */
+        error = elapi_resolve_message(resolver.message,
+                                      new_event);
+        if (error) {
+            TRACE_ERROR_NUMBER("Failed to resolve the event", error);
+            col_destroy_collection(new_event);
+            return error;
+        }
+    }
+
     *final_event = new_event;
 
     TRACE_FLOW_STRING("elapi_create_event_ctx", "Exit");
@@ -279,7 +322,7 @@ int elapi_init_resolve_list(struct collection_iterator **list)
     int error = EOK;
     struct elapi_resolve_list *current;
     struct collection_item *col = NULL;
-    struct collection_iterator *iterator;
+    struct collection_iterator *iterator = NULL;
     struct elapi_rslv_item_data *bin_data;
 
     TRACE_FLOW_STRING("elapi_init_resolve_list", "Entry");
diff --git a/common/elapi/elapi_subst.c b/common/elapi/elapi_subst.c
new file mode 100644
index 0000000..da507aa
--- /dev/null
+++ b/common/elapi/elapi_subst.c
@@ -0,0 +1,395 @@
+/*
+    ELAPI
+
+    Module contains functions related to format substitution
+
+    Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdio.h>
+#include "elapi_priv.h"
+#include "trace.h"
+#include "config.h"
+
+/* Reasonable size for one event */
+/* FIXME: may be it would make sense to make it configurable ? */
+#define ELAPI_SUBST_BLOCK      256
+
+/* Calculate the potential size of the item */
+static unsigned elapi_get_item_len(int type, int raw_len)
+{
+    int serialized_len = 0;
+
+    TRACE_FLOW_STRING("elapi_get_item_len", "Entry point");
+
+    switch (type) {
+    case COL_TYPE_INTEGER:
+    case COL_TYPE_UNSIGNED:
+    case COL_TYPE_LONG:
+    case COL_TYPE_ULONG:
+        serialized_len = MAX_LONG_STRING_LEN;
+        break;
+
+    case COL_TYPE_STRING:
+        serialized_len = raw_len;
+        break;
+
+    case COL_TYPE_BINARY:
+        serialized_len = raw_len * 2;
+        break;
+
+    case COL_TYPE_DOUBLE:
+        serialized_len = MAX_DOUBLE_STRING_LEN;
+        break;
+
+    case COL_TYPE_BOOL:
+        serialized_len = MAX_BOOL_STRING_LEN;
+        break;
+
+    default:
+        serialized_len = 0;
+        break;
+    }
+
+    TRACE_FLOW_STRING("elapi_get_item_len", "Exit point");
+    return (uint32_t)serialized_len;
+}
+
+
+/* Function to serialize one item */
+static int elapi_sprintf_item(struct elapi_data_out *out_data,
+                              struct collection_item *item)
+{
+    int error = EOK;
+    uint32_t projected_len;
+    uint32_t used_len;
+    uint32_t item_len;
+    void *data;
+    int type;
+    int i;
+
+    TRACE_FLOW_STRING("elapi_sprintf_item", "Entry");
+
+    /* Get projected length of the item */
+    item_len = col_get_item_length(item);
+    type = col_get_item_type(item);
+    projected_len = elapi_get_item_len(type, item_len);
+
+    TRACE_INFO_NUMBER("Expected data length: ", projected_len);
+
+    /* Make sure we have enough space */
+    if (out_data->buffer == NULL) {
+        TRACE_INFO_STRING("First time use.", "");
+        /* Add null terminating zero */
+        projected_len++;
+    }
+
+    /* Grow buffer if needed */
+    error = elapi_grow_data(out_data,
+                            projected_len,
+                            ELAPI_SUBST_BLOCK);
+    if (error) {
+        TRACE_ERROR_NUMBER("Error. Failed to allocate memory.", error);
+        return error;
+    }
+
+    data = col_get_item_data(item);
+
+    /* Add the value */
+    switch (type) {
+    case COL_TYPE_STRING:
+
+        /* Item's length includes trailing 0 for data items */
+        used_len = item_len - 1;
+        memcpy(&out_data->buffer[out_data->length],
+                (const char *)(data),
+                used_len);
+        out_data->buffer[out_data->length + used_len] = '\0';
+        break;
+
+    case COL_TYPE_BINARY:
+
+        for (i = 0; i < item_len; i++) {
+            sprintf((char *)&out_data->buffer[out_data->length + i * 2],
+                    "%02X", (unsigned int)(((const unsigned char *)(data))[i]));
+        }
+        used_len = item_len * 2;
+        /* We need it here for the case item_len = 0 */
+        out_data->buffer[out_data->length + used_len] = '\0';
+        break;
+
+    case COL_TYPE_INTEGER:
+        used_len = sprintf((char *)&out_data->buffer[out_data->length],
+                           "%d", *((const int *)(data)));
+        break;
+
+    case COL_TYPE_UNSIGNED:
+        used_len = sprintf((char *)&out_data->buffer[out_data->length],
+                           "%u", *((const unsigned int *)(data)));
+        break;
+
+    case COL_TYPE_LONG:
+        used_len = sprintf((char *)&out_data->buffer[out_data->length],
+                           "%ld", *((const long *)(data)));
+        break;
+
+    case COL_TYPE_ULONG:
+        used_len = sprintf((char *)&out_data->buffer[out_data->length],
+                           "%lu", *((const unsigned long *)(data)));
+        break;
+
+    case COL_TYPE_DOUBLE:
+        used_len = sprintf((char *)&out_data->buffer[out_data->length],
+                           "%.4f", *((const double *)(data)));
+        break;
+
+    case COL_TYPE_BOOL:
+        used_len = sprintf((char *)&out_data->buffer[out_data->length],
+                           "%s",
+                           (*((const unsigned char *)(data))) ? "true" : "false");
+        break;
+
+    default:
+        out_data->buffer[out_data->length] = '\0';
+        used_len = 0;
+        break;
+    }
+
+    /* Adjust length */
+    out_data->length += used_len;
+
+    TRACE_INFO_STRING("Data: ", (char *)out_data->buffer);
+
+    TRACE_FLOW_STRING("elapi_sprintf_item", "Exit");
+    return error;
+
+}
+
+/* Lookup item hoping that items in message are somewhat ordered.
+ * If there is some ordering we will save on performance.
+ * If not we will not loos against a standard lookup.
+ */
+static struct collection_item *elapi_lookup_item(const char *start,
+                                                 int length,
+                                                 struct collection_iterator *iterator)
+{
+    int error = EOK;
+    struct collection_item *found = NULL;
+    const char *property;
+    int property_len;
+    uint64_t hash;
+
+    TRACE_FLOW_STRING("elapi_lookup_item", "Entry");
+
+    /* Prepare hash */
+    hash = col_make_hash(start, length, NULL);
+
+    /* NOTE: This iteration loop uses advanced iterator
+     * capabilities. Read more about it before you decide
+     * to use this code as an example.
+     */
+    while (1) {
+
+        /* Advance to next item in the list */
+        error = col_iterate_collection(iterator,
+                                       &found);
+        if (error) {
+            TRACE_ERROR_NUMBER("Failed to iterate collection", error);
+            return NULL;
+        }
+
+        /* Are we done ? This means we looped and did not find
+         * the item. */
+        if (found == NULL) break;
+
+        property = col_get_item_property(found, &property_len);
+
+        /* Compare item and the property */
+        if ((hash == col_get_item_hash(found)) &&
+            (length == property_len) &&
+            (strncasecmp(start, property, length) == 0)) {
+            /* This is our item !!! */
+            /* Pin down the iterator here */
+            col_pin_iterator(iterator);
+
+            /* Break out of loop */
+            break;
+        }
+    }
+
+    TRACE_FLOW_STRING("elapi_lookup_item", "Exit");
+    return found;
+}
+
+
+/* Function to parse format string */
+static const char *elapi_parse_format(const char *start,
+                                      int *length,
+                                      struct collection_item **item,
+                                      struct collection_iterator *iterator)
+{
+    const char *runner;
+    const char *bracket;
+    const char *name_start;
+
+    TRACE_FLOW_STRING("elapi_parse_format", "Entry");
+    if ((start == NULL) || (*start == '\0')) {
+        TRACE_FLOW_STRING("String is empty", "Return");
+        return NULL;
+    }
+
+    runner = start;
+
+    while (1) {
+        /* First check for end of the string */
+        if (*runner == '\0') {
+            TRACE_FLOW_STRING("Found last token", start);
+            *length = runner - start;
+            return runner;
+        }
+
+        /* Is it the beginning of the field substitution? */
+        if (*runner == '%') {
+            /* Check for bracket */
+            if (*(runner + 1) == '(') {
+                /* Search for closing one */
+                name_start = runner + 2;
+                bracket = name_start;
+                while (1) {
+                    /* Check for the end */
+                    if (*bracket == '\0') {
+                        TRACE_FLOW_STRING("No closing bracket", start);
+                        *length = bracket - start;
+                        return bracket;
+                    }
+                    /* Did we find closing backet? */
+                    if (*bracket == ')') {
+                        TRACE_FLOW_STRING("Bracket is found: ", name_start);
+                        /* There might be specific format specifiers */
+                        if (*name_start == '!') {
+                            /* Force rewind of the
+                             * iterator */
+                            col_rewind_iterator(iterator);
+                            name_start++;
+                        }
+
+                        /* FIXME: Add other specifiers here...
+                         * Specifier that can be supported in future
+                         * might expand multi value property
+                         * to a list of values separated by
+                         * provided symbol.
+                         */
+
+                        *item = elapi_lookup_item(name_start,
+                                                  bracket - name_start,
+                                                  iterator);
+                        bracket++;
+                        if (*item == NULL) {
+                            /* The item is not known (or error) */
+                            TRACE_FLOW_STRING("No item in event", name_start);
+                            *length = bracket - start;
+                            return bracket;
+                        }
+
+                        /* Item is found */
+                        TRACE_FLOW_STRING("Item found: ", name_start);
+                        *length = runner - start;
+                        return bracket;
+                    }
+                    bracket++;
+                }
+            }
+        }
+        runner++;
+    }
+    /* This point is unreachable */
+}
+
+/* Function to place the event items into the formatted string */
+int elapi_sprintf(struct elapi_data_out *out_data,
+                  const char *format_str,
+                  struct collection_item *event)
+{
+    const char *start;
+    int length;
+    struct collection_item *item;
+    struct collection_iterator *iterator = NULL;
+    const char *result;
+    int error;
+
+    TRACE_FLOW_STRING("elapi_sprintf", "Entry");
+
+    /* Create iterator - by thus time cevent is resolved and should
+     * be a flattened collection. At least this is the assumption.
+     */
+    error = col_bind_iterator(&iterator, event, COL_TRAVERSE_IGNORE);
+    if (error) {
+        TRACE_ERROR_NUMBER("Failed to bind iterator", error);
+        return error;
+    }
+
+    start = format_str;
+
+    while(1) {
+
+        item = NULL;
+        length = 0;
+
+        /* Parse format definition */
+        result = elapi_parse_format(start, &length, &item, iterator);
+        if (result == NULL) {
+            TRACE_INFO_STRING("Done parsing string", "");
+            break;
+        }
+
+        /* Apply parsed data */
+        if (length > 0) {
+            error = elapi_grow_data(out_data,
+                                    length + 1,
+                                    ELAPI_SUBST_BLOCK);
+            if (error) {
+                TRACE_ERROR_NUMBER("Error. Failed to allocate memory.", error);
+                col_unbind_iterator(iterator);
+                return error;
+            }
+
+            memcpy(&out_data->buffer[out_data->length],
+                    (const char *)(start),
+                    length);
+
+            out_data->length += length;
+            /* We asked for this one extra byte above */
+            out_data->buffer[out_data->length] = '\0';
+        }
+
+        if (item != NULL) {
+            TRACE_INFO_NUMBER("Need to output item", error);
+            error = elapi_sprintf_item(out_data, item);
+            if (error) {
+                TRACE_ERROR_NUMBER("Error. Failed to allocate memory.", error);
+                col_unbind_iterator(iterator);
+                return error;
+            }
+        }
+
+        start = result;
+    }
+
+    col_unbind_iterator(iterator);
+
+    TRACE_FLOW_STRING("elapi_sprintf", "Exit");
+    return error;
+}
diff --git a/common/elapi/elapi_test/Makefile.am b/common/elapi/elapi_test/Makefile.am
index dcf1707..c0eac8a 100644
--- a/common/elapi/elapi_test/Makefile.am
+++ b/common/elapi/elapi_test/Makefile.am
@@ -32,6 +32,7 @@ libelapi_test_la_SOURCES = \
     ../elapi_basic.h \
     ../elapi_resolve.c \
     ../elapi_async.c \
+    ../elapi_subst.c \
     ../elapi_event.h \
     ../elapi_priv.h \
     ../elapi_sink.h \
diff --git a/common/elapi/elapi_test/elapi_ut.c b/common/elapi/elapi_test/elapi_ut.c
index 1046ed0..ab0f88d 100644
--- a/common/elapi/elapi_test/elapi_ut.c
+++ b/common/elapi/elapi_test/elapi_ut.c
@@ -76,7 +76,7 @@ int simple_event_test(void)
     printf("Simple test START:\n");
 
     error = elapi_set_default_template(
-        E_BASE_DEFV1 | E_BASE_HOSTEXT,
+        E_BASE_DEFV1 | E_BASE_HOSTEXT /* FIXME Ticket #207 */,
         "%n( bin )", bin, 8,
         " %sb( logical1 )", "false",
         "%sb( logical2   )", "YES",
@@ -391,6 +391,34 @@ int complex_event_test(void)
         return error;
     }
 
+    error = elapi_dsp_msg(E_TARGET_DEBUG,
+                          dispatcher,
+                          template,
+                          E_MESSAGE,
+                          "date = %(R_stamp__), pid = %(__pid__), "
+                          "hostname = %(__host__), %(__halias__), "
+                          "ip = %(__ip__), [%(__iplist__);%(!__iplist__);%(__iplist__)]"  ,
+                          E_EOARG);
+    if (error) {
+        elapi_destroy_event_template(template);
+        printf("Failed to log event! %d\n", error);
+        return error;
+    }
+
+    error = elapi_dsp_msg(E_TARGET_DEBUG,
+                          dispatcher,
+                          template,
+                          E_MESSAGE,
+                          "date = %(R_stamp__), pid = %(__pid__), "
+                          "hostname = %(__host__), %(__halias__), "
+                          "ip = %(__ip__), [%(__iplist__);%(__iplist__);%(__iplist__)]"  ,
+                          E_EOARG);
+    if (error) {
+        elapi_destroy_event_template(template);
+        printf("Failed to log event! %d\n", error);
+        return error;
+    }
+
     elapi_destroy_event_template(template);
 
     elapi_print_dispatcher(dispatcher);
diff --git a/common/elapi/providers/file/file_fmt_csv.c b/common/elapi/providers/file/file_fmt_csv.c
index e55d0b1..1a19871 100644
--- a/common/elapi/providers/file/file_fmt_csv.c
+++ b/common/elapi/providers/file/file_fmt_csv.c
@@ -40,7 +40,7 @@ static unsigned file_csv_data_len(struct file_csv_cfg *cfg,
 {
     int serialized_len = 0;
 
-    TRACE_FLOW_STRING("col_get_data_len", "Entry point");
+    TRACE_FLOW_STRING("file_csv_data_len", "Entry point");
 
     switch (type) {
     case COL_TYPE_INTEGER:
@@ -75,7 +75,7 @@ static unsigned file_csv_data_len(struct file_csv_cfg *cfg,
 
     if (cfg->csvqualifier) serialized_len += 2;
 
-    TRACE_FLOW_STRING("col_get_data_len","Exit point");
+    TRACE_FLOW_STRING("file_csv_data_len", "Exit point");
     return (uint32_t)serialized_len;
 }
 
@@ -249,7 +249,7 @@ int file_serialize_csv(struct elapi_data_out *out_data,
      */
     out_data->buffer[out_data->length] = '\0';
 
-    TRACE_INFO_STRING("Data: ", out_data->buffer);
+    TRACE_INFO_STRING("Data: ", (char *)out_data->buffer);
 
     TRACE_FLOW_STRING("file_serialize_csv.", "Exit");
     return error;
-- 
1.5.5.6

