Analysis-NginxLogs 是一个基于 Python 的 Nginx 日志分析与监控系统。它能够实时解析 Nginx 访问日志和错误日志,将数据存储到 MySQL 数据库中,并支持通过邮件发送异常告警。
- 实时日志分析:支持 Nginx
access_log和error_log的实时解析。 - 多平台支持:兼容 Nginx 和 OpenResty。
- 数据持久化:解析后的日志数据自动存储到 MySQL 数据库。
- 邮件告警:支持配置邮件服务,定时发送日志统计或异常告警。
- Docker 支持:提供 Dockerfile 和构建脚本,方便容器化部署。
- Python 3.8+
- MySQL 5.7+
- Nginx 或 OpenResty
为了让程序正确解析日志,需要在 Nginx 或 OpenResty 中配置特定的日志格式。
在 server 配置中添加以下内容,避免静态资源请求写入日志:
server {
location / {
# 除去静态文件日志
if ($request_uri ~* \.(gif|jpg|jpeg|png|bmp|swf|js|css|woff|ttf|ico)$) {
access_log off;
}
}
}注意:日志格式配置不可以有换行。
如果你使用 Nginx:
log_format main escape=json '{ "remote_addr":"$remote_addr","remote_user":"$remote_user","time_local":"$time_local","request":"$request","http_host":"$http_host","status":"$status","upstream_status":"$upstream_status","body_bytes_sent":"$body_bytes_sent","http_referer":"$http_referer","http_user_agent":"$http_user_agent","upstream_addr":"$upstream_addr","request_time":"$request_time","upstream_response_time":"$upstream_response_time","request_body":"$request_body" }';如果你使用 OpenResty:
log_format main escape=json '{"remote_addr": "$remote_addr","remote_user": "$remote_user","time_local": "$time_local","request": "$request","http_host": "$http_host","status": "$status","upstream_status":"$upstream_status","body_bytes_sent": "$body_bytes_sent","http_referer": "$http_referer","http_user_agent": "$http_user_agent","upstream_addr": "$upstream_addr","request_time": "$request_time","upstream_response_time":"$upstream_response_time","request_body":"$request_body","request_method": "$request_method","http_x_forwarded_for": "$http_x_forwarded_for","host": "$host","http_uri": "$uri","req_body": "$resp_body"}';OpenResty Lua 脚本配置 (用于捕获响应体):
# 初始化变量,用于后面捕获响应体
set $resp_body "";
# 使用 Lua 代码块来检查响应头
header_filter_by_lua_block {
local content_encoding = ngx.resp.get_headers()["Content-Encoding"]
if content_encoding then
ngx.ctx.is_compressed = (content_encoding == "gzip")
else
ngx.ctx.is_compressed = false
end
}
# 使用 Lua 代码块来捕获响应体
body_filter_by_lua_block {
local chunk = ngx.arg[1]
local eof = ngx.arg[2]
local buffered = ngx.ctx.buffered or ""
-- 如果响应被压缩
if ngx.ctx.is_compressed then
-- 如果没有解压缩流对象,则创建它
if not ngx.ctx.inflater and not eof then
local zlib = require "zlib"
ngx.ctx.inflater = zlib.inflate()
end
-- 如果存在解压缩流对象,尝试解压缩
if ngx.ctx.inflater then
local success, result
-- 如果当前chunk是空字符串,我们需要传递一个空字符串到inflate
-- 否则,如果是最后一个数据块(eof),我们应该完成解压缩流
if chunk == "" then
chunk = nil
end
success, result = pcall(ngx.ctx.inflater, chunk)
if not success then
ngx.log(ngx.ERR, "failed to decompress: ", result)
-- 如果解压缩失败,可以选择设置一个标志或者直接退出
ngx.ctx.bypass = true
return
end
-- 解压缩成功,追加到缓冲区
if result then
buffered = buffered .. result
end
end
else
-- 如果没有压缩,直接追加到缓冲区
buffered = buffered .. chunk
end
-- 只保留前1000个字符
-- buffered = string.sub(buffered, 1, 1000)
-- 保存缓冲的数据
ngx.ctx.buffered = buffered
-- 如果这是最后一个分块
if eof then
-- 如果之前解压缩失败,可能需要做一些处理
if ngx.ctx.bypass then
ngx.var.resp_body = nil
ngx.ctx.inflater = nil -- 清理解压缩流对象
return
end
ngx.var.resp_body = buffered
ngx.ctx.inflater = nil -- 清理解压缩流对象
end
}wget https://github.com/brimworks/lua-zlib/archive/master.zip
unzip master.zip
cd lua-zlib-master
cmake -DLUA_INCLUDE_DIR=/usr/local/openresty/luajit/include/luajit-2.1
make
cp zlib.so /usr/local/openresty/lualib/zlib.so
注:安装lua_zlib需要lua或luajit的支持,所以在cmake时需要指定lua的路径。
修改 config.yaml 文件以配置数据库、日志路径和邮件服务。
# 数据库配置
database:
host: '127.0.0.1'
port: 3306
username: 'root'
password: 'your_password'
name: 'analysis_nginx_logs'
charset: 'utf8mb4'
# Nginx日志路径配置 (请确保 Python 有权限读取)
nginx:
app_log_path: '/path/to/nginx/app.access.log'
app_err_log_path: '/path/to/nginx/app.error.log'
web_log_path: '/path/to/nginx/web.access.log'
web_err_log_path: '/path/to/nginx/web.error.log'
# 邮件发送配置
email:
host: 'smtp.exmail.qq.com'
port: 465
username: 'your_email@example.com'
password: 'your_password'- 安装依赖:
pip install -r requirements.txt
- 运行程序:
python main.py
- 构建镜像:
sh build.sh
- 运行容器:
sh run.sh
Analysis-NginxLogs/
├── config.yaml # 配置文件
├── main.py # 程序入口
├── requirements.txt # Python 依赖
├── Dockerfile # Docker 构建文件
├── build.sh # Docker 构建脚本
├── run.sh # Docker 运行脚本
├── db/ # 数据库模型
├── msg/ # 消息通知模块
├── task/ # 日志分析任务模块
└── logs/ # 程序运行日志