跳转至

log-sqlite: NGINX 的 SQLite 日志模块

安装

您可以在任何基于 RHEL 的发行版中安装此模块,包括但不限于:

  • RedHat Enterprise Linux 7、8、9 和 10
  • CentOS 7、8、9
  • AlmaLinux 8、9
  • Rocky Linux 8、9
  • Amazon Linux 2 和 Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-log-sqlite
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-log-sqlite

通过在 /etc/nginx/nginx.conf 的顶部添加以下内容来启用该模块:

load_module modules/ngx_http_sqlitelog_module.so;

本文档描述了 nginx-module-log-sqlite v0.0.1,于 2025 年 2 月 14 日发布。


摘要

此模块使用 SQLite 格式进行访问日志记录。 GitHub 的分支 https://git.serope.com/me/ngx-sqlitelog

指令

sqlitelog

  • 语法: sqlitelog path [format] [buffer=size [max=n] [flush=time]] [init=script] [if=condition] | off
  • 默认值: sqlitelog off
  • 上下文: http, server

此指令定义一个日志数据库。

path 参数是数据库文件的路径。它必须位于一个目录中,该目录的用户或组(由 user 指令 定义)具有写入权限,以便能够创建数据库文件和任何可能的 临时文件

format 参数是由 sqlitelog_format 指令定义的日志格式的名称。如果未给出,则使用默认的组合格式。

buffer 参数创建一个内存区域,其中日志条目被批量处理并在单个 BEGIN ... COMMIT 事务中写入数据库。这大大提高了性能,因为分组插入 比单独插入更快。当发生以下情况之一时,缓冲区将被提交:其 size 超过;它累积了 n 条日志条目;flush time 经过;Nginx 重新加载或退出。

init 参数是一个 SQL 脚本文件的路径,该文件在每次数据库连接时执行。这可以用于运行 pragma 命令 或创建附加的表、视图和触发器,以补充日志表;此类语句应包含 IF NOT EXISTS,因为它们可能会被执行多次。

if 参数设置日志记录条件。与标准的 log 模块 一样,如果 condition 的值为 0 或空字符串,则跳过当前请求的日志记录。

sqlitelog_format

  • 语法: sqlitelog_format table var1 [type1] var2 [type2] ... varN [typeN]
  • 默认值: sqlitelog_format combined $remote_addr $remote_user $time_local $request $status $body_bytes_sent $http_referer $http_user_agent
  • 上下文: http

此指令定义一个日志表。

第一个参数是表的名称。其余参数是变量,带有可选的列类型。一些变量具有 预设列类型,否则默认类型为 TEXT。如果变量为 BLOB 类型,则其值将作为未转义的字节写入。

sqlitelog_async

  • 语法: sqlitelog_async pool | on | off
  • 默认值: sqlitelog_async off
  • 上下文: http

此指令启用 线程池,允许 SQLite 文件写入在不阻塞的情况下进行。参数可以是现有的 pool 名称,on 表示默认池,或 off。此指令仅在 Nginx 使用 --with-threads 编译时可用。

错误

当发生 SQLite 错误时,遇到错误的工作进程将禁用该模块(等同于 sqlitelog off)。这是为了防止如果数据库不可用(例如,位于工作进程没有写入权限的目录中),错误日志被迅速淹没。

  • SQLITE_ERROR (1): 这是一个通用错误代码,涵盖多个情况,例如 init 脚本中的 SQL 语法错误。
  • SQLITE_BUSY (5): 多个工作进程尝试同时使用数据库并超过了忙碌超时(默认 1000 毫秒)。可以通过创建一个 buffer 来加快插入速度,或在 init 脚本中使用 PRAGMA busy_timeout 设置更长的超时来解决此问题。
  • SQLITE_READONLY (8): Nginx 可以打开数据库,但无法写入。这可能是由于文件权限问题。
  • SQLITE_CANTOPEN (14): Nginx 无法打开或创建数据库。这可能是由于目录权限问题。拥有工作进程的用户或组(由 user 指令 定义)必须对该目录具有写入权限。
  • SQLITE_READONLY_DBMOVED (1032): 文件在运行时被移动、重命名或删除。当发生这种情况时,Nginx 尝试重新创建该文件;如果成功,则忽略该错误,日志记录正常继续。

用法

位置

sqlitelog 指令不能在位置上下文中使用,但可以通过正则条件实现类似效果。在此示例中,仅记录以 "/mylocation" 开头的请求。

map $request_uri $is_my_loc {
    default            0;
    ~^/mylocation.*$   1;
}

sqlitelog access.db if=$is_my_loc;

继承

每个上下文仅允许一个 sqlitelog,较低的上下文优先。在此示例中,服务器 A 的请求记录到 global.db,而服务器 B 的请求记录到 b.db。

http {
    sqlitelog global.db;
    ...

    server {
        server_name a;
        ...
    }

    server {
        server_name b;
        sqlitelog b.db;
        ....
    }

WAL 模式

WAL 模式 通过在 init 脚本中使用 PRAGMA journal_mode=wal 启用。 WAL 检查点 在 Nginx 重新加载或退出时发生。

日志轮换

Logrotate 应配置为停止 Nginx、轮换日志并重新启动 Nginx。这样,Nginx 可以优雅地关闭与前一天数据库的连接,并打开与当前数据库的连接。

以下是 Debian 的示例脚本(/etc/logrotate.d/nginx)。它假设工作进程用户 www-data 已被授予对 /var/log/nginx 的写入权限,该目录通常仅由 root 可写。

/var/log/nginx/*.log
/var/log/nginx/*.db
{
    daily
    missingok
    rotate 52
    compress
    delaycompress
    notifempty
    create 640 www-data adm
    sharedscripts

    # 强制 Logrotate 在此目录中工作,即使
    # 其权限已被修改以允许非 root
    # 用户在其中写入
    su root adm

    # 向 Nginx 发送退出信号,并等待其 PID 文件
    # 被销毁
    firstaction
        systemctl stop nginx.service
        while [ -f /var/run/nginx.pid ]; do  
            sleep 0.1s
        done
    endscript

    # 再次启动 Nginx
    lastaction
        systemctl restart nginx.service
    endscript
}

列类型

以下变量具有预设列类型,但如果需要可以被覆盖。

变量 类型
$binary_remote_addr BLOB
$body_bytes_sent INTEGER
$bytes_sent INTEGER
$connection INTEGER
$connection_requests INTEGER
$connection_time REAL
$connections_active INTEGER
$connections_reading INTEGER
$connections_waiting INTEGER
$connections_writing INTEGER
$content_length INTEGER
$gzip_ratio REAL
$limit_rate INTEGER
$msec REAL
$pid INTEGER
$proxy_port INTEGER
$proxy_protocol_port INTEGER
$proxy_protocol_server_port INTEGER
$remote_port INTEGER
$request_time REAL
$server_port INTEGER
$status INTEGER

GitHub

您可以在 nginx-module-log-sqlite 的 GitHub 仓库 中找到有关此模块的其他配置提示和文档。