В прошлом месяце мне представилась возможность выступить на AmsterdamPHP с докладом на тему уровней логирования. Полученные положительные отзывы вдохновили меня на то, чтобы поделиться этой информацией для более широкой аудитории, поэтому я решил написать эту статью.
Важность структуры логов
В небольших командах структуры логирования могут различаться, и разработчики могут позволить себе применять разные подходы. Однако по мере роста команды поддержание устойчивых и последовательных уровней логирования становится крайне важным. Это не только помогает командам разработчиков не запутаться в логах, но и обеспечивает ясность для других отделов, которые полагаются на данные логов, не имея прямого доступа к кодовой базе.
Рассмотрим пример логирования IP-адреса клиента. Мы по сути не ограничены в вариантах представления этой информации, например:
src: 10.42.42.42
client_ip: 10.42.42.42
apache2.access.remote_ip: 10.42.42.42
context.user.ip: 10.42.42.42
src_ip: 10.42.42.42
Нет однозначного правильного или неправильного ответа; главное — создать стандартизированный и лаконичный способ логирования данных на всех платформах, например, client.ip: 10.42.42.42
.
Задача и решение
Если цель вполне ясна и прямолинейна, то почему достижение последовательности в этом процессе все еще остается сложной задачей? Ключ лежит в подготовке документированной структуры и обеспечении ее повсеместного принятия в команде. Именование переменных, как было с юмором отмечено в одной бородатой шутке о программировании, действительно является сложным аспектом программирования. Это трудоемкий процесс, требующий разносторонних знаний для выработки стандартного подхода в различных архитектурных областях.
Чтобы решить эту проблему, известная компания Elastic представила Elastic Common Schema (ECS) — спецификацию с открытым исходным кодом, разработанную при поддержке сообщества разработчиков. ECS определяет имена полей, типы данных и примеры использования, представляя собой хорошо документированное руководство.
ECS в PHP
Хотя ECS и предлагает готовое решение, его реализация с нуля на PHP требует определенных усилий. Доступный PHP SDK для ECS охватывает лишь ограниченный набор полей.
В результате осознания этого пробела была создана PECS (PHP Elastic Common Schema), которая привнесла полную поддержку ECS в мир PHP.
Абстракция и соглашение
Прежде чем погрузиться в пакет, давайте сначала определим, что является хорошей абстракцией. Черпая вдохновение из книги "Справочник эффективного инженера" (The Effective Engineer) Эдмонда Лау (Edmond Lau), хорошая абстракция должна быть:
Легкой в освоении
Простой в использовании без подробной документации
Трудной для использования не по назначению
Достаточно мощной для удовлетворения поставленных требований
Легко расширяемой
Подходить для целевой аудитории
PECS стремится соответствовать этим критериям. В этом пакете спецификации ECS полностью преобразованы в конфигурации JSON, что позволяет встроенному генератору создавать ECS PHP классы. Классы полностью аннотированны как нативными типами, так и определяемыми типами классов и перечислений, что сводит к минимуму риск некорректного использования. Пакет спроектирован таким образом, чтобы его можно было легко расширять, позволяя инстанцировать поля и отображать их в ожидаемом формате ECS.
Ниже приведен пример создания ECS-полей в коллекции:
(new EcsFieldsCollection([
new Log(
filePath: 'app/Http/Controllers/Controller.php',
level: 'info',
logger: 'name',
originFileLine: 42,
originFileName: 'Controller.php',
originFunction: 'index',
),
new Client(
ip: '10.42.42.42',
geo: new Geo(
cityName: 'Amsterdam',
continentCode: 'EU',
continentName: 'Europe',
countryIsoCode: 'NL',
countryName: 'Netherlands',
location: new GeoPoint(52.37403, 4.88969),
),
user: new User(
id: 'e125a612-899e-11ee-b9d1-0242ac120002',
name: 'hamid',
roles: (new ValueList())->push('admin')->push('user'),
)
),
new Os(
kernel: '4.19.0-6-amd64',
name: 'Arch',
platform: 'x86_64',
type: OsType::LINUX
),
]))->render();
и вывод, иллюстрирующий результат генерации указанных полей:
{
"log": {
"file": {
"path": "app\/Http\/Controllers\/Controller.php"
},
"level": "info",
"logger": "name",
"origin": {
"file": {
"line": 42,
"name": "Controller.php"
},
"function": "index"
}
},
"client": {
"ip": "10.42.42.42",
"geo": {
"city_name": "Amsterdam",
"continent_code": "EU",
"continent_name": "Europe",
"country_iso_code": "NL",
"country_name": "Netherlands",
"location": {
"lat": 52.37403,
"lon": 4.88969
}
},
"user": {
"id": "e125a612-899e-11ee-b9d1-0242ac120002",
"name": "hamid",
"roles": [
"admin",
"user"
]
}
}
}
Интеграция
Понимая, что чистый PHP в наши дни нормой не является, PECS включен в список сторонних пакетов для Monolog, самого популярного пакета для логирования на PHP.
$log->pushHandler($handler->setFormatter(new EcsFormatter()));
$log->info('message', [
new Event(action: 'test event'),
]);
Эта интеграция позволяет без проблем работать с Symfony и Laravel, которые под капотом используют Monolog.
Заключение
В заключение можно сказать, что PECS представляет собой комплексное решение для реализации Elastic Common Schema в PHP, обеспечивая структурированное и последовательное протоколирование на различных платформах. В этой статье вашему вниманию был представлен краткий обзор, а в следующей мы рассмотрим настройку PECS на практических примерах. Пока же рекомендую вам почитать документацию, чтобы получить общее представление о структуре PECS.
Приглашаем всех, кому интересна тема искусственного интеллекта в разработке на PHP, на открытый урок 10 января. Обсудим, какие есть инструменты и возможности, а также посмотрим примеры настройки и работы ИИ на примере Github Copilot в PhpStorm. Записаться можно по ссылке.