Логирование доступа

OxPHP формирует структурированные access-логи в формате JSON для каждого HTTP-запроса и пишет их в stdout. Логирование выполняется асинхронно, поэтому никогда не блокирует обработку запросов.

Как это работает

Когда задана переменная ACCESS_LOG, OxPHP после каждого завершённого запроса пишет в stdout одну JSON-строку. Эти записи буферизуются в фоновом потоке-писателе, поэтому логирование никогда не блокирует конвейер обработки запросов.

Режим определяет, что именно записывается. ACCESS_LOG=all логирует каждый запрос; ACCESS_LOG=error логирует только ответы со статусом 400 и выше.

Каждая строка лога содержит поле request_id, которое связывает записи access-лога с логами вашего приложения. Когда включено распространение W3C Trace Context, записи также содержат поля trace_id и span_id.

Конфигурация

Переменная Значение по умолчанию Описание
ACCESS_LOG (не задано) Режим access-лога. all логирует каждый запрос; error логирует только ответы 4xx и 5xx. Оставьте не заданной или пустой, чтобы отключить
Note

Допустимы только значения all и error. Задание нераспознанного значения приводит к записи предупреждения и отключает access-логирование.

Формат лога

Каждая запись access-лога — это одна JSON-строка, записываемая в stdout:

json
{ "timestamp": "2026-02-11T12:34:56.789012Z", "level": "INFO", "fields": { "request_id": "67890abc12341a2b0042", "method": "GET", "path": "/api/users", "status": 200, "duration_us": 1234, "remote_ip": "10.0.0.1", "message": "request completed" } }

Когда активен W3C Trace Context, поля trace_id и span_id включаются наряду со стандартными полями:

json
{ "timestamp": "2026-02-11T12:34:56.789012Z", "level": "INFO", "fields": { "request_id": "67890abc12341a2b0042", "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736", "span_id": "00f067aa0ba902b7", "method": "POST", "path": "/api/orders", "status": 201, "duration_us": 8421, "remote_ip": "10.0.0.1", "message": "request completed" } }

Поля

Поле Тип Описание
request_id строка Уникальный идентификатор запроса. См. Идентификаторы запросов
method строка HTTP-метод (GET, POST и т. д.)
path строка Путь URI запроса
status число Код статуса HTTP-ответа
duration_us число Общее время обработки запроса в микросекундах
remote_ip строка IP-адрес клиента (без порта). Когда настроена переменная TRUSTED_PROXIES, отображается реальный IP клиента, извлечённый из заголовков перенаправления, а не IP прокси
trace_id строка W3C trace ID (присутствует только при TRACE_CONTEXT=true)
span_id строка W3C span ID (присутствует только при TRACE_CONTEXT=true)

Тонкая фильтрация

OxPHP использует внутреннюю цель логирования access_log для записей access-лога. Используйте переменную RUST_LOG, чтобы фильтровать access-логи независимо от остального вывода логов:

bash
# Suppress general info messages, keep access logs RUST_LOG=warn,access_log=info
Note

Цель access_log используется для фильтрации через RUST_LOG, но не включается в JSON-вывод. Чтобы идентифицировать записи access-лога в нижестоящих системах, используйте поле "message": "request completed" и характерный набор полей (method, path, status, duration_us).

Устранение неполадок

Записи access-лога не появляются

Access-логирование отключено, когда переменная ACCESS_LOG не задана или пуста.

Решение: задайте переменной значение all или error:

bash
ACCESS_LOG=all
Access-логи в режиме `error`, но успешные запросы отсутствуют

ACCESS_LOG=error логирует только ответы со статусом 400 и выше. Это ожидаемое поведение — проверьте значение и переключитесь на all, если нужно логировать все запросы.

Проверка: подтвердите активную настройку:

bash
curl -s http://localhost:9090/config | jq '.access_log'
Записи лога появляются без `trace_id` и `span_id`

Поля контекста трассировки присутствуют только при включённом распространении W3C Trace Context.

Решение: включите его так:

bash
TRACE_CONTEXT=true

И убедитесь, что вышестоящий клиент или балансировщик нагрузки отправляет заголовок traceparent в запросах.

Пример для Docker

compose.yaml
services: app: image: ghcr.io/oxphp/oxphp:0.10.0 ports: - "80:80" - "9090:9090" volumes: - ./src:/var/www/html:ro environment: ACCESS_LOG: "all" ENTRY_FILE: "index.php" INTERNAL_ADDR: "0.0.0.0:9090"

Рекомендации

  • Используйте ACCESS_LOG=error в production, чтобы уменьшить объём логов, продолжая фиксировать все неудачные запросы. Успешные запросы не логируются, но ошибки с любым статусом 400+ фиксируются всегда.
  • Включайте идентификатор запроса в логи приложения через oxphp_request_id(), чтобы связывать записи логов уровня PHP с записями access-лога.
  • Используйте структурированный агрегатор логов, такой как Elasticsearch, Loki или Datadog, для эффективного поиска и фильтрации JSON-строк логов.

Интеграция

Поскольку логи — это JSON-строки в stdout, они напрямую интегрируются с драйверами логов контейнеров и инструментами агрегации:

  • Docker — собираются автоматически через драйвер логов контейнера (json-file, fluentd и другие)
  • Kubernetes — подхватываются агентом логов на узле (Fluentd, Fluent Bit, Filebeat и другие)
  • systemd — захватываются при запуске в виде службы systemd с логированием stdout через journald

Не требуется ни sidecar, ни доставка логов на основе файлов.

См. также