Перейти к содержимому

Журнал событий - чтение, очистка, свои записи

Читаем журнал событий сайта, добавляем в него свои записи и разбираемся, почему он разрастается до гигабайтов.

Решение

Смотрим последние записи журнала:

$res = CEventLog::GetList(['TIMESTAMP_X' => 'DESC'], []); // свежие записи сверху
// на большом журнале выборку ограничивают фильтром по типу события и датам
$i = 0;
while ($row = $res->Fetch()) {
printf("%-20s %-24s %s\n",
$row['TIMESTAMP_X'], $row['AUDIT_TYPE_ID'], mb_substr($row['DESCRIPTION'], 0, 40));
if (++$i >= 20) break;
}

В журнал попадают действия пользователей и системные происшествия: вход в админку, смена прав, ошибки модулей. Срабатывания обработчиков событий туда не пишутся вовсе - это два разных механизма с похожими названиями.

Фильтруем по типу события:

$res = CEventLog::GetList(['TIMESTAMP_X' => 'DESC'], [
'AUDIT_TYPE_ID' => 'USER_LOGIN_FAIL', // неудачные попытки входа
'>=TIMESTAMP_X' => date('d.m.Y', strtotime('-7 days')),
]);
printf("неудачных входов за неделю: %d\n", $res->SelectedRowsCount());

Всплеск неудачных входов с разных адресов - это обычный перебор паролей извне, а не сбой самого сайта. Такие записи как раз и выглядят странными, когда журнал событий открывают в первый раз.

Добавляем свою запись:

CEventLog::Log(
'SECURITY', // уровень: SECURITY, INFO, WARNING, ERROR
'MY_IMPORT_FAILED', // свой тип события, придумывается автором
'my.module',
$orderId, // идентификатор объекта, к которому относится
'обмен оборвался на позиции 145'
);

Свой тип события ничем не ограничен и появляется в фильтре журнала сразу после первой же записи. Это удобное место для следов фоновых процессов: хранилище уже есть, интерфейс просмотра тоже, а чистится журнал сам по расписанию.

Настраиваем срок хранения:

// сколько дней держать записи: чистку выполняет агент главного модуля
COption::SetOptionString('main', 'event_log_cleanup_days', '30');
COption::SetOptionString('main', 'event_log_logout', 'Y'); // писать выходы

Журнал растёт быстро на посещаемом сайте и без ограничения занимает заметное место в базе данных. Чистку выполняет агент главного модуля, поэтому при выключенных агентах записи копятся дальше, сколько бы дней ни было задано в настройке хранения.

Разбор инцидента по журналу упирается в две вещи: включён ли был нужный тип события и не успел ли агент вычистить записи по сроку хранения. Обе проверяются за минуту и экономят час поисков в заведомо пустом журнале. На проектах, где разбор инцидентов вероятен, срок хранения ставят с запасом и включают запись входов и смены прав до того, как что-нибудь случится.

Состав записываемых типов задаётся настройками главного модуля отдельно для каждого вида событий. Отключённый тип не пишется вовсе, и восстановить пропущенные события задним числом уже невозможно.

Типичные проблемы

Журнал занимает несколько гигабайт в базе.

Не задан срок хранения либо не работают агенты. Чистку выполняет агент главного модуля, и без него записи копятся бесконечно.

Нужного события в журнале нет.

Его тип отключён в настройках главного модуля. Пропущенные записи задним числом не восстанавливаются.

Много записей о неудачном входе.

Обычный перебор паролей извне. Это не сбой сайта, но повод включить ограничение попыток входа.

Своя запись не появилась в журнале.

Не указан уровень или тип события. Вызов без обязательных аргументов молча ничего не пишет.

Записи есть, а кто их сделал - непонятно.

Действие выполнено агентом или консольным скриптом, где текущего пользователя нет. Идентификатор пользователя в таких записях пуст.

Частые вопросы

Чем журнал отличается от журнала ошибок PHP?

Журнал событий пишет действия внутри платформы, журнал PHP - ошибки выполнения кода. Ошибка модуля попадает в оба, но с разной подробностью.

Можно ли получать письмо о новой записи?

Штатной рассылки нет, но обработчик события записи в журнал легко её добавляет. Так делают уведомления о неудачных входах и о критичных ошибках.

Как посмотреть, кто удалил элемент?

По записи журнала с типом события удаления, если этот тип включён. В ней хранятся идентификатор пользователя и объекта.

Стоит ли писать в журнал из своего кода?

Для редких значимых событий - да: хранение и чистка уже настроены. Для потока отладочных сообщений лучше свой файл: журнал не рассчитан на тысячи записей в минуту.

Смежное

Первоисточник