summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/logging.h
blob: b6b13fbd02a3a7e3b86f8fac50e0078f4c6cbf53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/*
  Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
  This file is part of GlusterFS.

  This file is licensed to you under your choice of the GNU Lesser
  General Public License, version 3 or any later version (LGPLv3 or
  later), or the GNU General Public License, version 2 (GPLv2), in all
  cases as published by the Free Software Foundation.
*/

#ifndef __LOGGING_H__
#define __LOGGING_H__

#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif

#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#include <pthread.h>

#ifdef GF_DARWIN_HOST_OS
#define GF_PRI_FSBLK       "u"
#define GF_PRI_DEV         PRId32
#define GF_PRI_NLINK       PRIu16
#define GF_PRI_SUSECONDS   "06d"
#else
#define GF_PRI_FSBLK       PRIu64
#define GF_PRI_DEV         PRIu64
#define GF_PRI_NLINK       PRIu32
#define GF_PRI_SUSECONDS   "06ld"
#endif
#define GF_PRI_BLKSIZE     PRId32
#define GF_PRI_SIZET       "zu"


#if 0
/* Syslog definitions :-) */
#define LOG_EMERG   0           /* system is unusable */
#define LOG_ALERT   1           /* action must be taken immediately */
#define LOG_CRIT    2           /* critical conditions */
#define LOG_ERR     3           /* error conditions */
#define LOG_WARNING 4           /* warning conditions */
#define LOG_NOTICE  5           /* normal but significant condition */
#define LOG_INFO    6           /* informational */
#define LOG_DEBUG   7           /* debug-level messages */
#endif

typedef enum {
        GF_LOG_NONE,
        GF_LOG_EMERG,
        GF_LOG_ALERT,
        GF_LOG_CRITICAL,   /* fatal errors */
        GF_LOG_ERROR,      /* major failures (not necessarily fatal) */
        GF_LOG_WARNING,    /* info about normal operation */
        GF_LOG_NOTICE,
        GF_LOG_INFO,       /* Normal information */
        GF_LOG_DEBUG,      /* internal errors */
        GF_LOG_TRACE,      /* full trace of operation */
} gf_loglevel_t;

/* format for the logs */
typedef enum {
        gf_logformat_traditional = 0, /* Format as in gluster 3.5 */
        gf_logformat_withmsgid, /* Format enhanced with MsgID, ident, errstr */
        gf_logformat_cee /* log enhanced format in cee */
} gf_log_format_t;

/* log infrastructure to log to */
typedef enum {
        gf_logger_glusterlog = 0, /* locations and files as in gluster 3.5 */
        gf_logger_syslog /* log to (r)syslog, based on (r)syslog conf */
        /* NOTE: In the future journald, lumberjack, next new thing here */
} gf_log_logger_t;

#define DEFAULT_LOG_FILE_DIRECTORY            DATADIR "/log/glusterfs"
#define DEFAULT_LOG_LEVEL                     GF_LOG_INFO

typedef struct gf_log_handle_ {
        pthread_mutex_t  logfile_mutex;
        uint8_t          logrotate;
        gf_loglevel_t    loglevel;
        int              gf_log_syslog;
        gf_loglevel_t    sys_log_level;
        char             gf_log_xl_log_set;
        char            *filename;
        FILE            *logfile;
        FILE            *gf_log_logfile;
        char            *cmd_log_filename;
        FILE            *cmdlogfile;
        gf_log_logger_t  logger;
        gf_log_format_t  logformat;
        char            *ident;
        int              log_control_file_found;
} gf_log_handle_t;

void gf_log_globals_init (void *ctx);
int gf_log_init (void *data, const char *filename, const char *ident);

void gf_log_logrotate (int signum);

void gf_log_cleanup (void);

/* Internal interfaces to log messages with message IDs */
int _gf_msg (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 *fmt, ...)
             __attribute__ ((__format__ (__printf__, 9, 10)));

void _gf_msg_backtrace_nomem (gf_loglevel_t level, int stacksize);

int _gf_msg_plain (gf_loglevel_t level, const char *fmt, ...)
                   __attribute__ ((__format__ (__printf__, 2, 3)));

int _gf_msg_plain_nomem (gf_loglevel_t level, const char *msg);

int _gf_msg_vplain (gf_loglevel_t level, const char *fmt, va_list ap);

int _gf_msg_nomem (const char *domain, const char *file,
                   const char *function, int line, gf_loglevel_t level,
                   size_t size);

int _gf_log (const char *domain, const char *file,
             const char *function, int32_t line, gf_loglevel_t level,
             const char *fmt, ...)
             __attribute__ ((__format__ (__printf__, 6, 7)));

int _gf_log_callingfn (const char *domain, const char *file,
                       const char *function, int32_t line, gf_loglevel_t level,
                       const char *fmt, ...)
                       __attribute__ ((__format__ (__printf__, 6, 7)));

int _gf_log_eh (const char *function, const char *fmt, ...);



/* treat GF_LOG_TRACE and GF_LOG_NONE as LOG_DEBUG and
 * other level as is */
#define SET_LOG_PRIO(level, priority) do {                              \
        if (GF_LOG_TRACE == (level) || GF_LOG_NONE == (level)) {        \
                priority = LOG_DEBUG;                                   \
        } else {                                                        \
                priority = (level) - 1;                                 \
        }                                                               \
        } while (0)

/* extract just the file name from the path */
#define GET_FILE_NAME_TO_LOG(file, basename) do {       \
        basename = strrchr ((file), '/');               \
        if (basename)                                   \
                basename++;                             \
        else                                            \
                basename = (file);                      \
        } while (0)

#define PRINT_SIZE_CHECK(ret, label, strsize) do {      \
        if (ret < 0)                            \
                goto label;                     \
        if ((strsize - ret) > 0) {              \
                strsize -= ret;                 \
        } else {                                \
                ret = 0;                        \
                goto label;                     \
        }                                       \
        } while (0)

#define FMT_WARN(fmt...) do { if (0) printf (fmt); } while (0)

/* Interface to log messages with message IDs */
#define gf_msg(dom, levl, errnum, msgid, fmt...) do {           \
                _gf_msg (dom, __FILE__, __FUNCTION__, __LINE__, \
                        levl, errnum, 0, msgid, ##fmt);         \
        } while (0)

/* no frills, no thrills, just a vanilla message, used to print the graph */
#define gf_msg_plain(levl, fmt...) do {         \
                _gf_msg_plain (levl, ##fmt);    \
        } while (0)

#define gf_msg_plain_nomem(levl, msg) do {              \
                _gf_msg_plain_nomem (levl, msg);        \
        } while (0)

#define gf_msg_vplain(levl, fmt, va) do {         \
                _gf_msg_vplain (levl, fmt, va);    \
        } while (0)

#define gf_msg_backtrace_nomem(level, stacksize) do {           \
                _gf_msg_backtrace_nomem (level, stacksize);     \
        } while (0)

#define gf_msg_callingfn(dom, levl, errnum, msgid, fmt...) do { \
                _gf_msg (dom, __FILE__, __FUNCTION__, __LINE__, \
                        levl, errnum, 1, msgid, ##fmt);         \
        } while (0)

/* No malloc or calloc should be called in this function */
#define gf_msg_nomem(dom, levl, size) do {                              \
                _gf_msg_nomem (dom, __FILE__, __FUNCTION__, __LINE__,   \
                                levl, size);                            \
        } while (0)

/* Debug or trace messages do not need message IDs as these are more developer
 * related. Hence, the following abstractions are provided for the same */
#define gf_msg_debug(dom, errnum, fmt...) do {                          \
                _gf_msg (dom, __FILE__, __FUNCTION__, __LINE__,         \
                        GF_LOG_DEBUG, errnum, 0, 0, ##fmt);             \
        } while (0)

#define gf_msg_trace(dom, errnum, fmt...) do {                          \
                _gf_msg (dom, __FILE__, __FUNCTION__, __LINE__,         \
                        GF_LOG_TRACE, errnum, 0, 0, ##fmt);             \
        } while (0)

#define gf_log(dom, levl, fmt...) do {                                  \
                FMT_WARN (fmt);                                         \
                _gf_log (dom, __FILE__, __FUNCTION__, __LINE__,         \
                         levl, ##fmt);                                  \
        } while (0)

#define gf_log_eh(fmt...) do {                                          \
                FMT_WARN (fmt);                                         \
                _gf_log_eh (__FUNCTION__, ##fmt);                        \
        } while (0)

#define gf_log_callingfn(dom, levl, fmt...) do {                        \
                FMT_WARN (fmt);                                         \
                _gf_log_callingfn (dom, __FILE__, __FUNCTION__, __LINE__, \
                                   levl, ##fmt);                        \
        } while (0)


/* Log once in GF_UNIVERSAL_ANSWER times */
#define GF_LOG_OCCASIONALLY(var, args...) if (!(var++%GF_UNIVERSAL_ANSWER)) { \
                gf_log (args);                                          \
        }

void gf_log_disable_syslog (void);
void gf_log_enable_syslog (void);
gf_loglevel_t gf_log_get_loglevel (void);
void gf_log_set_loglevel (gf_loglevel_t level);
void gf_log_flush (void);
gf_loglevel_t gf_log_get_xl_loglevel (void *xl);
void gf_log_set_xl_loglevel (void *xl, gf_loglevel_t level);

int gf_cmd_log (const char *domain, const char *fmt, ...)
                __attribute__ ((__format__ (__printf__, 2, 3)));

int gf_cmd_log_init (const char *filename);

void set_sys_log_level (gf_loglevel_t level);

int gf_log_fini(void *data);

#define GF_DEBUG(xl, format, args...)                           \
        gf_log ((xl)->name, GF_LOG_DEBUG, format, ##args)
#define GF_INFO(xl, format, args...)                            \
        gf_log ((xl)->name, GF_LOG_INFO, format, ##args)
#define GF_WARNING(xl, format, args...)                         \
        gf_log ((xl)->name, GF_LOG_WARNING, format, ##args)
#define GF_ERROR(xl, format, args...)                           \
        gf_log ((xl)->name, GF_LOG_ERROR, format, ##args)

#endif /* __LOGGING_H__ */