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

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

Установка на Debian/Ubuntu

Эти документы применимы к APT пакету nginx-module-log-sqlite, предоставленному репозиторием GetPageSpeed Extras.

  1. Настройте APT репозиторий, как описано в настройке APT репозитория.
  2. Установите модуль:
sudo apt-get update
sudo apt-get install nginx-module-log-sqlite
Показать наборы и архитектуры
| Дистрибутив | Версия            | Компонент   | Архитектуры   |
|-------------|-------------------|-------------|----------------|
| debian      | bookworm          | main        | amd64, arm64   |
| debian      | bookworm-mainline | main        | amd64, arm64   |
| debian      | trixie            | main        | amd64, arm64   |
| debian      | trixie-mainline   | main        | amd64, arm64   |
| ubuntu      | focal             | main        | amd64, arm64   |
| ubuntu      | focal-mainline    | main        | amd64, arm64   |
| ubuntu      | jammy             | main        | amd64, arm64   |
| ubuntu      | jammy-mainline    | main        | amd64, arm64   |
| ubuntu      | noble             | main        | amd64, arm64   |
| ubuntu      | noble-mainline    | main        | amd64, arm64   |

Сводка

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

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

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

Локации

Директива sqlitelog не может использоваться в контекстах местоположения, но можно использовать условие 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](https://www.sqlite.org/wal.html) включается с помощью `PRAGMA journal_mode=wal` в `init` скрипте. [Контрольные точки WAL](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`). Предполагается, что пользователю процесса рабочего `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

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