Логирование PHP на русском: практические решения и код

Раздел: Программирование на PHP -> Логирование 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] Японский: こんにちは世界

Журналы PHP на русском - comments

En
Journals ru php (php)