summaryrefslogtreecommitdiff
path: root/logger.h
blob: 31a246da3621b60f46d037d3572f342af72056e5 (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
/* logging functions */
#ifndef LOGGER_H
#define LOGGER_H

#include "bipbuffer.h"

/* TODO: starttime tunable */
#define LOGGER_BUF_SIZE 1024 * 64
#define LOGGER_THREAD_BUF_SIZE 1024 * 256
#define LOGGER_ENTRY_MAX_SIZE 2048
#define GET_LOGGER() ((logger *) pthread_getspecific(logger_key));

enum log_entry_type {
    LOGGER_ASCII_CMD = 0,
    LOGGER_EVICTION
};

enum log_entry_subtype {
    LOGGER_TEXT_ENTRY = 0,
    LOGGER_EVICTION_ENTRY
};

enum logger_ret_type {
    LOGGER_RET_OK = 0,
    LOGGER_RET_NOSPACE,
    LOGGER_RET_ERR
};

enum logger_parse_entry_ret {
    LOGGER_PARSE_ENTRY_OK = 0,
    LOGGER_PARSE_ENTRY_FULLBUF
};

typedef const struct {
    enum log_entry_subtype subtype;
    int reqlen;
    char *format;
} entry_details;

typedef struct _logentry {
    enum log_entry_subtype event;
    uint64_t gid;
    struct timeval tv; /* not monotonic! */
    int size;
    union {
        void *entry; /* probably an item */
        char end;
    } data[];
} logentry;

#define LOG_SYSEVENTS  (1<<1) /* threads start/stop/working */
#define LOG_FETCHERS   (1<<2) /* get/gets/etc */
#define LOG_MUTATIONS  (1<<3) /* set/append/incr/etc */
#define LOG_SYSERRORS  (1<<4) /* malloc/etc errors */
#define LOG_CONNEVENTS (1<<5) /* new client, closed, etc */
#define LOG_EVICTIONS  (1<<6) /* defailts of evicted items */
#define LOG_STRICT     (1<<7) /* block worker instead of drop */
#define LOG_TIME       (1<<8) /* log the entry time */

typedef struct _logger {
    struct _logger *prev;
    struct _logger *next;
    pthread_mutex_t mutex; /* guard for this + *buf */
    uint64_t logged; /* entries written to the buffer */
    uint64_t dropped; /* entries dropped */
    uint64_t blocked; /* times blocked instead of dropped */
    uint16_t fetcher_ratio; /* log one out of every N fetches */
    uint16_t mutation_ratio; /* log one out of every N mutations */
    uint16_t eflags; /* flags this logger should log */
    bipbuf_t *buf;
    const entry_details *entry_map;
} logger;

typedef struct _logger_chunk {
    struct _logger_chunk *next;
    int size; /* max potential size */
    int written; /* amount written into the buffer (actual size) */
    int refcount; /* number of attached watchers */
    unsigned int filled :1; /* reached storage max */
    char data[];
} logger_chunk;

enum logger_watcher_type {
    LOGGER_WATCHER_STDERR = 0,
    LOGGER_WATCHER_CLIENT = 1
};

typedef struct  {
    void *c; /* original connection structure. still with source thread attached */
    logger_chunk *lc;
    int chunks; /* count of chunks stored up */
    int sfd; /* client fd */
    int flushed; /* backlog data flushed so far from active chunk */
    int id; /* id number for watcher list */
    enum logger_watcher_type t; /* stderr, client, syslog, etc */
    uint16_t eflags; /* flags we are interested in */
} logger_watcher;

extern pthread_key_t logger_key;

/* public functions */

void logger_init(void);
logger *logger_create(void);

enum logger_ret_type logger_log(logger *l, const enum log_entry_type event, const void *entry, ...);

enum logger_add_watcher_ret {
    LOGGER_ADD_WATCHER_TOO_MANY = 0,
    LOGGER_ADD_WATCHER_OK,
    LOGGER_ADD_WATCHER_FAILED
};

enum logger_add_watcher_ret logger_add_watcher(void *c, const int sfd, uint16_t f);

#endif