litespeed-quic/src/liblsquic/lsquic_logger.h

273 lines
8.8 KiB
C

/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc. See LICENSE. */
/*
* lsquic_logger.h -- logging functions and macros.
*
* Usage (this assumes MY_MODULE) is a part of enum lsquic_logger_module):
* #define LSQUIC_LOGGER_MODULE MY_MODULE
* #include "lsquic_logger.h"
* LSQ_INFO("info message");
*
* If you want log messages from your module to contain connection ID, #define
* LSQUIC_LOG_CONN_ID so that it evaluates to connection ID. If, in addition,
* you want stream ID to be logged, #define LSQUIC_LOG_STREAM_ID similarly.
* See existing code for examples.
*
* To add a module:
* 1. Add entry to enum lsquic_logger_module.
* 2. Update lsqlm_to_str.
* 3. Update lsq_log_levels.
*/
#ifndef LSQUIC_LOGGER_H
#define LSQUIC_LOGGER_H
#include <stdint.h>
#include <stdio.h>
#include "lsquic_shared_support.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef LSQUIC_LOWEST_LOG_LEVEL
# define LSQUIC_LOWEST_LOG_LEVEL LSQ_LOG_DEBUG
#endif
/* Same levels as in sys/syslog.h: */
enum lsq_log_level {
LSQ_LOG_EMERG,
LSQ_LOG_ALERT,
LSQ_LOG_CRIT,
LSQ_LOG_ERROR,
LSQ_LOG_WARN,
LSQ_LOG_NOTICE,
LSQ_LOG_INFO,
LSQ_LOG_DEBUG,
N_LSQUIC_LOG_LEVELS
};
enum lsquic_logger_module {
LSQLM_NOMODULE,
LSQLM_LOGGER,
LSQLM_EVENT,
LSQLM_ENGINE,
LSQLM_CONN,
LSQLM_STREAM,
LSQLM_PARSE,
LSQLM_CFCW,
LSQLM_SFCW,
LSQLM_SENDCTL,
LSQLM_ALARMSET,
LSQLM_CRYPTO,
LSQLM_HANDSHAKE,
LSQLM_HSK_ADAPTER,
LSQLM_BBR,
LSQLM_CUBIC,
LSQLM_ADAPTIVE_CC,
LSQLM_HEADERS,
LSQLM_FRAME_WRITER,
LSQLM_FRAME_READER,
LSQLM_MINI_CONN,
LSQLM_TOKGEN,
LSQLM_ENG_HIST,
LSQLM_SPI,
LSQLM_HPI,
LSQLM_DI,
LSQLM_PRQ,
LSQLM_PACER,
LSQLM_HTTP1X,
LSQLM_QLOG,
LSQLM_TRAPA,
LSQLM_PURGA,
LSQLM_HCSI_READER,
LSQLM_HCSO_WRITER,
LSQLM_QENC_HDL,
LSQLM_QDEC_HDL,
LSQLM_QPACK_ENC,
LSQLM_QPACK_DEC,
LSQLM_PRIO,
LSQLM_BW_SAMPLER,
LSQLM_PACKET_RESIZE,
LSQLM_CONN_STATS,
N_LSQUIC_LOGGER_MODULES
};
/* Each module has its own log level.
*/
LSQUIC_EXTERN enum lsq_log_level lsq_log_levels[N_LSQUIC_LOGGER_MODULES];
extern const char *const lsqlm_to_str[N_LSQUIC_LOGGER_MODULES];
extern const char *const lsq_loglevel2str[N_LSQUIC_LOG_LEVELS];
#define LSQ_LOG_ENABLED_EXT(level, module) ( \
level <= LSQUIC_LOWEST_LOG_LEVEL && level <= lsq_log_levels[module])
#define LSQ_LOG_ENABLED(level) LSQ_LOG_ENABLED_EXT(level, LSQUIC_LOGGER_MODULE)
struct lsquic_cid;
/* The functions that perform actual logging are void. This is an
* optimization. In majority of cases the calls will succeed; even if
* they fail, there is nothing (at least, nothing simple) to be done to
* handle logging failure.
*/
/* There are four levels of log functions, depending on whether they take
* the following arguments:
* 1. Logger module
* 2. Connection ID
* 3. Stream ID
*
* Each level of logging function supports one additional argument, as seen
* below. LSQ_LOG is set to one of LSQ_LOG0, LSQ_LOG1, LSQ_LOG2, or LSQ_LOG3.
* You can still use LSQ_LOG{0..3} directly.
*/
void
lsquic_logger_log3 (enum lsq_log_level, enum lsquic_logger_module,
const struct lsquic_cid *conn_id,
lsquic_stream_id_t stream_id, const char *format, ...)
#if __GNUC__
__attribute__((format(printf, 5, 6)))
#endif
;
# define LSQ_LOG3(level, ...) do { \
if (LSQ_LOG_ENABLED(level)) \
lsquic_logger_log3(level, LSQUIC_LOGGER_MODULE, \
LSQUIC_LOG_CONN_ID, LSQUIC_LOG_STREAM_ID, __VA_ARGS__); \
} while (0)
void
lsquic_logger_log2 (enum lsq_log_level, enum lsquic_logger_module,
const struct lsquic_cid *conn_id, const char *format, ...)
#if __GNUC__
__attribute__((format(printf, 4, 5)))
#endif
;
# define LSQ_LOG2(level, ...) do { \
if (LSQ_LOG_ENABLED(level)) \
lsquic_logger_log2(level, LSQUIC_LOGGER_MODULE, \
LSQUIC_LOG_CONN_ID, __VA_ARGS__); \
} while (0)
# define LSQ_LOG2C(level, ...) do { \
if (LSQ_LOG_ENABLED(level)) \
{ \
char cidbuf_[MAX_CID_LEN * 2 + 1]; \
lsquic_logger_log2(level, LSQUIC_LOGGER_MODULE, \
LSQUIC_LOG_CONN_ID, __VA_ARGS__); \
} \
} while (0)
void
lsquic_logger_log1 (enum lsq_log_level, enum lsquic_logger_module,
const char *format, ...)
#if __GNUC__
__attribute__((format(printf, 3, 4)))
#endif
;
# define LSQ_LOG1(level, ...) do { \
if (LSQ_LOG_ENABLED(level)) \
lsquic_logger_log1(level, LSQUIC_LOGGER_MODULE, __VA_ARGS__); \
} while (0)
# define LSQ_LOG1C(level, ...) do { \
if (LSQ_LOG_ENABLED(level)) \
{ \
char cidbuf_[MAX_CID_LEN * 2 + 1]; \
lsquic_logger_log1(level, LSQUIC_LOGGER_MODULE, __VA_ARGS__); \
} \
} while (0)
void
lsquic_logger_log0 (enum lsq_log_level, const char *format, ...)
#if __GNUC__
__attribute__((format(printf, 2, 3)))
#endif
;
# define LSQ_LOG0(level, ...) do { \
if (LSQ_LOG_ENABLED(level)) \
lsquic_logger_log0(level, __VA_ARGS__); \
} while (0)
# define LSQ_LOG0C(level, ...) do { \
if (LSQ_LOG_ENABLED(level)) \
{ \
char cidbuf_[MAX_CID_LEN * 2 + 1]; \
lsquic_logger_log0(level, __VA_ARGS__); \
} \
} while (0)
#if defined(LSQUIC_LOGGER_MODULE)
#if defined(LSQUIC_LOG_CONN_ID)
#if defined(LSQUIC_LOG_STREAM_ID)
# define LSQ_LOG LSQ_LOG3
#else
# define LSQ_LOG LSQ_LOG2
# define LSQ_LOGC LSQ_LOG2C
#endif
#else
# define LSQ_LOG LSQ_LOG1
# define LSQ_LOGC LSQ_LOG1C
#endif
#else
# define LSQ_LOG LSQ_LOG0
# define LSQ_LOGC LSQ_LOG0C
# define LSQUIC_LOGGER_MODULE LSQLM_NOMODULE
#endif
#define LSQ_DEBUG(...) LSQ_LOG(LSQ_LOG_DEBUG, __VA_ARGS__)
#define LSQ_WARN(...) LSQ_LOG(LSQ_LOG_WARN, __VA_ARGS__)
#define LSQ_ALERT(...) LSQ_LOG(LSQ_LOG_ALERT, __VA_ARGS__)
#define LSQ_CRIT(...) LSQ_LOG(LSQ_LOG_CRIT, __VA_ARGS__)
#define LSQ_ERROR(...) LSQ_LOG(LSQ_LOG_ERROR, __VA_ARGS__)
#define LSQ_NOTICE(...) LSQ_LOG(LSQ_LOG_NOTICE, __VA_ARGS__)
#define LSQ_INFO(...) LSQ_LOG(LSQ_LOG_INFO, __VA_ARGS__)
#define LSQ_EMERG(...) LSQ_LOG(LSQ_LOG_EMERG, __VA_ARGS__)
#define LSQ_DEBUGC(...) LSQ_LOGC(LSQ_LOG_DEBUG, __VA_ARGS__)
#define LSQ_WARNC(...) LSQ_LOGC(LSQ_LOG_WARN, __VA_ARGS__)
#define LSQ_ALERTC(...) LSQ_LOGC(LSQ_LOG_ALERT, __VA_ARGS__)
#define LSQ_CRITC(...) LSQ_LOGC(LSQ_LOG_CRIT, __VA_ARGS__)
#define LSQ_ERRORC(...) LSQ_LOGC(LSQ_LOG_ERROR, __VA_ARGS__)
#define LSQ_NOTICEC(...) LSQ_LOGC(LSQ_LOG_NOTICE, __VA_ARGS__)
#define LSQ_INFOC(...) LSQ_LOGC(LSQ_LOG_INFO, __VA_ARGS__)
#define LSQ_EMERGC(...) LSQ_LOGC(LSQ_LOG_EMERG, __VA_ARGS__)
/* Shorthand for printing to file streams using internal lsquic_logger_if
*/
void
lsquic_log_to_fstream (FILE *, unsigned llts);
enum lsquic_logger_module
lsquic_str_to_logger_module (const char *);
enum lsq_log_level
lsquic_str_to_log_level (const char *);
/* Parse and set log levels passed via -l flag. If an error is encountered,
* an error message is printed to stderr and negative value is returned.
*/
int
lsquic_logger_lopt (const char *optarg);
#define CID_FMT ".*s"
#define CID_BITS_B(cid, b) 2 * (int) (cid)->len, \
(lsquic_cid2str(cid, b), b)
#define CID_BITS(cid) CID_BITS_B(cid, cidbuf_)
void
lsquic_cid2str (const struct lsquic_cid *, char *out);
const struct lsquic_cid *
lsquic_conn_log_cid (const struct lsquic_conn *);
#ifdef __cplusplus
}
#endif
#endif