Skip to content

fengziadmin/Analysis-Nginx-Logs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Analysis-NginxLogs

Analysis-NginxLogs 是一个基于 Python 的 Nginx 日志分析与监控系统。它能够实时解析 Nginx 访问日志和错误日志,将数据存储到 MySQL 数据库中,并支持通过邮件发送异常告警。

功能特性

  • 实时日志分析:支持 Nginx access_logerror_log 的实时解析。
  • 多平台支持:兼容 Nginx 和 OpenResty。
  • 数据持久化:解析后的日志数据自动存储到 MySQL 数据库。
  • 邮件告警:支持配置邮件服务,定时发送日志统计或异常告警。
  • Docker 支持:提供 Dockerfile 和构建脚本,方便容器化部署。

环境要求

  • Python 3.8+
  • MySQL 5.7+
  • Nginx 或 OpenResty

快速开始

1. Nginx 配置

为了让程序正确解析日志,需要在 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
}

增加openresty对gzip的支持

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的路径。

https://www.cnblogs.com/kgdxpr/p/4195216.html

2. 项目配置

修改 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'

3. 运行项目

本地运行

  1. 安装依赖:
    pip install -r requirements.txt
  2. 运行程序:
    python main.py

Docker 运行

  1. 构建镜像:
    sh build.sh
  2. 运行容器:
    sh run.sh

目录结构

Analysis-NginxLogs/
├── config.yaml          # 配置文件
├── main.py              # 程序入口
├── requirements.txt     # Python 依赖
├── Dockerfile           # Docker 构建文件
├── build.sh             # Docker 构建脚本
├── run.sh               # Docker 运行脚本
├── db/                  # 数据库模型
├── msg/                 # 消息通知模块
├── task/                # 日志分析任务模块
└── logs/                # 程序运行日志

About

Nginx分析工具

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published