1 /* logging functions */
2 #ifndef LOGGER_H
3 #define LOGGER_H
4 
5 #include "bipbuffer.h"
6 
7 /* TODO: starttime tunable */
8 #define LOGGER_BUF_SIZE 1024 * 64
9 #define LOGGER_WATCHER_BUF_SIZE 1024 * 256
10 #define LOGGER_ENTRY_MAX_SIZE 2048
11 #define GET_LOGGER() ((logger *) pthread_getspecific(logger_key));
12 
13 /* Inlined from memcached.h - should go into sub header */
14 typedef unsigned int rel_time_t;
15 
16 enum log_entry_type {
17     LOGGER_ASCII_CMD = 0,
18     LOGGER_EVICTION,
19     LOGGER_ITEM_GET,
20     LOGGER_ITEM_STORE,
21     LOGGER_CRAWLER_STATUS,
22     LOGGER_SLAB_MOVE,
23     LOGGER_CONNECTION_NEW,
24     LOGGER_CONNECTION_CLOSE,
25     LOGGER_CONNECTION_ERROR,
26     LOGGER_CONNECTION_TLSERROR,
27     LOGGER_DELETIONS,
28 #ifdef EXTSTORE
29     LOGGER_EXTSTORE_WRITE,
30     LOGGER_COMPACT_START,
31     LOGGER_COMPACT_ABORT,
32     LOGGER_COMPACT_READ_START,
33     LOGGER_COMPACT_READ_END,
34     LOGGER_COMPACT_END,
35     LOGGER_COMPACT_FRAGINFO,
36 #endif
37 #ifdef PROXY
38     LOGGER_PROXY_CONFIG,
39     LOGGER_PROXY_RAW,
40     LOGGER_PROXY_ERROR,
41     LOGGER_PROXY_USER,
42     LOGGER_PROXY_REQ,
43     LOGGER_PROXY_BE_ERROR,
44 #endif
45 };
46 
47 enum logger_ret_type {
48     LOGGER_RET_OK = 0,
49     LOGGER_RET_NOSPACE,
50     LOGGER_RET_ERR
51 };
52 
53 enum logger_parse_entry_ret {
54     LOGGER_PARSE_ENTRY_OK = 0,
55     LOGGER_PARSE_ENTRY_FULLBUF,
56     LOGGER_PARSE_ENTRY_FAILED
57 };
58 
59 typedef struct _logentry logentry;
60 typedef struct _entry_details entry_details;
61 
62 typedef void (*entry_log_cb)(logentry *e, const entry_details *d, const void *entry, va_list ap);
63 typedef int (*entry_parse_cb)(logentry *e, char *scratch);
64 
65 struct _entry_details {
66     int reqlen;
67     uint16_t eflags;
68     entry_log_cb log_cb;
69     entry_parse_cb parse_cb;
70     char *format;
71 };
72 
73 /* log entry intermediary structures */
74 struct logentry_eviction {
75     long long int exptime;
76     int nbytes;
77     uint32_t latime;
78     uint16_t it_flags;
79     uint8_t nkey;
80     uint8_t clsid;
81     char key[];
82 };
83 #ifdef EXTSTORE
84 struct logentry_ext_write {
85     long long int exptime;
86     uint32_t latime;
87     uint16_t it_flags;
88     uint8_t nkey;
89     uint8_t clsid;
90     uint8_t bucket;
91     char key[];
92 };
93 #endif
94 struct logentry_item_get {
95     uint8_t was_found;
96     uint8_t nkey;
97     uint8_t clsid;
98     int nbytes;
99     int sfd;
100     char key[];
101 };
102 
103 struct logentry_item_store {
104     int status;
105     int cmd;
106     rel_time_t ttl;
107     uint8_t nkey;
108     uint8_t clsid;
109     int nbytes;
110     int sfd;
111     char key[];
112 };
113 
114 struct logentry_deletion {
115     int nbytes;
116     int cmd;
117     uint8_t nkey;
118     uint8_t clsid;
119     char key[];
120 };
121 
122 struct logentry_conn_event {
123     int transport;
124     int reason;
125     int sfd;
126     struct sockaddr_in6 addr;
127 };
128 #ifdef PROXY
129 struct logentry_proxy_req {
130     unsigned short type;
131     unsigned short code;
132     int status;
133     int conn_fd;
134     uint32_t reqlen;
135     size_t dlen;
136     size_t be_namelen;
137     size_t be_portlen;
138     long elapsed;
139     char data[];
140 };
141 
142 struct logentry_proxy_errbe {
143     size_t errlen;
144     size_t be_namelen;
145     size_t be_portlen;
146     size_t be_labellen;
147     size_t be_rbuflen;
148     int be_depth;
149     int retry;
150     char data[];
151 };
152 #endif
153 /* end intermediary structures */
154 
155 /* WARNING: cuddled items aren't compatible with warm restart. more code
156  * necessary to ensure log streams are all flushed/processed before stopping
157  */
158 struct _logentry {
159     enum log_entry_type event;
160     uint8_t pad;
161     uint16_t eflags;
162     uint64_t gid;
163     struct timeval tv; /* not monotonic! */
164     int size;
165     union {
166         char end;
167     } data[];
168 };
169 
170 #define LOG_SYSEVENTS  (1<<1) /* threads start/stop/working */
171 #define LOG_FETCHERS   (1<<2) /* get/gets/etc */
172 #define LOG_MUTATIONS  (1<<3) /* set/append/incr/etc */
173 #define LOG_SYSERRORS  (1<<4) /* malloc/etc errors */
174 #define LOG_CONNEVENTS (1<<5) /* new client, closed, etc */
175 #define LOG_EVICTIONS  (1<<6) /* details of evicted items */
176 #define LOG_STRICT     (1<<7) /* block worker instead of drop */
177 #define LOG_RAWCMDS    (1<<9) /* raw ascii commands */
178 #define LOG_PROXYREQS  (1<<10) /* command logs from proxy */
179 #define LOG_PROXYEVENTS (1<<11) /* error log stream from proxy */
180 #define LOG_PROXYUSER (1<<12) /* user generated logs from proxy */
181 #define LOG_DELETIONS (1<<13) /* see whats deleted */
182 
183 typedef struct _logger {
184     struct _logger *prev;
185     struct _logger *next;
186     pthread_mutex_t mutex; /* guard for this + *buf */
187     uint64_t written; /* entries written to the buffer */
188     uint64_t dropped; /* entries dropped */
189     uint64_t blocked; /* times blocked instead of dropped */
190     uint16_t fetcher_ratio; /* log one out of every N fetches */
191     uint16_t mutation_ratio; /* log one out of every N mutations */
192     uint16_t eflags; /* flags this logger should log */
193     bipbuf_t *buf;
194     const entry_details *entry_map;
195 } logger;
196 
197 enum logger_watcher_type {
198     LOGGER_WATCHER_STDERR = 0,
199     LOGGER_WATCHER_CLIENT = 1
200 };
201 
202 typedef struct  {
203     void *c; /* original connection structure. still with source thread attached */
204     int sfd; /* client fd */
205     int id; /* id number for watcher list */
206     uint64_t skipped; /* lines skipped since last successful print */
207     uint64_t min_gid; /* don't show log entries older than this GID */
208     bool failed_flush; /* recently failed to write out (EAGAIN), wait before retry */
209     enum logger_watcher_type t; /* stderr, client, syslog, etc */
210     uint16_t eflags; /* flags we are interested in */
211     bipbuf_t *buf; /* per-watcher output buffer */
212 } logger_watcher;
213 
214 
215 struct logger_stats {
216     uint64_t worker_dropped;
217     uint64_t worker_written;
218     uint64_t watcher_skipped;
219     uint64_t watcher_sent;
220     uint64_t watcher_count;
221 };
222 
223 extern pthread_key_t logger_key;
224 
225 /* public functions */
226 
227 void logger_init(void);
228 void logger_stop(void);
229 logger *logger_create(void);
230 
231 #define LOGGER_LOG(l, flag, type, ...) \
232     do { \
233         logger *myl = l; \
234         if (l == NULL) \
235             myl = GET_LOGGER(); \
236         if (myl->eflags & flag) \
237             logger_log(myl, type, __VA_ARGS__); \
238     } while (0)
239 
240 enum logger_ret_type logger_log(logger *l, const enum log_entry_type event, const void *entry, ...);
241 
242 enum logger_add_watcher_ret {
243     LOGGER_ADD_WATCHER_TOO_MANY = 0,
244     LOGGER_ADD_WATCHER_OK,
245     LOGGER_ADD_WATCHER_FAILED
246 };
247 
248 enum logger_add_watcher_ret logger_add_watcher(void *c, const int sfd, uint16_t f);
249 
250 /* functions used by restart system */
251 uint64_t logger_get_gid(void);
252 void logger_set_gid(uint64_t gid);
253 
254 #endif
255