lsquic_logger.h revision a74702c6
1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * lsquic_logger.h -- logging functions and macros.
4 *
5 * Usage (this assumes MY_MODULE) is a part of enum lsquic_logger_module):
6 *   #define LSQUIC_LOGGER_MODULE MY_MODULE
7 *   #include "lsquic_logger.h"
8 *   LSQ_INFO("info message");
9 *
10 * If you want log messages from your module to contain connection ID, #define
11 * LSQUIC_LOG_CONN_ID so that it evaluates to connection ID.  If, in addition,
12 * you want stream ID to be logged, #define LSQUIC_LOG_STREAM_ID similarly.
13 * See existing code for examples.
14 *
15 * To add a module:
16 *   1. Add entry to enum lsquic_logger_module.
17 *   2. Update lsqlm_to_str.
18 *   3. Update lsq_log_levels.
19 */
20
21#ifndef LSQUIC_LOGGER_H
22#define LSQUIC_LOGGER_H
23
24#include <stdint.h>
25#include <stdio.h>
26
27#include "lsquic_shared_support.h"
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33#ifndef LSQUIC_LOWEST_LOG_LEVEL
34#   define LSQUIC_LOWEST_LOG_LEVEL LSQ_LOG_DEBUG
35#endif
36
37/* Same levels as in sys/syslog.h: */
38enum lsq_log_level {
39    LSQ_LOG_EMERG,
40    LSQ_LOG_ALERT,
41    LSQ_LOG_CRIT,
42    LSQ_LOG_ERROR,
43    LSQ_LOG_WARN,
44    LSQ_LOG_NOTICE,
45    LSQ_LOG_INFO,
46    LSQ_LOG_DEBUG,
47    N_LSQUIC_LOG_LEVELS
48};
49
50enum lsquic_logger_module {
51    LSQLM_NOMODULE,
52    LSQLM_LOGGER,
53    LSQLM_EVENT,
54    LSQLM_ENGINE,
55    LSQLM_CONN,
56    LSQLM_STREAM,
57    LSQLM_PARSE,
58    LSQLM_CFCW,
59    LSQLM_SFCW,
60    LSQLM_SENDCTL,
61    LSQLM_ALARMSET,
62    LSQLM_CRYPTO,
63    LSQLM_HANDSHAKE,
64    LSQLM_HSK_ADAPTER,
65    LSQLM_BBR,
66    LSQLM_CUBIC,
67    LSQLM_ADAPTIVE_CC,
68    LSQLM_HEADERS,
69    LSQLM_FRAME_WRITER,
70    LSQLM_FRAME_READER,
71    LSQLM_MINI_CONN,
72    LSQLM_TOKGEN,
73    LSQLM_ENG_HIST,
74    LSQLM_SPI,
75    LSQLM_HPI,
76    LSQLM_DI,
77    LSQLM_PRQ,
78    LSQLM_PACER,
79    LSQLM_HTTP1X,
80    LSQLM_QLOG,
81    LSQLM_TRAPA,
82    LSQLM_PURGA,
83    LSQLM_HCSI_READER,
84    LSQLM_HCSO_WRITER,
85    LSQLM_QENC_HDL,
86    LSQLM_QDEC_HDL,
87    LSQLM_QPACK_ENC,
88    LSQLM_QPACK_DEC,
89    LSQLM_PRIO,
90    LSQLM_BW_SAMPLER,
91    LSQLM_PACKET_RESIZE,
92    LSQLM_CONN_STATS,
93    N_LSQUIC_LOGGER_MODULES
94};
95
96/* Each module has its own log level.
97 */
98
99LSQUIC_EXTERN enum lsq_log_level lsq_log_levels[N_LSQUIC_LOGGER_MODULES];
100
101extern const char *const lsqlm_to_str[N_LSQUIC_LOGGER_MODULES];
102
103extern const char *const lsq_loglevel2str[N_LSQUIC_LOG_LEVELS];
104
105#define LSQ_LOG_ENABLED_EXT(level, module) (                            \
106    level <= LSQUIC_LOWEST_LOG_LEVEL && level <= lsq_log_levels[module])
107
108#define LSQ_LOG_ENABLED(level) LSQ_LOG_ENABLED_EXT(level, LSQUIC_LOGGER_MODULE)
109
110struct lsquic_cid;
111
112/* The functions that perform actual logging are void.  This is an
113 * optimization.  In majority of cases the calls will succeed; even if
114 * they fail, there is nothing (at least, nothing simple) to be done to
115 * handle logging failure.
116 */
117
118/* There are four levels of log functions, depending on whether they take
119 * the following arguments:
120 *  1. Logger module
121 *  2. Connection ID
122 *  3. Stream ID
123 *
124 * Each level of logging function supports one additional argument, as seen
125 * below.  LSQ_LOG is set to one of LSQ_LOG0, LSQ_LOG1, LSQ_LOG2, or LSQ_LOG3.
126 * You can still use LSQ_LOG{0..3} directly.
127 */
128
129void
130lsquic_logger_log3 (enum lsq_log_level, enum lsquic_logger_module,
131                    const struct lsquic_cid *conn_id,
132                    lsquic_stream_id_t stream_id, const char *format, ...)
133#if __GNUC__
134            __attribute__((format(printf, 5, 6)))
135#endif
136;
137#   define LSQ_LOG3(level, ...) do {                                         \
138        if (LSQ_LOG_ENABLED(level))                                          \
139            lsquic_logger_log3(level, LSQUIC_LOGGER_MODULE,                  \
140                    LSQUIC_LOG_CONN_ID, LSQUIC_LOG_STREAM_ID, __VA_ARGS__);  \
141    } while (0)
142
143
144void
145lsquic_logger_log2 (enum lsq_log_level, enum lsquic_logger_module,
146                    const struct lsquic_cid *conn_id, const char *format, ...)
147#if __GNUC__
148            __attribute__((format(printf, 4, 5)))
149#endif
150;
151#   define LSQ_LOG2(level, ...) do {                                         \
152        if (LSQ_LOG_ENABLED(level))                                          \
153            lsquic_logger_log2(level, LSQUIC_LOGGER_MODULE,                  \
154                                       LSQUIC_LOG_CONN_ID, __VA_ARGS__);     \
155    } while (0)
156#   define LSQ_LOG2C(level, ...) do {                                        \
157        if (LSQ_LOG_ENABLED(level))                                          \
158        {                                                                    \
159            char cidbuf_[MAX_CID_LEN * 2 + 1];                               \
160            lsquic_logger_log2(level, LSQUIC_LOGGER_MODULE,                  \
161                                       LSQUIC_LOG_CONN_ID, __VA_ARGS__);     \
162        }                                                                    \
163    } while (0)
164
165void
166lsquic_logger_log1 (enum lsq_log_level, enum lsquic_logger_module,
167                    const char *format, ...)
168#if __GNUC__
169            __attribute__((format(printf, 3, 4)))
170#endif
171;
172#   define LSQ_LOG1(level, ...) do {                                         \
173        if (LSQ_LOG_ENABLED(level))                                          \
174            lsquic_logger_log1(level, LSQUIC_LOGGER_MODULE, __VA_ARGS__);    \
175    } while (0)
176#   define LSQ_LOG1C(level, ...) do {                                        \
177        if (LSQ_LOG_ENABLED(level))                                          \
178        {                                                                    \
179            char cidbuf_[MAX_CID_LEN * 2 + 1];                               \
180            lsquic_logger_log1(level, LSQUIC_LOGGER_MODULE, __VA_ARGS__);    \
181        }                                                                    \
182    } while (0)
183
184void
185lsquic_logger_log0 (enum lsq_log_level, const char *format, ...)
186#if __GNUC__
187            __attribute__((format(printf, 2, 3)))
188#endif
189;
190#   define LSQ_LOG0(level, ...) do {                                         \
191        if (LSQ_LOG_ENABLED(level))                                          \
192            lsquic_logger_log0(level, __VA_ARGS__);                          \
193    } while (0)
194#   define LSQ_LOG0C(level, ...) do {                                        \
195        if (LSQ_LOG_ENABLED(level))                                          \
196        {                                                                    \
197            char cidbuf_[MAX_CID_LEN * 2 + 1];                               \
198            lsquic_logger_log0(level, __VA_ARGS__);                          \
199        }                                                                    \
200    } while (0)
201
202#if defined(LSQUIC_LOGGER_MODULE)
203#if defined(LSQUIC_LOG_CONN_ID)
204#if defined(LSQUIC_LOG_STREAM_ID)
205#       define LSQ_LOG LSQ_LOG3
206#else
207#       define LSQ_LOG LSQ_LOG2
208#       define LSQ_LOGC LSQ_LOG2C
209#endif
210#else
211#       define LSQ_LOG LSQ_LOG1
212#       define LSQ_LOGC LSQ_LOG1C
213#endif
214#else
215#       define LSQ_LOG LSQ_LOG0
216#       define LSQ_LOGC LSQ_LOG0C
217#       define LSQUIC_LOGGER_MODULE LSQLM_NOMODULE
218#endif
219
220#define LSQ_DEBUG(...)   LSQ_LOG(LSQ_LOG_DEBUG,  __VA_ARGS__)
221#define LSQ_WARN(...)    LSQ_LOG(LSQ_LOG_WARN,   __VA_ARGS__)
222#define LSQ_ALERT(...)   LSQ_LOG(LSQ_LOG_ALERT,  __VA_ARGS__)
223#define LSQ_CRIT(...)    LSQ_LOG(LSQ_LOG_CRIT,   __VA_ARGS__)
224#define LSQ_ERROR(...)   LSQ_LOG(LSQ_LOG_ERROR,  __VA_ARGS__)
225#define LSQ_NOTICE(...)  LSQ_LOG(LSQ_LOG_NOTICE, __VA_ARGS__)
226#define LSQ_INFO(...)    LSQ_LOG(LSQ_LOG_INFO,   __VA_ARGS__)
227#define LSQ_EMERG(...)   LSQ_LOG(LSQ_LOG_EMERG,  __VA_ARGS__)
228
229#define LSQ_DEBUGC(...)   LSQ_LOGC(LSQ_LOG_DEBUG,  __VA_ARGS__)
230#define LSQ_WARNC(...)    LSQ_LOGC(LSQ_LOG_WARN,   __VA_ARGS__)
231#define LSQ_ALERTC(...)   LSQ_LOGC(LSQ_LOG_ALERT,  __VA_ARGS__)
232#define LSQ_CRITC(...)    LSQ_LOGC(LSQ_LOG_CRIT,   __VA_ARGS__)
233#define LSQ_ERRORC(...)   LSQ_LOGC(LSQ_LOG_ERROR,  __VA_ARGS__)
234#define LSQ_NOTICEC(...)  LSQ_LOGC(LSQ_LOG_NOTICE, __VA_ARGS__)
235#define LSQ_INFOC(...)    LSQ_LOGC(LSQ_LOG_INFO,   __VA_ARGS__)
236#define LSQ_EMERGC(...)   LSQ_LOGC(LSQ_LOG_EMERG,  __VA_ARGS__)
237
238/* Shorthand for printing to file streams using internal lsquic_logger_if
239 */
240void
241lsquic_log_to_fstream (FILE *, unsigned llts);
242
243enum lsquic_logger_module
244lsquic_str_to_logger_module (const char *);
245
246enum lsq_log_level
247lsquic_str_to_log_level (const char *);
248
249/* Parse and set log levels passed via -l flag.  If an error is encountered,
250 * an error message is printed to stderr and negative value is returned.
251 */
252int
253lsquic_logger_lopt (const char *optarg);
254
255#define CID_FMT ".*s"
256
257#define CID_BITS_B(cid, b) 2 * (int) (cid)->len, \
258                                    (lsquic_cid2str(cid, b), b)
259
260#define CID_BITS(cid) CID_BITS_B(cid, cidbuf_)
261
262void
263lsquic_cid2str (const struct lsquic_cid *, char *out);
264
265const struct lsquic_cid *
266lsquic_conn_log_cid (const struct lsquic_conn *);
267
268#ifdef __cplusplus
269}
270#endif
271
272#endif
273