Розробка модуля логування 1С-Бітрікс
Розбір інциденту на продакшні без нормальних логів — справа болісна. Стандартний \Bitrix\Main\Diag\Debug::writeToFile() пише до плаского файлу без структури, без рівнів, без ротації. За тиждень роботи — файл на 2 ГБ, який неможливо ні проаналізувати, ні знайти потрібний запис. Модуль логування вирішує це системно: структуровані записи в БД, рівні severity, теги, контекст, ротація, пошук через адміністративний інтерфейс.
Архітектура
Модуль vendor.logger реалізує інтерфейс PSR-3 (Psr\Log\LoggerInterface), що дозволяє підключати його до будь-яких бібліотек із підтримкою PSR-3 (Guzzle, Doctrine, Symfony компоненти).
ORM-таблиці:
-
b_vendor_log_entry— записи логу: id, level (debug/info/notice/warning/error/critical/alert/emergency), channel, message, context (JSON), extra (JSON), created_at, user_id, request_uri, ip -
b_vendor_log_channel— канали: id, code, name, min_level, handlers (JSON), is_active -
b_vendor_log_archive— архівовані записи (після ротації): аналогічна структура + archived_at
Реалізація PSR-3
class BitrixLogger extends \Psr\Log\AbstractLogger
{
private string $channel;
public function __construct(string $channel = 'app')
{
$this->channel = $channel;
}
public function log($level, $message, array $context = []): void
{
if (!$this->isLevelEnabled($level)) {
return;
}
$extra = [
'user_id' => $GLOBALS['USER']?->GetID(),
'request_uri' => $_SERVER['REQUEST_URI'] ?? '',
'ip' => $_SERVER['REMOTE_ADDR'] ?? '',
];
LogEntryTable::add([
'LEVEL' => $level,
'CHANNEL' => $this->channel,
'MESSAGE' => $this->interpolate($message, $context),
'CONTEXT' => $context,
'EXTRA' => $extra,
]);
}
private function interpolate(string $message, array $context): string
{
$replace = [];
foreach ($context as $key => $val) {
$replace['{' . $key . '}'] = is_scalar($val) ? $val : json_encode($val, JSON_UNESCAPED_UNICODE);
}
return strtr($message, $replace);
}
}
Використання в коді
$logger = new \Vendor\Logger\BitrixLogger('payment');
$logger->info('Ініційовано платіж', ['order_id' => 42, 'sum' => 1500.00, 'gateway' => 'sberbank']);
$logger->error('Помилка платіжного шлюзу', ['order_id' => 42, 'response' => $gatewayResponse]);
// Глобальний логер через фасад
\Vendor\Logger\Log::channel('sync')->warning('Синхронізація з 1С: товар не знайдено', ['xml_id' => 'ABC-123']);
Обробники (Handlers)
Запис до БД — не єдиний обробник. Модуль підтримує кілька handlers на один канал:
-
DatabaseHandler — запис до
b_vendor_log_entry(основний) - FileHandler — запис до файлу з автоматичною ротацією (щоденно, максимум N файлів)
- SlackHandler — надсилання critical/emergency до Slack-каналу через Webhook
- TelegramHandler — надсилання алертів до Telegram-бота при рівні >= error
Конфігурація каналів зберігається в b_vendor_log_channel у полі handlers (JSON). Приклад:
{
"handlers": [
{"type": "database", "min_level": "debug"},
{"type": "telegram", "min_level": "error", "chat_id": "-100123456789"}
]
}
Ротація та архівація
Агент ротації запускається раз на добу:
// Записам старше 30 днів — перенесення до b_vendor_log_archive
// Записам старше 90 днів в архіві — видалення
// Параметри налаштовуються в адміністративному інтерфейсі модуля
\Vendor\Logger\RotationAgent::run();
Перенесення виконується батчами по 1 000 записів, щоб не блокувати таблицю надовго.
Перехоплення помилок PHP
Модуль може реєструвати глобальний обробник помилок PHP:
set_error_handler(function($errno, $errstr, $errfile, $errline) {
$level = ErrorLevelMapper::toLogLevel($errno);
\Vendor\Logger\Log::channel('php')->log($level, $errstr, [
'file' => $errfile,
'line' => $errline,
'errno' => $errno,
]);
return false; // Стандартний обробник Бітрікс також спрацьовує
});
set_exception_handler(function(\Throwable $e) {
\Vendor\Logger\Log::channel('php')->critical($e->getMessage(), [
'exception' => get_class($e),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString(),
]);
});
Адміністративний інтерфейс
Пошук по логах — основний інструмент при налагодженні:
- Фільтрація за рівнем, каналом, датою, IP, користувачем, текстом повідомлення
- Пошук по контексту (JSON-поле через PostgreSQL
@>або LIKE по serialized) - Детальний перегляд запису: повний контекст, стек викликів, заголовки запиту
- Статистика: топ помилок за період, динаміка за рівнями, розбивка за каналами
- Управління конфігурацією каналів та обробників
Терміни розробки
| Етап | Термін |
|---|---|
| ORM-таблиці, реалізація PSR-3 | 1 день |
| DatabaseHandler, FileHandler | 1 день |
| Slack та Telegram алерти | 1 день |
| Ротація та архівація (агент) | 1 день |
| Перехоплення помилок PHP | 1 день |
| Адміністративний інтерфейс, пошук | 2 дні |
| Тестування | 1 день |
Разом: 8 робочих днів. Інтеграція із зовнішніми системами моніторингу (Sentry, Graylog) — додатково 1–2 дні.







