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