ngx_errlog_module模块是nginx中第二个被执行的模块,它是nginx用来为其它模块提供日志记录功能的基础模块,http,mail,stream等模块都会调用该模块的接口实现日志记录功能。该模块提供了一个指令:error_log,用于指定全局范围的日志配置,指令的定义如下:
static ngx_command_t ngx_errlog_commands[] = {
{ ngx_string("error_log"),
NGX_MAIN_CONF|NGX_CONF_1MORE,
ngx_error_log,
0,
0,
NULL },
ngx_null_command
};
http,mail,stream等类型的核心模块也实现了各自的error_log指令,但它们的有效上下文环境各有不同。
同一个上下文环境内可以存在多条error_log指令,它们的配置会以链表形式保存,nginx写日志时会将日志内容写入到链表的每一个节点对应的设备上。
nginx支持输出到多种类型的设备,如下所示
stderr:顾名思义,就是将日志输出到标准错误文件中
memory:将日志写入到内存缓冲区中,该类型只有在启用了debug的时候才能生效,通常用于调试
syslog:将日志写入到linux的syslog文件中
普通文件:将日志写入到指定的日志文件中,通常在生产环境中使用
nginx支持8个错误日志级别,每个级别自动包含自身及以上级别的日志,默认级别是error。错误日志级别从高到底分别是
NGX_LOG_STDERR
0 将日志输出到标准错误
emerg NGX_LOG_EMERG
1
alert NGX_LOG_ALERT
2
crit NGX_LOG_CRIT
3
error NGX_LOG_ERR
4
warn NGX_LOG_WARN
5
notice NGX_LOG_NOTICE
6
info NGX_LOG_INFO
7
debug NGX_LOG_DEBUG
8
该模块提供了几个核心api供其它模块记录日志,分别是ngx_log_error,ngx_log_debug,ngx_log_error_core。
根据所在操作系统和c语言版本对变长参数列表的支持情况不同,这几个api的参数可能有所不同,但实现的目的都是一样的。以C99为例,定义如下:
#define ngx_log_error(level, log, ...) \
if ((log)->log_level >= level) ngx_log_error_core(level, log, __VA_ARGS__)
void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log,
ngx_err_t err, const char *fmt, ...);
#define ngx_log_debug(level, log, ...) \
if ((log)->log_level & level) \
ngx_log_error_core(NGX_LOG_DEBUG, log, __VA_ARGS__)
可以看到,ngx_log_error和ngx_log_debug都是通过调用ngx_log_error_core函数实现日志记录的,2者区别在于对level参数的处理不同。
ngx_log_error的处理逻辑是只有在og参数的log_level大于level时,才调用ngx_log_error_core,否则忽略。
ngx_log_debug的处理逻辑是只要log参数的log_level设置了与level参数对应的位时,就调用ngx_log_error_core,否则忽略。
ngx_log_error_core的执行流程如下(忽略对于debug_connection的处理逻辑):
1.
生成统一的的日志内容前缀,保存在buffer中。日志前缀格式是:"timestr [loglevel] pid#tid *connid"
2
生成参数指定内容
将可变长参数列表格式化后的字符串添加在第一步保存的buffer末尾。如果err不为0,就把err对应的错误码和错误短语添加到buffer末尾
3
添加自定义内容
如果level不是NGX_LOG_DEBUG并且log参数的handler不为NULL,说明log需要添加自定义内容,
nginx会调用log->handler把自定义内容添加到第1步保存的buffer的末尾,并在最后添加换行符
4
输出日志内容
日志内容可能有多个输出目标。nginx会从输入参数log开始,遍历所有的输出目标。如果目标的writer不为空,
就调用writer输出日志,然后继续遍历下一个目标,否则就用默认的方式输出。默认的输出方式是调用ngx_write_fd函数
向文件描述符写入内容
5
将前缀之外的日志内容写到标准错误文件
如果nginx使用标准错误文件作为输出目标,并且在第4步的目标中没有标准错误文件,并且level级别不高于NGX_LOG_WARN,
就把除了前缀之外的日志内容输出到标准错误文件中。这主要是用于在启动nginx的过程中,错误日志能够输出到控制台,不会丢失