Files
smartdns/src/tlog.h

301 lines
7.8 KiB
C++

/*
* tinylog
* Copyright (C) 2018-2023 Ruilin Peng (Nick) <pymumu@gmail.com>
* https://github.com/pymumu/tinylog
*/
#ifndef TLOG_H
#define TLOG_H
#include <stdarg.h>
#include <sys/stat.h>
#include <sys/types.h>
#ifdef __cplusplus
#include <functional>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
extern "C" {
#endif /*__cplusplus */
typedef enum {
TLOG_DEBUG = 0,
TLOG_INFO = 1,
TLOG_NOTICE = 2,
TLOG_WARN = 3,
TLOG_ERROR = 4,
TLOG_FATAL = 5,
TLOG_OFF = 6,
TLOG_END = 7
} tlog_level;
struct tlog_time {
int year;
unsigned int usec;
unsigned char mon;
unsigned char mday;
unsigned char hour;
unsigned char min;
unsigned char sec;
} __attribute__((packed));
#ifndef TLOG_MAX_LINE_LEN
#define TLOG_MAX_LINE_LEN (1024)
#endif
/* TLOG FLAGS LIST */
/* set tlog not compress file when archive */
#define TLOG_NOCOMPRESS (1 << 0)
/* Set the segmentation mode to process the log, Used by the callback function to return a full log*/
#define TLOG_SEGMENT (1 << 1)
/*
multiwrite: enable multi process write mode.
NOTICE: maxlogsize in all processes must be same when enable this mode.
*/
#define TLOG_MULTI_WRITE (1 << 2)
/* Not Block if buffer is insufficient. */
#define TLOG_NONBLOCK (1 << 3)
/* enable log to screen */
#define TLOG_SCREEN (1 << 4)
/* enable support fork process */
#define TLOG_SUPPORT_FORK (1 << 5)
struct tlog_loginfo {
tlog_level level;
const char *file;
const char *func;
int line;
struct tlog_time time;
} __attribute__((packed));
/*
Function: Print log
level: Current log Levels
format: Log formats
*/
#ifndef BASE_FILE_NAME
#define BASE_FILE_NAME \
(__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 \
: __FILE__)
#endif
#define tlog(level, format, ...) tlog_ext(level, BASE_FILE_NAME, __LINE__, __func__, NULL, format, ##__VA_ARGS__)
extern int tlog_ext(tlog_level level, const char *file, int line, const char *func, void *userptr, const char *format, ...)
__attribute__((format(printf, 6, 7))) __attribute__((nonnull(6)));
extern int tlog_vext(tlog_level level, const char *file, int line, const char *func, void *userptr, const char *format, va_list ap);
/* write buff to log file */
extern int tlog_write_log(char *buff, int bufflen);
/* set log level */
extern int tlog_setlevel(tlog_level level);
/* is log level enabled*/
extern int tlog_log_enabled(tlog_level level);
/* get log level */
extern tlog_level tlog_getlevel(void);
/* set log file */
extern void tlog_set_logfile(const char *logfile);
/* enable log to screen */
extern void tlog_setlogscreen(int enable);
/* enable early log to screen */
extern void tlog_set_early_printf(int enable);
/* Get log level in string */
extern const char *tlog_get_level_string(tlog_level level);
/* set max log count */
extern void tlog_set_maxlog_count(int count);
/*
Function: Initialize log module
logfile: log file.
maxlogsize: The maximum size of a single log file.
maxlogcount: Number of archived logs.
buffsize: Buffer size, zero for default (128K)
flag: read tlog flags
*/
extern int tlog_init(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag);
/* flush pending log message, and exit tlog */
extern void tlog_exit(void);
/*
customize log output format
steps:
1. define format function, function must be defined as tlog_format_func, use snprintf or vsnprintf format log to buffer
2. call tlog_reg_format_func to register format function.
read _tlog_format for example.
*/
typedef int (*tlog_format_func)(char *buff, int maxlen, struct tlog_loginfo *info, void *userptr, const char *format, va_list ap);
extern int tlog_reg_format_func(tlog_format_func callback);
/* register log output callback
Note: info is invalid when flag TLOG_SEGMENT is not set.
*/
typedef int (*tlog_log_output_func)(struct tlog_loginfo *info, const char *buff, int bufflen, void *private_data);
extern int tlog_reg_log_output_func(tlog_log_output_func output, void *private_data);
struct tlog_log;
typedef struct tlog_log tlog_log;
/* get root log handler */
extern tlog_log *tlog_get_root(void);
/*
Function: open a new log stream, handler should close by tlog_close
logfile: log file.
maxlogsize: The maximum size of a single log file.
maxlogcount: Number of archived logs.
buffsize: Buffer size, zero for default (128K)
flag: read tlog flags
return: log stream handler.
*/
extern tlog_log *tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag);
/* write buff to log file */
extern int tlog_write(struct tlog_log *log, const char *buff, int bufflen);
/* close log stream */
extern void tlog_close(tlog_log *log);
/* change log file */
extern void tlog_rename_logfile(struct tlog_log *log, const char *logfile);
/*
Function: Print log to log stream
log: log stream
format: Log formats
*/
extern int tlog_printf(tlog_log *log, const char *format, ...) __attribute__((format(printf, 2, 3))) __attribute__((nonnull(1, 2)));
/*
Function: Print log to log stream with ap
log: log stream
format: Log formats
va_list: args list
*/
extern int tlog_vprintf(tlog_log *log, const char *format, va_list ap);
/* enable log to screen */
extern void tlog_logscreen(tlog_log *log, int enable);
/* register output callback */
typedef int (*tlog_output_func)(struct tlog_log *log, const char *buff, int bufflen);
extern int tlog_reg_output_func(tlog_log *log, tlog_output_func output);
/* set private data */
extern void tlog_set_private(tlog_log *log, void *private_data);
/* get private data */
extern void *tlog_get_private(tlog_log *log);
/* get local time */
extern int tlog_localtime(struct tlog_time *tm);
/* set max line size */
extern void tlog_set_maxline_size(struct tlog_log *log, int size);
/* set max log count */
extern void tlog_logcount(struct tlog_log *log, int count);
/*
Function: set log file and archive permission
log: log stream
file: log file permission, default is 640
archive: archive file permission, default is 440
*/
extern void tlog_set_permission(struct tlog_log *log, mode_t file, mode_t archive);
#ifdef __cplusplus
class Tlog {
public:
Tlog(tlog_level level, const char *file, int line, const char *func, void *userptr)
{
level_ = level;
file_ = file;
line_ = line;
func_ = func;
userptr_ = userptr;
}
~Tlog()
{
tlog_ext(level_, file_, line_, func_, userptr_, "%s", msg_.str().c_str());
}
std::ostream &Stream()
{
return msg_;
}
private:
tlog_level level_;
const char *file_;
int line_;
const char *func_;
void *userptr_;
std::ostringstream msg_;
};
class TlogOut {
public:
TlogOut(tlog_log *log)
{
log_ = log;
}
~TlogOut()
{
if (log_ == nullptr) {
return;
}
tlog_printf(log_, "%s", msg_.str().c_str());
}
std::ostream &Stream()
{
return msg_;
}
private:
tlog_log *log_;
std::ostringstream msg_;
};
#define Tlog_stream(level) \
if (tlog_getlevel() <= level) \
Tlog(level, BASE_FILE_NAME, __LINE__, __func__, NULL).Stream()
#define tlog_debug Tlog_stream(TLOG_DEBUG)
#define tlog_info Tlog_stream(TLOG_INFO)
#define tlog_notice Tlog_stream(TLOG_NOTICE)
#define tlog_warn Tlog_stream(TLOG_WARN)
#define tlog_error Tlog_stream(TLOG_ERROR)
#define tlog_fatal Tlog_stream(TLOG_FATAL)
#define tlog_out(stream) TlogOut(stream).Stream()
} /*__cplusplus */
#else
#define tlog_debug(...) tlog(TLOG_DEBUG, ##__VA_ARGS__)
#define tlog_info(...) tlog(TLOG_INFO, ##__VA_ARGS__)
#define tlog_notice(...) tlog(TLOG_NOTICE, ##__VA_ARGS__)
#define tlog_warn(...) tlog(TLOG_WARN, ##__VA_ARGS__)
#define tlog_error(...) tlog(TLOG_ERROR, ##__VA_ARGS__)
#define tlog_fatal(...) tlog(TLOG_FATAL, ##__VA_ARGS__)
#endif
#endif // !TLOG_H