Nginx模块开发-日志模型
来源:互联网 发布:wind数据库 免费版 编辑:程序博客网 时间:2024/06/06 00:33
1、日志级别
简介
Level
Description
Example
emerg
Emergencies - system is unusable
紧急 - 系统无法使用
Child cannot open lock file. Exiting
alert
Action must be taken immediately
必须立即采取措施
getpwuid: couldn't determine user name from uid
crit
Critical Conditions
致命情况
socket: Failed to get a socket, exiting child
error
Error conditions
错误情况
Premature end of script headers
warn
Warning conditions
警告情况
child process 1234 did not exit, sending another SIGHUP
notice
Normal but significant condition
一般重要情况
httpd: caught SIGBUS, attempting to dump core in ...
info
Informational
普通信息
Server seems busy, (you may need to increase StartServers, or Min/MaxSpareServers)...
debug
Debug-level messages
出错级别信息
Opening config file ...
nginx日志级别
#define NGX_LOG_STDERR 0
#define NGX_LOG_EMERG 1
#define NGX_LOG_ALERT 2
#define NGX_LOG_CRIT 3
#define NGX_LOG_ERR 4
#define NGX_LOG_WARN 5
#define NGX_LOG_NOTICE 6
#define NGX_LOG_INFO 7
#define NGX_LOG_DEBUG 8
#define NGX_LOG_DEBUG_CORE 0x010
#define NGX_LOG_DEBUG_ALLOC 0x020
#define NGX_LOG_DEBUG_MUTEX 0x040
#define NGX_LOG_DEBUG_EVENT 0x080
#define NGX_LOG_DEBUG_HTTP 0x100
#define NGX_LOG_DEBUG_MAIL 0x200
#define NGX_LOG_DEBUG_MYSQL 0x400
备注:为了开发调试方便,日志被分成很多等级,Nginx的调试等级分成了两个维度,也可简称为error和debug维度,nginx支持的日志级别主要有emerg、alert、crit、error、warn、notice、info、debug,main部分默认是error级别、HTTP部分默认是crit级别,server部分默认是crit级别。
(1)第一个维度是0-8,对应nginx的配置如下所示:
#error_log logs/debug.log debug;
#error_log logs/error.log notice;
#error_log logs/error.log info;
define ngx_log_error(level, log, args...) \
if ((log)->log_level >= level) ngx_log_error_core(level, log, args)
(2)第二个维度是0x10以上,我们可以自由扩展,这个维度是按照叠加效果计算的。
#define ngx_log_debug(level, log, args...) \
if ((log)->log_level & level) \
ngx_log_error_core(NGX_LOG_DEBUG, log, args)
2、数据结构
日志的源代码放在src/core/ngx_log.h和ngx_log.c中。
日志操作函数:
typedef u_char *(*ngx_log_handler_pt) (ngx_log_t *log, u_char *buf, size_t len);
struct ngx_log_s {
ngx_uint_t log_level; //日志级别
ngx_open_file_t *file; //对应的access和error文件
ngx_atomic_uint_t connection;
ngx_log_handler_pt handler;
void *data;
char *action;
};
3、日志格式
access.log
访问日志格式(可自定义):
log_format main '$remote_addr $remote_user [$time_local] "$request" $http_host '
'$status $upstream_status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $ssl_protocol $ssl_cipher $upstream_addr '
'$request_time $upstream_response_time';
有价值变量:
(1)$remote_addr:客户端IP地址,可以得到分省流量信息;
(2)$ssl_protocol: 所用协议如TLSv1、SSLv3;
(3)$ssl_cipher:传输过程中的加密算法如RC4-SHA、AES128-SHA;
真实日志格式(1):
1.1.1.1 - [21/May/2012:09:00:01 +0800] "GET /tile/service/XX?hello=123 HTTP/1.1" hello.world.com($http_host)
200 200 3583 "https://hello.cj.com/standard/XXX?dddde=ddddd"($http_referer,来源地址) "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; 360SE)" TLSv1($ssl_protocol) AES128-SHA($ssl_cipher) 3.3.3.3:80($upstream_addr)0.145 0.053
真实日志格式(2):
1.1.1.1 - [21/May/2012:09:00:01 +0800] "GET /index.htm HTTP/1.1" hello.world.com 302 302 37 "https://hello.cj.com/user/i
.htm?srcsdfsd=yysdfdsf" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)" SSLv3($ssl_protocol) RC4-SHA($ssl_cipher) 3.3.3.3:80 ($upstream_addr)0.309 0.007
关闭访问日志:
access_log off;
error.log
错误日志格式(不能自定义):
error_log logs/error.log;
真实日志格式:
2012/05/21 09:00:09 [error] 9849#0: *354826826 upstream_ci:free the peer name:"3.3.3.3:80" fails:2 while connecting to upstre
am, client: 10.228.255.101, server: , request: "HEAD / HTTP/1.1", upstream: "http://3.3.3.3:80/", host: "hello.world.com"
关闭错误日志:
error_log /dev/null crit;
备注:不能使用error_log off,会创建一个名为off的日志文件。
4、操作函数
ngx_log_init (u_char *prefix)
函数功能:main函数初始化错误日志"./logs/error.log"。
ngx_log_t *
ngx_log_init(u_char *prefix)
{
ngx_log.file = &ngx_log_file;
ngx_log.log_level = NGX_LOG_NOTICE;
name = (u_char *) NGX_ERROR_LOG_PATH; // "logs/error.log"
nlen = ngx_strlen(name);
。。。
ngx_log_file.fd = ngx_open_file(name, NGX_FILE_APPEND,
NGX_FILE_CREATE_OR_OPEN,
NGX_FILE_DEFAULT_ACCESS);
//name ="./logs/error.log"
return &ngx_log;
}
ngx_log_create(ngx_cycle_t *cycle, ngx_str_t *name)
函数功能:创建新的日志结构。
ngx_log_t *
ngx_log_create(ngx_cycle_t *cycle, ngx_str_t *name)
{
ngx_log_t *log;
log = ngx_pcalloc(cycle->pool, sizeof(ngx_log_t)); //分配空间
if (log == NULL) {
return NULL;
}
log->file = ngx_conf_open_file(cycle, name);
//循环查找list(cycle->open_files.part),如果文件已经打开,返回已有结构,否则分配空间,并放入cycle->open_files.part管理
if (log->file == NULL) {
return NULL;
}
return log;
}
ngx_log_set_levels (ngx_conf_t *cf, ngx_log_t *log)
函数功能:根据配置文件设定日志级别,error维度和debug维度。
char *
ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log)
{
ngx_uint_t i, n, d;
ngx_str_t *value;
value = cf->args->elts;
//error_log logs/error.log info;
for (i = 2; i < cf->args->nelts; i++) {
for (n = 1; n <= NGX_LOG_DEBUG; n++) {
// NGX_LOG_DEBUG是error维度最低的级别
if (ngx_strcmp(value[i].data, err_levels[n].data) == 0) {
if (log->log_level != 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"duplicate log level \"%V\"",
&value[i]);
return NGX_CONF_ERROR;
}
log->log_level = n;
continue;
}
}
//error_log logs/error.log debug_http
for (n = 0, d = NGX_LOG_DEBUG_FIRST; d <= NGX_LOG_DEBUG_LAST; d <<= 1) {
if (ngx_strcmp(value[i].data, debug_levels[n++]) == 0) {
if (log->log_level & ~NGX_LOG_DEBUG_ALL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid log level \"%V\"",
&value[i]);
return NGX_CONF_ERROR;
}
log->log_level |= d; //叠加级别
}
}
if (log->log_level == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid log level \"%V\"", &value[i]);
return NGX_CONF_ERROR;
}
}
if (log->log_level == NGX_LOG_DEBUG) {
log->log_level = NGX_LOG_DEBUG_ALL;
}
return NGX_CONF_OK;
}
ngx_log_error_core (ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, ...)
函数功能:错误日志中最核心的函数,打印如下格式的错误日志(不能自定义),即时间+错误级别+nginx pid+错误详细信息。
2012/05/21 09:00:09 [error] 9849#0: *354826826 upstream_ci:free the peer name:"10.228.17.149:80" fails:2 while connecting to upstre
am, client: 10.228.255.101, server: , request: "HEAD / HTTP/1.1", upstream: "http://10.228.17.149:80/", host: "alipay.com"
void
ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
const char *fmt, va_list args)
#endif
{
#if (NGX_HAVE_VARIADIC_MACROS)
va_list args;
#endif
u_char *p, *last, *msg;
u_char errstr[NGX_MAX_ERROR_STR];
if (log->file->fd == NGX_INVALID_FILE) {
return;
}
last = errstr + NGX_MAX_ERROR_STR;
ngx_memcpy(errstr, ngx_cached_err_log_time.data,
ngx_cached_err_log_time.len); //2012/05/21 09:00:09
p = errstr + ngx_cached_err_log_time.len;
p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]); //错误打印级别
/* pid#tid */
p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ",
ngx_log_pid, ngx_log_tid); //nginx的pid
if (log->connection) {
p = ngx_slprintf(p, last, "*%uA ", log->connection);
}
msg = p;
#if (NGX_HAVE_VARIADIC_MACROS)
va_start(args, fmt);
p = ngx_vslprintf(p, last, fmt, args); //详细的错误信息
va_end(args);
#else
p = ngx_vslprintf(p, last, fmt, args);
#endif
if (err) {
p = ngx_log_errno(p, last, err);
}
if (level != NGX_LOG_DEBUG && log->handler) {
p = log->handler(log, p, last - p);
}
if (p > last - NGX_LINEFEED_SIZE) {
p = last - NGX_LINEFEED_SIZE;
}
ngx_linefeed(p);
(void) ngx_write_fd(log->file->fd, errstr, p - errstr); //写入文件
ngx_http_tracker_add_error_count();
if (!ngx_use_stderr
|| level > NGX_LOG_WARN
|| log->file->fd == ngx_stderr)
{
return;
}
msg -= (7 + err_levels[level].len + 3);
(void) ngx_sprintf(msg, "nginx: [%V] ", &err_levels[level]);
(void) ngx_write_console(ngx_stderr, msg, p - msg); //写到终端
}
ngx_log_debug_core (ngx_log_t *log, ngx_err_t err, const char *fmt, ...)
函数功能:将日志级别设置为NGX_LOG_DEBUG,调用ngx_log_error_core打印错误日志。
void ngx_cdecl
ngx_log_debug_core(ngx_log_t *log, ngx_err_t err, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt, args);
va_end(args);
}
ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf, ngx_err_t err
函数功能:配置错误的入口,一般level为EMEG。
ngx_log_error(level, cf->log, 0, "%*s in %s:%ui",
p - errstr, errstr,
cf->conf_file->file.name.data, cf->conf_file->line);
ngx_log_error (level, log, ...)
函数功能:比较日志错误级别,调用ngx_log_error_core打印错误日志。
#define ngx_log_error(level, log, ...) \
if ((log)->log_level >= level) ngx_log_error_core(level, log, __VA_ARGS__)
ngx_log_abort (ngx_err_t err, const char *fmt, ...)
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err,
"%*s", p - errstr, errstr);
ngx_log_stderr
函数功能:将错误信息,直接打印到终端。
ngx_http_log_handler(ngx_http_request_t *r)
函数功能:ngx_http_log_init(ngx_conf_t *cf)将ngx_http_log_handler放入NGX_HTTP_LOG_PHASE中,在请求过来的时候写access_log。
h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
*h = ngx_http_log_handler;
5、切割日志
用nginx做web服务器,如果没有处理好日志,日志文件可能会很恐怖~10G、20G。解决方法:
(1)access_log /dev/null,将日志丢到系统的黑洞,延长硬盘的寿命。
(2)用定时任务来切割日志,kill –USR1来发送命令;
#crontab –l
00 * * * * /home/admin/spanner/sbin/log_rotate.sh
Filename: /home/admin/spanner/sbin/log_rotate.sh
#!/bin/bash
log_dir="/home/admin/spanner/logs"
backup_dir="/home/admin/spanner_logs"
date_dir=`date +%Y/%m/%d/%H`
/bin/mkdir -p ${backup_dir}/${date_dir} > /dev/null 2>&1
/bin/mv ${log_dir}/access.log ${backup_dir}/${date_dir}/access.log
/bin/mv ${log_dir}/error.log ${backup_dir}/${date_dir}/error.log
kill -USR1 `cat ${log_dir}/nginx.pid`
/bin/gzip ${backup_dir}/${date_dir}/access.log &
/bin/gzip ${backup_dir}/${date_dir}/error.log &
6、使用实例
ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]);
函数功能:向终端打印错误信息;
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[i]);
函数功能:在启动过程中,配置错误打印接口;
ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "[white list]: access allowed by rule");
函数功能:运行过程中,向错误日志文件写入信息,级别是DEBUG;
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[black list]: access forbidden by rule");
函数功能:运行过程中,向错误日志文件写入信息,级别是ERROR;
- Nginx模块开发-日志模型
- Nginx模块开发(15)—日志模型
- nginx模块开发-定时器模型
- Nginx模块开发—数组模型
- Nginx模块开发—队列模型
- Nginx模块开发 —进程模型
- nginx日志模块分析
- nginx日志模块分析详解
- Nginx 模块开发之日志模块---实时记录http请求信息写入flume
- Nginx基础知识. Nginx模块开发
- Nginx模块开发入门
- Nginx模块开发入门
- nginx模块开发
- nginx模块开发说明
- Nginx模块开发
- NGINX模块开发
- Nginx Http模块开发
- Nginx 模块开发
- Hibernate学习笔记----session缓存
- 图片轮播
- POJ 2533Longest Ordered Subsequence
- Tarjan算法求无向图割边割点、最近公共祖先的总结
- UVA 575-Skew Binary
- Nginx模块开发-日志模型
- 简单总结Unity使用Resources类资源管理
- 敏捷开发之Scrum扫盲,及敏捷开发中XP与SCRUM的区别
- SDUTOJ 1294选票统计
- linux网卡报错设置
- hdu 1495 非常可乐
- 2016 Multi-University Training Contest 1
- Spring——IOC/DI理解
- UVA 10970-Big Chocolate