~ubuntu-branches/debian/sid/glusterfs/sid

« back to all changes in this revision

Viewing changes to libglusterfs/src/logging.c

  • Committer: Package Import Robot
  • Author(s): Patrick Matthäi
  • Date: 2014-04-22 10:00:41 UTC
  • mfrom: (1.3.25)
  • Revision ID: package-import@ubuntu.com-20140422100041-6mur2ttyvb8zzpfq
Tags: 3.5.0-1
* New upstream release.
  - Rewrite patch 01-spelling-error.
  - Adjust lintian overrides.
  - Install new files.
  - The offical tarball is not properly generated, hack it around.
  - Add symlink from fusermount-glusterfs manpage to mount.glusterfs.
  - Move gsync-sync-gfid from /usr/share to /usr/lib.
  - Add benchmarking directory.
* Remove old versioned build dependencies and build depend on libglib2.0-dev.
* Add lintian override for possible-gpl-code-linked-with-openssl. It is the
  same false positive like with the gluster-server package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
#include <string.h>
23
23
#include <stdlib.h>
24
24
 
 
25
#ifdef GF_USE_SYSLOG
 
26
#include <libintl.h>
 
27
#include <syslog.h>
 
28
#include <sys/stat.h>
 
29
#include "gf-error-codes.h"
 
30
 
 
31
#define GF_JSON_MSG_LENGTH      8192
 
32
#define GF_SYSLOG_CEE_FORMAT    \
 
33
        "@cee: {\"msg\": \"%s\", \"gf_code\": \"%u\", \"gf_message\": \"%s\"}"
 
34
#define GF_LOG_CONTROL_FILE     "/etc/glusterfs/logger.conf"
 
35
#endif /* GF_USE_SYSLOG */
 
36
 
25
37
#include "xlator.h"
26
38
#include "logging.h"
27
39
#include "defaults.h"
96
108
}
97
109
 
98
110
void
99
 
gf_log_fini (void)
 
111
gf_log_globals_fini (void)
100
112
{
101
113
        pthread_mutex_destroy (&THIS->ctx->log.logfile_mutex);
102
114
}
103
115
 
 
116
/** gf_log_fini - function to perform the cleanup of the log information
 
117
 * @data - glusterfs context
 
118
 * @return: success: 0
 
119
 *          failure: -1
 
120
 */
 
121
int
 
122
gf_log_fini (void *data)
 
123
{
 
124
        glusterfs_ctx_t *ctx = data;
 
125
        int ret = 0;
 
126
 
 
127
        if (ctx == NULL) {
 
128
                ret = -1;
 
129
                goto out;
 
130
        }
 
131
 
 
132
        pthread_mutex_lock (&ctx->log.logfile_mutex);
 
133
        {
 
134
                if (ctx->log.logfile) {
 
135
                        if (fclose (ctx->log.logfile) != 0)
 
136
                                ret = -1;
 
137
                        /* Logfile needs to be set to NULL, so that any
 
138
                           call to gf_log after calling gf_log_fini, will
 
139
                           log the message to stderr.
 
140
                        */
 
141
                        ctx->log.logfile = NULL;
 
142
                }
 
143
        }
 
144
        pthread_mutex_unlock (&ctx->log.logfile_mutex);
 
145
 
 
146
 out:
 
147
        return ret;
 
148
}
 
149
 
 
150
#ifdef GF_USE_SYSLOG
 
151
/**
 
152
 * gf_get_error_message -function to get error message for given error code
 
153
 * @error_code: error code defined by log book
 
154
 *
 
155
 * @return: success: string
 
156
 *          failure: NULL
 
157
 */
 
158
const char *
 
159
gf_get_error_message (int error_code) {
 
160
        return _gf_get_message (error_code);
 
161
}
 
162
 
 
163
 
 
164
/**
 
165
 * gf_openlog -function to open syslog specific to gluster based on
 
166
 *             existence of file /etc/glusterfs/logger.conf
 
167
 * @ident:    optional identification string similar to openlog()
 
168
 * @option:   optional value to option to openlog().  Passing -1 uses
 
169
 *            'LOG_PID | LOG_NDELAY' as default
 
170
 * @facility: optional facility code similar to openlog().  Passing -1
 
171
 *            uses LOG_DAEMON as default
 
172
 *
 
173
 * @return: void
 
174
 */
 
175
void
 
176
gf_openlog (const char *ident, int option, int facility)
 
177
{
 
178
        int _option = option;
 
179
        int _facility = facility;
 
180
 
 
181
        if (-1 == _option) {
 
182
                _option = LOG_PID | LOG_NDELAY;
 
183
        }
 
184
        if (-1 == _facility) {
 
185
                _facility = LOG_LOCAL1;
 
186
        }
 
187
 
 
188
        setlocale(LC_ALL, "");
 
189
        bindtextdomain("gluster", "/usr/share/locale");
 
190
        textdomain("gluster");
 
191
 
 
192
        openlog(ident, _option, _facility);
 
193
}
 
194
 
 
195
 
 
196
/**
 
197
 * _json_escape -function to convert string to json encoded string
 
198
 * @str: input string
 
199
 * @buf: buffer to store encoded string
 
200
 * @len: length of @buf
 
201
 *
 
202
 * @return: success: last unprocessed character position by pointer in @str
 
203
 *          failure: NULL
 
204
 *
 
205
 * Internal function. Heavily inspired by _ul_str_escape() function in
 
206
 * libumberlog
 
207
 *
 
208
 * Sample output:
 
209
 * [1] str = "devel error"
 
210
 *     buf = "devel error"
 
211
 * [2] str = "devel     error"
 
212
 *     buf = "devel\terror"
 
213
 * [3] str = "I/O error on "/tmp/foo" file"
 
214
 *     buf = "I/O error on \"/tmp/foo\" file"
 
215
 * [4] str = "I/O erroron /tmp/bar file"
 
216
 *     buf = "I/O error\u001bon /tmp/bar file"
 
217
 *
 
218
 */
 
219
char *
 
220
_json_escape(const char *str, char *buf, size_t len)
 
221
{
 
222
        static const unsigned char json_exceptions[UCHAR_MAX + 1] =
 
223
                {
 
224
                        [0x01] = 1, [0x02] = 1, [0x03] = 1, [0x04] = 1,
 
225
                        [0x05] = 1, [0x06] = 1, [0x07] = 1, [0x08] = 1,
 
226
                        [0x09] = 1, [0x0a] = 1, [0x0b] = 1, [0x0c] = 1,
 
227
                        [0x0d] = 1, [0x0e] = 1, [0x0f] = 1, [0x10] = 1,
 
228
                        [0x11] = 1, [0x12] = 1, [0x13] = 1, [0x14] = 1,
 
229
                        [0x15] = 1, [0x16] = 1, [0x17] = 1, [0x18] = 1,
 
230
                        [0x19] = 1, [0x1a] = 1, [0x1b] = 1, [0x1c] = 1,
 
231
                        [0x1d] = 1, [0x1e] = 1, [0x1f] = 1,
 
232
                        ['\\'] = 1, ['"'] = 1
 
233
                };
 
234
        static const char  json_hex_chars[16] = "0123456789abcdef";
 
235
        unsigned char     *p = NULL;
 
236
        size_t             pos = 0;
 
237
 
 
238
        if (!str || !buf || len <= 0) {
 
239
                return NULL;
 
240
        }
 
241
 
 
242
        for (p = (unsigned char *)str;
 
243
             *p && (pos + 1) < len;
 
244
             p++)
 
245
        {
 
246
                if (json_exceptions[*p] == 0) {
 
247
                        buf[pos++] = *p;
 
248
                        continue;
 
249
                }
 
250
 
 
251
                if ((pos + 2) >= len) {
 
252
                        break;
 
253
                }
 
254
 
 
255
                switch (*p)
 
256
                {
 
257
                case '\b':
 
258
                        buf[pos++] = '\\';
 
259
                        buf[pos++] = 'b';
 
260
                        break;
 
261
                case '\n':
 
262
                        buf[pos++] = '\\';
 
263
                        buf[pos++] = 'n';
 
264
                        break;
 
265
                case '\r':
 
266
                        buf[pos++] = '\\';
 
267
                        buf[pos++] = 'r';
 
268
                        break;
 
269
                case '\t':
 
270
                        buf[pos++] = '\\';
 
271
                        buf[pos++] = 't';
 
272
                        break;
 
273
                case '\\':
 
274
                        buf[pos++] = '\\';
 
275
                        buf[pos++] = '\\';
 
276
                        break;
 
277
                case '"':
 
278
                        buf[pos++] = '\\';
 
279
                        buf[pos++] = '"';
 
280
                        break;
 
281
                default:
 
282
                        if ((pos + 6) >= len) {
 
283
                                buf[pos] = '\0';
 
284
                                return (char *)p;
 
285
                        }
 
286
                        buf[pos++] = '\\';
 
287
                        buf[pos++] = 'u';
 
288
                        buf[pos++] = '0';
 
289
                        buf[pos++] = '0';
 
290
                        buf[pos++] = json_hex_chars[(*p) >> 4];
 
291
                        buf[pos++] = json_hex_chars[(*p) & 0xf];
 
292
                        break;
 
293
                }
 
294
        }
 
295
 
 
296
        buf[pos] = '\0';
 
297
        return (char *)p;
 
298
}
 
299
 
 
300
 
 
301
/**
 
302
 * gf_syslog -function to submit message to syslog specific to gluster
 
303
 * @error_code:        error code defined by log book
 
304
 * @facility_priority: facility_priority of syslog()
 
305
 * @format:            optional format string to syslog()
 
306
 *
 
307
 * @return: void
 
308
 */
 
309
void
 
310
gf_syslog (int error_code, int facility_priority, char *format, ...)
 
311
{
 
312
        char       *msg = NULL;
 
313
        char        json_msg[GF_JSON_MSG_LENGTH];
 
314
        GF_UNUSED char       *p = NULL;
 
315
        const char *error_message = NULL;
 
316
        char        json_error_message[GF_JSON_MSG_LENGTH];
 
317
        va_list     ap;
 
318
 
 
319
        error_message = gf_get_error_message (error_code);
 
320
 
 
321
        va_start (ap, format);
 
322
        if (format) {
 
323
                vasprintf (&msg, format, ap);
 
324
                p = _json_escape (msg, json_msg, GF_JSON_MSG_LENGTH);
 
325
                if (error_message) {
 
326
                        p = _json_escape (error_message, json_error_message,
 
327
                                          GF_JSON_MSG_LENGTH);
 
328
                        syslog (facility_priority, GF_SYSLOG_CEE_FORMAT,
 
329
                                json_msg, error_code, json_error_message);
 
330
                } else {
 
331
                        /* ignore the error code because no error message for it
 
332
                           and use normal syslog */
 
333
                        syslog (facility_priority, "%s", msg);
 
334
                }
 
335
                free (msg);
 
336
        } else {
 
337
                if (error_message) {
 
338
                        /* no user message: treat error_message as msg */
 
339
                        syslog (facility_priority, GF_SYSLOG_CEE_FORMAT,
 
340
                                json_error_message, error_code,
 
341
                                json_error_message);
 
342
                } else {
 
343
                        /* cannot produce log as neither error_message nor
 
344
                           msg available */
 
345
                }
 
346
        }
 
347
        va_end (ap);
 
348
}
 
349
#endif /* GF_USE_SYSLOG */
104
350
 
105
351
void
106
352
gf_log_globals_init (void *data)
113
359
        ctx->log.gf_log_syslog    = 1;
114
360
        ctx->log.sys_log_level    = GF_LOG_CRITICAL;
115
361
 
 
362
#ifndef GF_USE_SYSLOG
116
363
#ifdef GF_LINUX_HOST_OS
117
364
        /* For the 'syslog' output. one can grep 'GlusterFS' in syslog
118
365
           for serious logs */
119
366
        openlog ("GlusterFS", LOG_PID, LOG_DAEMON);
120
367
#endif
 
368
#endif
121
369
}
122
370
 
123
371
int
124
 
gf_log_init (void *data, const char *file)
 
372
gf_log_init (void *data, const char *file, const char *ident)
125
373
{
126
374
        glusterfs_ctx_t *ctx = NULL;
127
375
        int     fd = -1;
128
376
 
129
377
        ctx = data;
130
378
 
 
379
#if defined(GF_USE_SYSLOG)
 
380
        {
 
381
                /* use default ident and option */
 
382
                /* TODO: make FACILITY configurable than LOG_DAEMON */
 
383
                struct stat buf;
 
384
 
 
385
                if (stat (GF_LOG_CONTROL_FILE, &buf) == 0) {
 
386
                        /* use syslog logging */
 
387
                        ctx->log.log_control_file_found = 1;
 
388
                        if (ident) {
 
389
                                /* we need to keep this value as */
 
390
                                /* syslog uses it on every logging */
 
391
                                ctx->log.ident = gf_strdup (ident);
 
392
                                gf_openlog (ctx->log.ident, -1, LOG_DAEMON);
 
393
                        } else {
 
394
                                gf_openlog (NULL, -1, LOG_DAEMON);
 
395
                        }
 
396
                } else {
 
397
                        /* use old style logging */
 
398
                        ctx->log.log_control_file_found = 0;
 
399
                }
 
400
        }
 
401
#endif
 
402
 
131
403
        if (!file){
132
404
                fprintf (stderr, "ERROR: no filename specified\n");
133
405
                return -1;
134
406
        }
135
407
 
136
408
        if (strcmp (file, "-") == 0) {
137
 
                ctx->log.gf_log_logfile = stderr;
138
 
 
139
 
                return 0;
 
409
                file = "/dev/stderr";
140
410
        }
141
411
 
142
412
        ctx->log.filename = gf_strdup (file);
215
485
                return -1;
216
486
        }
217
487
 
 
488
        basename = strrchr (file, '/');
 
489
        if (basename)
 
490
                basename++;
 
491
        else
 
492
                basename = file;
 
493
 
218
494
#if HAVE_BACKTRACE
219
495
        /* Print 'calling function' */
220
496
        do {
241
517
        } while (0);
242
518
#endif /* HAVE_BACKTRACE */
243
519
 
 
520
#if defined(GF_USE_SYSLOG)
 
521
        if (ctx->log.log_control_file_found)
 
522
        {
 
523
                int priority;
 
524
                /* treat GF_LOG_TRACE and GF_LOG_NONE as LOG_DEBUG and
 
525
                   other level as is */
 
526
                if (GF_LOG_TRACE == level || GF_LOG_NONE == level) {
 
527
                        priority = LOG_DEBUG;
 
528
                } else {
 
529
                        priority = level - 1;
 
530
                }
 
531
                gf_syslog (GF_ERR_DEV, priority,
 
532
                           "[%s:%d:%s] %s %s: no memory "
 
533
                           "available for size (%"GF_PRI_SIZET")",
 
534
                           basename, line, function, callstr, domain,
 
535
                           size);
 
536
                goto out;
 
537
        }
 
538
#endif /* GF_USE_SYSLOG */
244
539
        ret = gettimeofday (&tv, NULL);
245
540
        if (-1 == ret)
246
541
                goto out;
248
543
        snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr),
249
544
                  ".%"GF_PRI_SUSECONDS, tv.tv_usec);
250
545
 
251
 
        basename = strrchr (file, '/');
252
 
        if (basename)
253
 
                basename++;
254
 
        else
255
 
                basename = file;
256
 
 
257
546
        ret = sprintf (msg, "[%s] %s [%s:%d:%s] %s %s: no memory "
258
547
                       "available for size (%"GF_PRI_SIZET")",
259
548
                       timestr, level_strings[level],
331
620
                return -1;
332
621
        }
333
622
 
 
623
        basename = strrchr (file, '/');
 
624
        if (basename)
 
625
                basename++;
 
626
        else
 
627
                basename = file;
 
628
 
334
629
#if HAVE_BACKTRACE
335
630
        /* Print 'calling function' */
336
631
        do {
357
652
        } while (0);
358
653
#endif /* HAVE_BACKTRACE */
359
654
 
 
655
#if defined(GF_USE_SYSLOG)
 
656
        if (ctx->log.log_control_file_found)
 
657
        {
 
658
                int priority;
 
659
                /* treat GF_LOG_TRACE and GF_LOG_NONE as LOG_DEBUG and
 
660
                   other level as is */
 
661
                if (GF_LOG_TRACE == level || GF_LOG_NONE == level) {
 
662
                        priority = LOG_DEBUG;
 
663
                } else {
 
664
                        priority = level - 1;
 
665
                }
 
666
 
 
667
                va_start (ap, fmt);
 
668
                vasprintf (&str2, fmt, ap);
 
669
                va_end (ap);
 
670
 
 
671
                gf_syslog (GF_ERR_DEV, priority,
 
672
                           "[%s:%d:%s] %s %d-%s: %s",
 
673
                           basename, line, function,
 
674
                           callstr,
 
675
                           ((this->graph) ? this->graph->id:0), domain,
 
676
                           str2);
 
677
 
 
678
                goto out;
 
679
        }
 
680
#endif /* GF_USE_SYSLOG */
360
681
        ret = gettimeofday (&tv, NULL);
361
682
        if (-1 == ret)
362
683
                goto out;
365
686
        snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr),
366
687
                  ".%"GF_PRI_SUSECONDS, tv.tv_usec);
367
688
 
368
 
        basename = strrchr (file, '/');
369
 
        if (basename)
370
 
                basename++;
371
 
        else
372
 
                basename = file;
373
 
 
374
689
        ret = gf_asprintf (&str1, "[%s] %s [%s:%d:%s] %s %d-%s: ",
375
690
                           timestr, level_strings[level],
376
691
                           basename, line, function, callstr,
468
783
                return -1;
469
784
        }
470
785
 
 
786
        basename = strrchr (file, '/');
 
787
        if (basename)
 
788
                basename++;
 
789
        else
 
790
                basename = file;
 
791
 
 
792
#if defined(GF_USE_SYSLOG)
 
793
        if (ctx->log.log_control_file_found)
 
794
        {
 
795
                int priority;
 
796
                /* treat GF_LOG_TRACE and GF_LOG_NONE as LOG_DEBUG and
 
797
                   other level as is */
 
798
                if (GF_LOG_TRACE == level || GF_LOG_NONE == level) {
 
799
                        priority = LOG_DEBUG;
 
800
                } else {
 
801
                        priority = level - 1;
 
802
                }
 
803
 
 
804
                va_start (ap, fmt);
 
805
                vasprintf (&str2, fmt, ap);
 
806
                va_end (ap);
 
807
 
 
808
                gf_syslog (GF_ERR_DEV, priority,
 
809
                           "[%s:%d:%s] %d-%s: %s",
 
810
                           basename, line, function,
 
811
                           ((this->graph) ? this->graph->id:0), domain, str2);
 
812
                goto err;
 
813
        }
 
814
#endif /* GF_USE_SYSLOG */
471
815
 
472
816
        if (ctx->log.logrotate) {
473
817
                ctx->log.logrotate = 0;
509
853
        snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr),
510
854
                  ".%"GF_PRI_SUSECONDS, tv.tv_usec);
511
855
 
512
 
        basename = strrchr (file, '/');
513
 
        if (basename)
514
 
                basename++;
515
 
        else
516
 
                basename = file;
517
 
 
518
856
        ret = gf_asprintf (&str1, "[%s] %s [%s:%d:%s] %d-%s: ",
519
857
                           timestr, level_strings[level],
520
858
                           basename, line, function,