Перейти к содержанию

log-sqlite: Модуль логирования SQLite для NGINX

Установка

Вы можете установить этот модуль в любой дистрибутив на базе 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, выпущенный 14 февраля 2025 года.


Резюме

Этот модуль использует формат 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 — это путь к файлу базы данных. Он должен находиться в директории, где пользователь или группа, владеющая процессами worker Nginx (определены директивой user), имеет права на запись, чтобы он мог создать файл базы данных и любые возможные временные файлы.

Параметр format — это имя формата лога, определенного директивой sqlitelog_format. Если не указано, используется формат по умолчанию.

Параметр buffer создает зону памяти, где записи логов группируются и записываются в базу данных в одной транзакции BEGIN ... COMMIT. Это значительно улучшает производительность, так как групповые вставки быстрее, чем отдельные. Буфер фиксируется, когда происходит одно из следующих событий: превышен его size; накоплено n записей лога; истекло время flush; Nginx перезагружается или завершает работу.

Параметр init — это путь к файлу SQL-скрипта, который выполняется при каждом подключении к базе данных. Это можно использовать для выполнения pragma-команд или для создания дополнительных таблиц, представлений и триггеров для дополнения таблицы логирования; такие операторы должны содержать IF NOT EXISTS, так как они могут выполняться более одного раза.

Параметр if устанавливает условие логирования. Как и в стандартном модуле логирования, если 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) для процесса worker, который столкнулся с ошибкой. Это сделано для предотвращения быстрого заполнения error.log сообщениями об ошибках, если база данных непригодна для использования (например, находится в директории, где процессы worker не имеют прав на запись).

  • SQLITE_ERROR (1): Это общий код ошибки, который охватывает несколько случаев, таких как синтаксические ошибки SQL в скрипте init.
  • SQLITE_BUSY (5): Несколько процессов worker попытались одновременно использовать базу данных и превысили тайм-аут занятости (по умолчанию 1000 мс). Это можно решить, создав buffer для ускорения вставок или установив более длительный тайм-аут с помощью PRAGMA busy_timeout в скрипте init.
  • SQLITE_READONLY (8): Nginx может открыть базу данных, но не может записать в нее. Это, вероятно, связано с правами доступа к файлу.
  • SQLITE_CANTOPEN (14): Nginx не может открыть или создать базу данных. Это, вероятно, связано с правами доступа к директории. Пользователь или группа, владеющая процессами worker (определены директивой user), должны иметь права на запись в директорию.
  • SQLITE_READONLY_DBMOVED (1032): Файл был перемещен, переименован или удален во время выполнения. Когда это происходит, Nginx пытается воссоздать файл; если это удается, ошибка игнорируется, и логирование продолжается нормально.

Использование

Локации

Директива sqlitelog не может использоваться в контекстах location, но условие regex может достичь аналогичного эффекта. В этом примере логируются только запросы, которые начинаются с "/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 mode](https://www.sqlite.org/wal.html) включается с помощью `PRAGMA journal_mode=wal` в скрипте `init`. [WAL checkpointing](https://www.sqlite.org/wal.html#ckpt) происходит, когда Nginx перезагружается или завершает работу.

### Logrotate

[Logrotate](https://man.archlinux.org/man/logrotate.8) должен быть настроен для остановки Nginx, ротации логов и повторного запуска Nginx. Таким образом, Nginx корректно закрывает свои соединения с базой данных предыдущего дня и открывает новые соединения с базами данных текущего дня.

Ниже приведен пример скрипта для Debian (`/etc/logrotate.d/nginx`). Предполагается, что пользователю процесса worker, `www-data`, предоставлены права на запись в `/var/log/nginx`, который обычно доступен только для записи пользователю `root`.

```sh
/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

    # Отправить сигнал quit 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

Вы можете найти дополнительные советы по конфигурации и документацию для этого модуля в репозитории GitHub для nginx-module-log-sqlite.