Saltar a contenido

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: sqlitelog path [format] [buffer=size [max=n] [flush=time]] [init=script] [if=condition] | off
  • Predeterminado: sqlitelog off
  • 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_format table var1 [type1] var2 [type2] ... varN [typeN]
  • Predeterminado: sqlitelog_format combined $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_async pool | on | off
  • Predeterminado: sqlitelog_async off
  • 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 buffer para acelerar las inserciones o configurando un tiempo de espera más largo con PRAGMA busy_timeout en un script init.
  • 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.