diff options
| author | Aravinda VK <avishwan@redhat.com> | 2017-06-14 13:31:42 +0530 | 
|---|---|---|
| committer | Jeff Darcy <jeff@pl.atyp.us> | 2017-06-29 11:55:39 +0000 | 
| commit | c0f1db29a2d8b3eb1311ad60c2935da0aff7ab70 (patch) | |
| tree | 61acaa5f48ed93c011da4e92b4d37114f1a1a71b /libglusterfs/src | |
| parent | e9c5b61861299add8bf4b61382611cda68ebb68c (diff) | |
logging: Support for Structured logging format
Wrapper for `gf_log` and `gf_msg` to add support for
structured logging format.
Two new wrappers available `gf_slog` and `gf_smsg`
Example 1: All static details
    gf_slog ("cli", GF_LOG_INFO, "Volume Set",
             "name=gv1",
             "option=changelog.changelog",
             "value=on",
             NULL);
    gf_smsg ("cli", GF_LOG_INFO, 0, MSGID_VOLUME_SET,
             "Volume Set",
             "name=gv1",
             "option=changelog.changelog",
             "value=on",
             NULL);
Example 2: Using Format chars in key values
    gf_slog ("cli", GF_LOG_INFO, "Volume Set",
             "name=%s", volume_name,
             "option=%s", option_name,
             "value=%s", option_value,
             NULL);
    gf_smsg ("cli", GF_LOG_INFO, 0, MSGID_VOLUME_SET,
             "Volume Set",
             "name=%s", volume_name,
             "option=%s", option_name,
             "value=%s", option_value,
             NULL);
Formats as,
    <EVENT><TAB><KEY1=VALUE1><TAB><KEY2=VALUE2>...
Example:
    Volume Set	name=gv1	option=changelog.changelog	value=on
Updates: #240
Change-Id: I871727be16a39f681d41f363daa0029b8066fb52
Signed-off-by: Aravinda VK <avishwan@redhat.com>
Reviewed-on: https://review.gluster.org/17543
Reviewed-by: MOHIT AGRAWAL <moagrawa@redhat.com>
Smoke: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: Amar Tumballi <amarts@redhat.com>
Tested-by: Amar Tumballi <amarts@redhat.com>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
Diffstat (limited to 'libglusterfs/src')
| -rw-r--r-- | libglusterfs/src/logging.c | 144 | ||||
| -rw-r--r-- | libglusterfs/src/logging.h | 20 | 
2 files changed, 164 insertions, 0 deletions
diff --git a/libglusterfs/src/logging.c b/libglusterfs/src/logging.c index a8e7b96a24c..9147f2782e9 100644 --- a/libglusterfs/src/logging.c +++ b/libglusterfs/src/logging.c @@ -35,6 +35,7 @@  #define GF_LOG_BACKTRACE_DEPTH  5  #define GF_LOG_BACKTRACE_SIZE   4096  #define GF_LOG_TIMESTR_SIZE     256 +#define GF_MAX_SLOG_PAIR_COUNT  100  #include "xlator.h"  #include "logging.h" @@ -2468,3 +2469,146 @@ out:          return ret;  } + +int +_do_slog_format (const char *event, va_list inp, char **msg) { +        va_list                    valist_tmp; +        int                        i = 0; +        int                        j = 0; +        int                        k = 0; +        int                        ret = 0; +        char                      *fmt = NULL; +        char                      *buffer = NULL; +        int                        num_format_chars = 0; +        char                       format_char = '%'; +        char                      *tmp1 = NULL; +        char                      *tmp2 = NULL; + +        ret = gf_asprintf (&tmp2, "%s", event); +        if (ret == -1) +                goto out; + +        /* Hardcoded value for max key value pairs, exits early */ +        /* from loop if found NULL */ +        for (i = 0; i < GF_MAX_SLOG_PAIR_COUNT; i++) { +                fmt = va_arg (inp, char*); +                if (fmt == NULL) { +                        break; +                } + +                /* Get number of times % is used in input for formating, */ +                /* this count will be used to skip those many args from the */ +                /* main list and will be used to format inner format */ +                num_format_chars = 0; +                for (k = 0; fmt[k] != '\0'; k++) { +                        /* If %% is used then that is escaped */ +                        if (fmt[k] == format_char && fmt[k+1] == format_char) { +                                k++; +                        } else if (fmt[k] == format_char) { +                                num_format_chars++; +                        } +                } + +                tmp1 = gf_strdup (tmp2); +                if (!tmp1) { +                        ret = -1; +                        goto out; +                } + +                GF_FREE (tmp2); +                tmp2 = NULL; + +                if (num_format_chars > 0) { +                        /* Make separate valist and format the string */ +                        va_copy (valist_tmp, inp); +                        ret = gf_vasprintf (&buffer, fmt, valist_tmp); +                        if (ret < 0) { +                                va_end (valist_tmp); +                                goto out; +                        } +                        va_end (valist_tmp); + +                        for (j = 0; j < num_format_chars; j++) { +                                /* Skip the va_arg value since these values +                                   are already used for internal formatting */ +                                (void) va_arg (inp, void*); +                        } + +                        ret = gf_asprintf (&tmp2, "%s\t%s", tmp1, buffer); +                        if (ret < 0) +                                goto out; + +                        GF_FREE (buffer); +                        buffer = NULL; +                } else { +                        ret = gf_asprintf (&tmp2, "%s\t%s", tmp1, fmt); +                        if (ret < 0) +                                goto out; +                } + +                GF_FREE (tmp1); +                tmp1 = NULL; +        } + +        *msg = gf_strdup (tmp2); +        if (!msg) +                ret = -1; + + out: +        if (buffer) +                GF_FREE (buffer); + +        if (tmp1) +                GF_FREE (tmp1); + +        if (tmp2) +                GF_FREE (tmp2); + +        return ret; +} + +int +_gf_smsg (const char *domain, const char *file, const char *function, +          int32_t line, gf_loglevel_t level, int errnum, int trace, +          uint64_t msgid, const char *event, ...) +{ +        va_list     valist; +        char       *msg = NULL; +        int         ret = 0; + +        va_start (valist, event); +        ret = _do_slog_format (event, valist, &msg); +        if (ret == -1) +                goto out; + +        ret = _gf_msg (domain, file, function, line, level, errnum, trace, +                       msgid, "%s", msg); + + out: +        va_end (valist); +        if (msg) +                GF_FREE (msg); +        return ret; +} + +int +_gf_slog (const char *domain, const char *file, const char *function, int line, +          gf_loglevel_t level, const char *event, ...) +{ +        va_list      valist; +        char        *msg = NULL; +        int          ret = 0; + +        va_start (valist, event); +        ret = _do_slog_format (event, valist, &msg); +        if (ret == -1) +                goto out; + +        ret = _gf_log (domain, file, function, line, level, "%s", msg); + + out: +        va_end (valist); +        if (msg) +                GF_FREE (msg); +        return ret; +} diff --git a/libglusterfs/src/logging.h b/libglusterfs/src/logging.h index 78d57888f35..a7f252acf67 100644 --- a/libglusterfs/src/logging.h +++ b/libglusterfs/src/logging.h @@ -325,4 +325,24 @@ gf_log_disable_suppression_before_exit (struct _glusterfs_ctx *ctx);  #define GF_ERROR(xl, format, args...)                           \          gf_log ((xl)->name, GF_LOG_ERROR, format, ##args) +int +_gf_slog (const char *domain, const char *file, const char *function, int line, +          gf_loglevel_t level, const char *event, ...); + +int +_gf_smsg (const char *domain, const char *file, const char *function, +          int32_t line, gf_loglevel_t level, int errnum, int trace, +          uint64_t msgid, const char *event, ...); + +/* Interface to log messages with message IDs */ +#define gf_smsg(dom, levl, errnum, msgid, event...) do {              \ +                _gf_smsg (dom, __FILE__, __FUNCTION__, __LINE__,      \ +                          levl, errnum, 0, msgid, ##event);           \ +        } while (0) + +#define gf_slog(dom, levl, event...) do {                             \ +                _gf_slog (dom, __FILE__, __FUNCTION__, __LINE__,      \ +                          levl, ##event);                             \ +        } while (0) +  #endif /* __LOGGING_H__ */  | 
