Логирование PHP на русском: практические решения и код
Реализация логирования на PHP с поддержкой русского языка
Какое решение обеспечивает полноценное логирование с русскими сообщениями и гибкой настройкой?
Наиболее эффективный способ логирования на PHP с использованием русского языка - библиотека Monolog. Она поддерживает различные каналы вывода (файлы, базы данных, системные журналы, внешние сервисы) и позволяет корректно обрабатывать UTF-8 вывод. Ниже приведён пример настройки Monolog с русским языком и временной зоной.
// Подключение через Composer: composer require monolog/monolog
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\LineFormatter;
// Устанавливаем временную зону для России (Москва)
date_default_timezone_set('Europe/Moscow');
// Создаём логгер
$log = new Logger('russian_app');
// Настраиваем формат с русскими символами и датой
$formatter = new LineFormatter(
"[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n",
'Y-m-d H:i:s',
true,
true
);
// Обработчик для записи в файл с русскими путями (UTF-8)
$handler = new StreamHandler(__DIR__ . '/logs/app_ru.log', Logger::INFO);
$handler->setFormatter($formatter);
$log->pushHandler($handler);
// Пример логирования на русском
$log->info('Пользователь успешно авторизован', ['user_id' => 42, 'role' => 'администратор']);
$log->error('Ошибка соединения с базой данных: ' . $e->getMessage());
Journals ru php (журналы php на русском)
Типичные проблемы:
- Кириллица в имени файла или пути - убедитесь, что файловая система поддерживает UTF‑8 (например, ext4 на Linux). В Windows может потребоваться настройка кодировки через
mb_internal_encoding('UTF-8'). - Временные метки выводятся в UTC по умолчанию - явно вызывайте
date_default_timezone_set(). - Неверный уровень логирования - используйте
Logger::DEBUG,::INFO,::WARNING,::ERRORи т.д.
Чтобы избежать потери памяти при большом количестве логов, настройте ротацию через RotatingFileHandler.
Как организовать простое логирование в файл без сторонних библиотек?
Для минимальных проектов можно использовать встроенную функцию error_log или file_put_contents. Однако такой способ неудобен для структурирования и форматирования сообщений.
$message = 'Ошибка: не удалось загрузить файл';
// Дописываем в файл с меткой времени
file_put_contents('log.txt', '[' . date('Y-m-d H:i:s') . '] ' . $message . PHP_EOL, FILE_APPEND);
Недостатки и решения:
- Нет контроля уровней - все сообщения смешиваются. Применяйте отдельные файлы для разных уровней.
- Не работает с многопоточностью - используйте блокировки
flock(). - Ручное форматирование даты - легко ошибиться. Придерживайтесь единого формата.
Как записывать логи в базу данных (MySQL) для централизованного хранения и поиска?
Логи в БД удобны для анализа, но могут замедлять работу при интенсивной записи. Пример с PDO и русскими сообщениями:
try {
$pdo = new PDO('mysql:host=localhost;dbname=logs;charset=utf8mb4', 'user', 'pass');
$stmt = $pdo->prepare('INSERT INTO log (level, message, created_at, user_id) VALUES (?, ?, NOW(), ?)');
$stmt->execute(['ERROR', 'Не удалось подключиться к серверу', 101]);
} catch (PDOException $e) {
error_log('Ошибка записи лога в БД: ' . $e->getMessage());
}
Проблемы:
- Ошибка при записи лога может остаться незамеченной. Используйте
error_logкак fallback. - Кодировка: убедитесь, что таблица использует
utf8mb4, иначе кириллица превратится в знаки вопроса. - Высокая нагрузка: для продакшена лучше применять буферизацию или писать в очередях (RabbitMQ).
Как перенаправить стандартный вывод ошибок PHP в русскоязычный журнал?
Можно переопределить обработчик ошибок, чтобы все PHP-ошибки записывались в единый лог-файл с русским текстом.
function customErrorHandler($errno, $errstr, $errfile, $errline) {
$msg = 'Ошибка (уровень ' . $errno . '): ' . $errstr . ' в файле ' . $errfile . ' на строке ' . $errline;
file_put_contents('php_errors_ru.log', '[' . date('Y-m-d H:i:s') . '] ' . $msg . PHP_EOL, FILE_APPEND);
return true;
}
set_error_handler('customErrorHandler');
trigger_error('Тестовое предупреждение на русском', E_USER_WARNING);
Сложности:
- Функция не ловит фатальные ошибки (E_ERROR). Используйте
register_shutdown_function. - Стек вызовов не включается - добавьте
debug_backtrace()в сообщение. - Конфликт с другими обработчиками - проверьте совместимость с фреймворками.
Как отправлять логи в систему журналирования Linux (syslog) с русским текстом?
Используйте syslog() или библиотеку Monolog с NativeMailerHandler. Внимание: syslog может обрезать длинные строки.
openlog('myapp_ru', LOG_PID | LOG_PERROR, LOG_LOCAL0);
syslog(LOG_WARNING, 'Предупреждение: закончилось место на диске');
closelog();
Ограничения:
- Кодировка syslog на старых системах не гарантирует UTF‑8 - проверяйте настройки локали.
- Нет структурированных данных (только строка).
- Права: только root может менять конфигурацию syslog.
Как написать свою простую библиотеку для логирования на русском?
Для контроля над каждым аспектом можно создать класс-логгер с поддержкой уровней и каналов на русском языке.
class RussianLogger {
private $file;
private $levels = ['debug' => 'ОТЛАДКА', 'info' => 'ИНФО', 'error' => 'ОШИБКА'];
public function __construct($file) {
$this->file = $file;
if (!file_exists(dirname($file))) {
mkdir(dirname($file), 0755, true);
}
}
public function log($level, $message) {
$rusLevel = $this->levels[$level] ?? strtoupper($level);
$line = '[' . date('Y-m-d H:i:s') . '] ' . $rusLevel . ': ' . $message . PHP_EOL;
file_put_contents($this->file, $line, FILE_APPEND | LOCK_EX);
}
}
$logger = new RussianLogger('logs/my.log');
$logger->log('info', 'Система запущена на русском');
Риски:
- Отсутствие ротации - файл может вырасти до больших размеров.
- Нет поддержки контекста - добавьте аргумент
$contextи сериализуйте его. - Ошибки при создании директории - обрабатывайте исключения.
Расширенные примеры логирования на PHP с русским языком
1. Monolog с несколькими обработчиками и русским форматированием
Настройка логгера, который записывает сообщения в файл и одновременно отправляет критичные ошибки на email (с русским текстом).
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\NativeMailerHandler;
use Monolog\Formatter\LineFormatter;
date_default_timezone_set('Asia/Yekaterinburg'); // Екатеринбург, Россия
$log = new Logger('myapp');
// Единый формат для всех обработчиков
$formatter = new LineFormatter(
"[%datetime%] %channel%.%level_name%: %message% %context%\n",
'd.m.Y H:i:s',
true,
true
);
// Файловый обработчик
$fileHandler = new StreamHandler(__DIR__ . '/data/application.log', Logger::INFO);
$fileHandler->setFormatter($formatter);
$log->pushHandler($fileHandler);
// Email-обработчик для ошибок (только для критических уведомлений)
$mailHandler = new NativeMailerHandler(
'admin@example.com', // кому
'Ошибка в приложении (Русский лог)', // тема
'from@example.com', // от кого
Logger::ERROR // уровень
);
$mailHandler->setFormatter($formatter);
$log->pushHandler($mailHandler);
// Логирование
$log->info('Приложение инициализировано', ['version' => '2.1.0']);
$log->error('Транзакция не завершена: недостаточно средств на счете', ['account' => '40817810099910004321']);
[11.03.2025 14:32:10] myapp.INFO: Приложение инициализировано {"version":"2.1.0"}
[11.03.2025 14:32:12] myapp.ERROR: Транзакция не завершена: недостаточно средств на счете {"account":"40817810099910004321"}
2. Ротация логов с русским суффиксом даты
Использование RotatingFileHandler для автоматического создания архива с русским названием файлов (например, app_2025-03-11.log).
use Monolog\Logger;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Formatter\JsonFormatter; // альтернативный формат
$log = new Logger('rotate');
// Хранить файлы за 30 дней, уровень DEBUG
$handler = new RotatingFileHandler(__DIR__ . '/logs/rus_app.log', 30, Logger::DEBUG);
// Формат с русскими датами в имени файла (по умолчанию Y-m-d)
$handler->setFilenameFormat('rus_app_{date}', 'Y-m-d');
$log->pushHandler($handler);
$log->debug('Отладочное сообщение: проверка соединения');
$log->info('Сессия создана', ['user' => 'Иван Петров']);
$log->warning('Время выполнения близко к лимиту', ['time' => '28.5s']);
(созданы файлы в директории logs/): rus_app_2025-03-11.log rus_app_2025-03-10.log (с предыдущего дня)
3. Логирование с русскими именами каналов и контекстом
Создание отдельных логгеров для разных модулей приложения (например, 'пользователи', 'заказы', 'платежи').
$userLogger = new Logger('пользователи');
$orderLogger = new Logger('заказы');
// Оба пишут в один файл, но с разными метками канала
$handler = new StreamHandler(__DIR__ . '/logs/main.log', Logger::INFO);
$handler->setFormatter(new LineFormatter("[%datetime%] [%channel%] %level_name%: %message%\n"));
$userLogger->pushHandler($handler);
$orderLogger->pushHandler($handler);
$userLogger->info('Регистрация нового пользователя', ['email' => 'test@русский.рф', 'role' => 'клиент']);
$orderLogger->info('Создан заказ №1234', ['сумма' => 1500.50, 'позиции' => 3]);
$orderLogger->warning('Заказ №1234: недостаточно товара на складе', ['склад' => 'Москва']);
[11.03.2025 15:00:01] [пользователи] INFO: Регистрация нового пользователя {"email":"test@xn--80ahd...","role":"клиент"}
[11.03.2025 15:00:02] [заказы] INFO: Создан заказ №1234 {"сумма":1500.5,"позиции":3}
[11.03.2025 15:00:03] [заказы] WARNING: Заказ №1234: недостаточно товара на складе {"склад":"Москва"}
4. Использование SAPI-зависимого логирования (Web vs CLI)
Настройка разного вывода для веб-запросов и консольных скриптов с русскими сообщениями.
$log = new Logger('multi');
if (php_sapi_name() === 'cli') {
// В CLI вывод в stdout с цветовой подсветкой (если терминал поддерживает)
$handler = new StreamHandler('php://stdout', Logger::DEBUG);
$handler->setFormatter(new LineFormatter("%level_name%: %message%\n"));
} else {
// В вебе записываем в файл и добавляем IP-адрес клиента
$handler = new StreamHandler(__DIR__ . '/logs/web.log', Logger::WARNING);
$formatter = new LineFormatter(
"[%datetime%] %extra.client_ip% %message%\n"
);
$handler->setFormatter($formatter);
$log->pushProcessor(function ($record) {
$record['extra']['client_ip'] = $_SERVER['REMOTE_ADDR'] ?? 'неизвестен';
return $record;
});
}
$log->pushHandler($handler);
$log->info('Скрипт запущен из ' . (php_sapi_name() === 'cli' ? 'командной строки' : 'веба'));
5. Интеграция с логированием Yandex Cloud (через HTTP)
Отправка логов в сервис Yandex Cloud Logging с использованием cURL и русскоязычных сообщений.
function sendToYandexCloud($message, $level = 'INFO') {
$logData = [
'timestamp' => date('c'),
'level' => $level,
'message' => $message,
'resource' => ['type' => 'php-app', 'id' => 'production']
];
$ch = curl_init('https://logging.yandexcloud.net/v1/entries');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($logData, JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . getenv('YC_IAM_TOKEN'),
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
if (curl_error($ch)) {
error_log('Ошибка отправки лога в Yandex Cloud: ' . curl_error($ch));
}
curl_close($ch);
}
sendToYandexCloud('Приложение запущено успешно', 'INFO');
sendToYandexCloud('Критическая ошибка в модуле оплаты', 'ERROR');
(при успешной отправке ответ от API: 200 OK, ошибки записываются в локальный журнал)
6. Логирование с поддержкой Unicode (эмодзи, японский и русский одновременно)
Monolog корректно обрабатывает любые символы UTF‑8 при использовании правильного формата.
$log = new Logger('unicode_test');
$handler = new StreamHandler('php://output', Logger::DEBUG);
$handler->setFormatter(new LineFormatter("[%datetime%] %message%"));
$log->pushHandler($handler);
$log->info('Логирование на русском: привет мир!');
$log->info('Emoji: ? PHP 8.2 работает');
$log->info('Японский: こんにちは世界');
[11.03.2025 16:00:00] Логирование на русском: привет мир! [11.03.2025 16:00:00] Emoji: ? PHP 8.2 работает [11.03.2025 16:00:00] Японский: こんにちは世界