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
- 语法:
sqlitelogpath[format][buffer=size [max=n] [flush=time]][init=script][if=condition]|off - 默认值:
sqlitelogoff - 上下文: 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_formattablevar1[type1]var2[type2]...varN[typeN] - 默认值:
sqlitelog_formatcombined$remote_addr$remote_user$time_local$request$status$body_bytes_sent$http_referer$http_user_agent - 上下文: http
此指令定义一个日志表。
第一个参数是表的名称。其余参数是变量,带有可选的列类型。一些变量具有 预设列类型,否则默认类型为 TEXT。如果变量为 BLOB 类型,则其值将作为未转义的字节写入。
sqlitelog_async
- 语法:
sqlitelog_asyncpool|on|off - 默认值:
sqlitelog_asyncoff - 上下文: 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 仓库 中找到有关此模块的其他配置提示和文档。