log-sqlite: Módulo de registro SQLite para NGINX
Instalación
Puedes instalar este módulo en cualquier distribución basada en RHEL, incluyendo, pero no limitado a:
- RedHat Enterprise Linux 7, 8, 9 y 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 y 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
Habilita el módulo añadiendo lo siguiente en la parte superior de /etc/nginx/nginx.conf:
load_module modules/ngx_http_sqlitelog_module.so;
Este documento describe nginx-module-log-sqlite v0.0.1 lanzado el 14 de febrero de 2025.
Resumen
Este módulo utiliza el formato SQLite para los registros de acceso. Fork de GitHub de https://git.serope.com/me/ngx-sqlitelog
Directivas
sqlitelog
- Sintaxis:
sqlitelogpath[format][buffer=size [max=n] [flush=time]][init=script][if=condition]|off - Predeterminado:
sqlitelogoff - Contexto: http, server
Esta directiva define una base de datos de registro.
El parámetro path es la ruta del archivo de base de datos. Debe estar ubicado en un directorio donde el usuario o grupo que posee los procesos de trabajo de Nginx (definido por la directiva user) tenga permiso de escritura para que pueda crear el archivo de base de datos y cualquier posible archivo temporal.
El parámetro format es el nombre de un formato de registro definido por la directiva sqlitelog_format. Si no se proporciona, se utiliza el formato combinado predeterminado.
El parámetro buffer crea una zona de memoria donde las entradas de registro se agrupan y se escriben en la base de datos en una única transacción BEGIN ... COMMIT. Esto mejora significativamente el rendimiento, ya que las inserciones agrupadas son más rápidas que las separadas. El buffer se confirma cuando ocurre uno de los siguientes eventos: se excede su size; acumula n entradas de registro; transcurre el time de vaciado; Nginx se recarga o sale.
El parámetro init es una ruta a un archivo de script SQL que se ejecuta en cada conexión a la base de datos. Esto se puede utilizar para ejecutar comandos pragma o para crear tablas, vistas y disparadores adicionales para complementar la tabla de registro; tales declaraciones deben incluir IF NOT EXISTS ya que pueden ejecutarse más de una vez.
El parámetro if establece una condición de registro. Al igual que en el módulo de registro estándar, si condition evalúa a 0 o una cadena vacía, se omite el registro para la solicitud actual.
sqlitelog_format
- Sintaxis:
sqlitelog_formattablevar1[type1]var2[type2]...varN[typeN] - Predeterminado:
sqlitelog_formatcombined$remote_addr$remote_user$time_local$request$status$body_bytes_sent$http_referer$http_user_agent - Contexto: http
Esta directiva define una tabla de registro.
El primer argumento es el nombre de la tabla. Los argumentos restantes son variables con tipos de columna opcionales. Algunas variables tienen tipos de columna predefinidos, de lo contrario, el predeterminado es TEXT. Si una variable es de tipo BLOB, su valor se escribe como bytes sin escapar.
sqlitelog_async
- Sintaxis:
sqlitelog_asyncpool|on|off - Predeterminado:
sqlitelog_asyncoff - Contexto: http
Esta directiva habilita un pool de hilos, permitiendo que las escrituras de archivos SQLite ocurran sin bloquear. El argumento puede ser un nombre de pool existente, on para el pool predeterminado, o off. Esta directiva solo está disponible si Nginx se compila con --with-threads.
Errores
Cuando ocurre un error de SQLite, el módulo se desactiva (equivalente a sqlitelog off) para el proceso de trabajo que encontró el error. Esto es para evitar que error.log se inunde rápidamente con mensajes de error si la base de datos es inutilizable (por ejemplo, ubicada en un directorio donde los procesos de trabajo no tienen permiso de escritura).
- SQLITE_ERROR (1): Este es un código de error genérico que cubre varios casos, como errores de sintaxis SQL en un script
init. - SQLITE_BUSY (5): Múltiples procesos de trabajo intentaron usar la base de datos simultáneamente y excedieron el tiempo de espera de ocupado (1000 ms por defecto). Esto se puede resolver creando un
bufferpara acelerar las inserciones o configurando un tiempo de espera más largo conPRAGMA busy_timeouten un scriptinit. - SQLITE_READONLY (8): Nginx puede abrir la base de datos, pero no puede escribir en ella. Esto se debe probablemente a permisos de archivo.
- SQLITE_CANTOPEN (14): Nginx no puede abrir o crear la base de datos. Esto se debe probablemente a permisos de directorio. El usuario o grupo que posee los procesos de trabajo (definido por la directiva
user) debe tener permiso de escritura en el directorio. - SQLITE_READONLY_DBMOVED (1032): El archivo fue movido, renombrado o eliminado en tiempo de ejecución. Cuando esto sucede, Nginx intenta recrear el archivo; si tiene éxito, el error se ignora y el registro continúa normalmente.
Uso
Ubicaciones
La directiva sqlitelog no se puede usar en contextos de ubicación, pero una condición regex puede lograr un efecto similar. En este ejemplo, solo se registran las solicitudes que comienzan con "/mylocation".
map $request_uri $is_my_loc {
default 0;
~^/mylocation.*$ 1;
}
sqlitelog access.db if=$is_my_loc;
Herencia
Solo se permite un sqlitelog por contexto, siendo los contextos inferiores los que tienen prioridad. En este ejemplo, las solicitudes al servidor A se registran en global.db, mientras que las solicitudes al servidor B se registran en b.db.
http {
sqlitelog global.db;
...
server {
server_name a;
...
}
server {
server_name b;
sqlitelog b.db;
....
}
````
### Modo WAL
[WAL mode](https://www.sqlite.org/wal.html) se habilita mediante `PRAGMA journal_mode=wal` en un script `init`. [WAL checkpointing](https://www.sqlite.org/wal.html#ckpt) ocurre cuando Nginx se recarga o sale.
### Logrotate
[Logrotate](https://man.archlinux.org/man/logrotate.8) debe configurarse para detener Nginx, rotar los registros y reiniciar Nginx. De esta manera, Nginx cierra de manera ordenada sus conexiones a la(s) base(s) de datos del día anterior y abre nuevas a la(s) base(s) de datos del día actual.
A continuación se muestra un script de ejemplo para Debian (`/etc/logrotate.d/nginx`). Asume que el usuario del proceso de trabajo, `www-data`, ha recibido permiso de escritura en `/var/log/nginx`, que normalmente solo es escribible por `root`.
```sh
/var/log/nginx/*.log
/var/log/nginx/*.db
{
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 640 www-data adm
sharedscripts
# Forzar a Logrotate a trabajar en este directorio aunque
# sus permisos han sido modificados para permitir que un usuario
# no root escriba en él
su root adm
# Enviar una señal de salida a Nginx y esperar a que su archivo PID
# sea destruido
firstaction
systemctl stop nginx.service
while [ -f /var/run/nginx.pid ]; do
sleep 0.1s
done
endscript
# Reiniciar Nginx nuevamente
lastaction
systemctl restart nginx.service
endscript
}
Tipos de columna
Las siguientes variables tienen tipos de columna predefinidos, pero se pueden sobrescribir si es necesario.
| Variable | Tipo |
|---|---|
| $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
Puedes encontrar consejos de configuración adicionales y documentación para este módulo en el repositorio de GitHub para nginx-module-log-sqlite.