1916fff36Sdormando /* logging functions */ 2916fff36Sdormando #ifndef LOGGER_H 3916fff36Sdormando #define LOGGER_H 4916fff36Sdormando 5916fff36Sdormando #include "bipbuffer.h" 6916fff36Sdormando 7916fff36Sdormando /* TODO: starttime tunable */ 8916fff36Sdormando #define LOGGER_BUF_SIZE 1024 * 64 9a4f8b982Sdormando #define LOGGER_WATCHER_BUF_SIZE 1024 * 256 10916fff36Sdormando #define LOGGER_ENTRY_MAX_SIZE 2048 11916fff36Sdormando #define GET_LOGGER() ((logger *) pthread_getspecific(logger_key)); 12916fff36Sdormando 13916fff36Sdormando enum log_entry_type { 14916fff36Sdormando LOGGER_ASCII_CMD = 0, 15*c7fbccebSdormando LOGGER_EVICTION, 16*c7fbccebSdormando LOGGER_ITEM_GET, 17*c7fbccebSdormando LOGGER_ITEM_STORE 18916fff36Sdormando }; 19916fff36Sdormando 20916fff36Sdormando enum log_entry_subtype { 21916fff36Sdormando LOGGER_TEXT_ENTRY = 0, 22*c7fbccebSdormando LOGGER_EVICTION_ENTRY, 23*c7fbccebSdormando LOGGER_ITEM_GET_ENTRY, 24*c7fbccebSdormando LOGGER_ITEM_STORE_ENTRY 25916fff36Sdormando }; 26916fff36Sdormando 27916fff36Sdormando enum logger_ret_type { 28916fff36Sdormando LOGGER_RET_OK = 0, 29916fff36Sdormando LOGGER_RET_NOSPACE, 30916fff36Sdormando LOGGER_RET_ERR 31916fff36Sdormando }; 32916fff36Sdormando 33916fff36Sdormando enum logger_parse_entry_ret { 34916fff36Sdormando LOGGER_PARSE_ENTRY_OK = 0, 35d5f7f89aSdormando LOGGER_PARSE_ENTRY_FULLBUF, 36d5f7f89aSdormando LOGGER_PARSE_ENTRY_FAILED 37916fff36Sdormando }; 38916fff36Sdormando 39916fff36Sdormando typedef const struct { 40916fff36Sdormando enum log_entry_subtype subtype; 41916fff36Sdormando int reqlen; 42a4f8b982Sdormando uint16_t eflags; 43916fff36Sdormando char *format; 44916fff36Sdormando } entry_details; 45916fff36Sdormando 46*c7fbccebSdormando /* log entry intermediary structures */ 47cb8257e3Sdormando struct logentry_eviction { 48cb8257e3Sdormando long long int exptime; 49cb8257e3Sdormando uint32_t latime; 50cb8257e3Sdormando uint16_t it_flags; 51cb8257e3Sdormando uint8_t nkey; 52cb8257e3Sdormando char key[]; 53cb8257e3Sdormando }; 54cb8257e3Sdormando 55*c7fbccebSdormando struct logentry_item_get { 56*c7fbccebSdormando uint8_t was_found; 57*c7fbccebSdormando uint8_t nkey; 58*c7fbccebSdormando char key[]; 59*c7fbccebSdormando }; 60*c7fbccebSdormando 61*c7fbccebSdormando struct logentry_item_store { 62*c7fbccebSdormando int status; 63*c7fbccebSdormando int cmd; 64*c7fbccebSdormando uint8_t nkey; 65*c7fbccebSdormando char key[]; 66*c7fbccebSdormando }; 67*c7fbccebSdormando 68*c7fbccebSdormando /* end intermediary structures */ 69*c7fbccebSdormando 70916fff36Sdormando typedef struct _logentry { 71916fff36Sdormando enum log_entry_subtype event; 72a4f8b982Sdormando uint16_t eflags; 73916fff36Sdormando uint64_t gid; 74916fff36Sdormando struct timeval tv; /* not monotonic! */ 75916fff36Sdormando int size; 76916fff36Sdormando union { 77916fff36Sdormando void *entry; /* probably an item */ 78916fff36Sdormando char end; 79916fff36Sdormando } data[]; 80916fff36Sdormando } logentry; 81916fff36Sdormando 826a4e8e1fSdormando #define LOG_SYSEVENTS (1<<1) /* threads start/stop/working */ 836a4e8e1fSdormando #define LOG_FETCHERS (1<<2) /* get/gets/etc */ 846a4e8e1fSdormando #define LOG_MUTATIONS (1<<3) /* set/append/incr/etc */ 856a4e8e1fSdormando #define LOG_SYSERRORS (1<<4) /* malloc/etc errors */ 866a4e8e1fSdormando #define LOG_CONNEVENTS (1<<5) /* new client, closed, etc */ 876a4e8e1fSdormando #define LOG_EVICTIONS (1<<6) /* defailts of evicted items */ 886a4e8e1fSdormando #define LOG_STRICT (1<<7) /* block worker instead of drop */ 89d5f7f89aSdormando #define LOG_RAWCMDS (1<<9) /* raw ascii commands */ 9073407543Sdormando 9173407543Sdormando typedef struct _logger { 9273407543Sdormando struct _logger *prev; 9373407543Sdormando struct _logger *next; 9473407543Sdormando pthread_mutex_t mutex; /* guard for this + *buf */ 950503b5e2Sdormando uint64_t written; /* entries written to the buffer */ 9673407543Sdormando uint64_t dropped; /* entries dropped */ 9773407543Sdormando uint64_t blocked; /* times blocked instead of dropped */ 9873407543Sdormando uint16_t fetcher_ratio; /* log one out of every N fetches */ 9973407543Sdormando uint16_t mutation_ratio; /* log one out of every N mutations */ 1006a4e8e1fSdormando uint16_t eflags; /* flags this logger should log */ 101916fff36Sdormando bipbuf_t *buf; 102916fff36Sdormando const entry_details *entry_map; 103916fff36Sdormando } logger; 104916fff36Sdormando 105916fff36Sdormando enum logger_watcher_type { 106916fff36Sdormando LOGGER_WATCHER_STDERR = 0, 107916fff36Sdormando LOGGER_WATCHER_CLIENT = 1 108916fff36Sdormando }; 109916fff36Sdormando 110916fff36Sdormando typedef struct { 111916fff36Sdormando void *c; /* original connection structure. still with source thread attached */ 112916fff36Sdormando int sfd; /* client fd */ 113916fff36Sdormando int id; /* id number for watcher list */ 1141b03a9c6Sdormando uint64_t skipped; /* lines skipped since last successful print */ 1151b03a9c6Sdormando bool failed_flush; /* recently failed to write out (EAGAIN), wait before retry */ 116916fff36Sdormando enum logger_watcher_type t; /* stderr, client, syslog, etc */ 1176a4e8e1fSdormando uint16_t eflags; /* flags we are interested in */ 118a4f8b982Sdormando bipbuf_t *buf; /* per-watcher output buffer */ 119916fff36Sdormando } logger_watcher; 120916fff36Sdormando 1210503b5e2Sdormando 1220503b5e2Sdormando struct logger_stats { 1230503b5e2Sdormando uint64_t worker_dropped; 1240503b5e2Sdormando uint64_t worker_written; 1250503b5e2Sdormando uint64_t watcher_skipped; 1260503b5e2Sdormando uint64_t watcher_sent; 1270503b5e2Sdormando }; 1280503b5e2Sdormando 129916fff36Sdormando extern pthread_key_t logger_key; 130916fff36Sdormando 131916fff36Sdormando /* public functions */ 132916fff36Sdormando 133916fff36Sdormando void logger_init(void); 134916fff36Sdormando logger *logger_create(void); 135916fff36Sdormando 136cb8257e3Sdormando #define LOGGER_LOG(l, flag, type, ...) \ 137cb8257e3Sdormando do { \ 138cb8257e3Sdormando logger *myl = l; \ 139cb8257e3Sdormando if (l == NULL) \ 140cb8257e3Sdormando myl = GET_LOGGER(); \ 141cb8257e3Sdormando if (myl->eflags & flag) \ 142cb8257e3Sdormando logger_log(myl, type, __VA_ARGS__); \ 143cb8257e3Sdormando } while (0) 144cb8257e3Sdormando 145916fff36Sdormando enum logger_ret_type logger_log(logger *l, const enum log_entry_type event, const void *entry, ...); 146916fff36Sdormando 147916fff36Sdormando enum logger_add_watcher_ret { 148916fff36Sdormando LOGGER_ADD_WATCHER_TOO_MANY = 0, 149916fff36Sdormando LOGGER_ADD_WATCHER_OK, 150916fff36Sdormando LOGGER_ADD_WATCHER_FAILED 151916fff36Sdormando }; 152916fff36Sdormando 1536a4e8e1fSdormando enum logger_add_watcher_ret logger_add_watcher(void *c, const int sfd, uint16_t f); 154916fff36Sdormando 155916fff36Sdormando #endif 156