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

Loggings
Логи

Важность структуры логов

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

Рассмотрим пример логирования 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 Fields Documentation
Документация по полям ECS

ECS в PHP

Хотя ECS и предлагает готовое решение, его реализация с нуля на PHP требует определенных усилий. Доступный PHP SDK для ECS охватывает лишь ограниченный набор полей.

ECS fields covered by the SDK
Поля ECS, покрываемые SDK

В результате осознания этого пробела была создана 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. Записаться можно по ссылке.

Комментарии (2)


  1. lair
    28.12.2023 14:15

    Чтобы решить эту проблему, известная компания Elastic представила Elastic Common Schema (ECS) — спецификацию с открытым исходным кодом, разработанную при поддержке сообщества разработчиков.

    Но разве ECS предназначен не только для хранения данных в Эластике? Читаем:

    ECS defines a common set of fields to be used when storing event data in Elasticsearch, such as logs and metrics. [...] The goal of ECS is to enable and encourage users of Elasticsearch to normalize their event data

    При этом приведенный пример "создания полей в коллекции" выглядит... ужасно. Но хуже всего то, что нигде не показано, как же выглядит логирование прикладных данных (а не стандартного окружения, которое обычно меньше всего проблем вызывает).

    Вообще, выглядит так, что человек просто продвигает свой пакет.


  1. nin-jin
    28.12.2023 14:15
    -3

    Гляньте только, насколько наглядней ваш вывод было бы на языке ecs.tree: