Сайт Романа ПарпалакаБлог20230326

Мониторинг производительности приложений в New Relic

26 марта 2023 года, 00:03

New Relic — это набор инструментов для обеспечения «observability» веб-приложений, то есть наблюдения за их внутренним состоянием. Для меня самый полезный инструмент — APM, или мониторинг производительности.

Я использую нью-релик в проектах на работе лет 9, и всегда думал, что он стоит кучу денег. Но оказалось, они предоставляют бесплатную квоту на 100 гигабайт данных в месяц. Ее может хватить, скажем, на 100 пользователей, одновременно совершающих какие-то действия несколько раз в минуту.

Зачем нужен мониторинг производительности

Мониторинг производительности неоценим, когда сервис работает медленно или с перебоями, и нужно быстро понять причину.

Первый полезный экран — список запросов к базе данных. Можно выбрать какой-либо запрос (на скриншоте запросы на чтение к таблице users) и увидеть среднее время выполнения в миллисекундах (query time) и количество запросов в минуту (throughput). Кроме того, есть разбиение по источникам запросов (time consumption by caller), в котором видно, с каких страниц идут выбранные запросы.

Второй полезный экран с http-запросами ко внешним сервисам выглядит аналогично. Из него можно понять, идут ли запросы к внешним API и отвечают ли они в положенное время.

Третий полезный экран — список «транзакций». Под транзакциями нью-релик понимает действия в веб-приложении. Они делятся на веб-транзакции (обычно запросы и ответы через веб-сервер) и фоновые транзакции (обычно запуски консольных скриптов). По транзакциям также выводится их количество и среднее время выполнения (читай время ответа веб-приложения). Кроме того, доступна детализация, в которой видно, какие запросы или обращения к внешним системам происходят именно в этой транзакции и как долго они выполняются. Например, вот детализация по ответам публичной части моего сайта:

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

Например, на скриншоте выше время ответа веб-сервера составляло целых 4 секунды, а причина тому — запрос к БД. Сам запрос тоже можно открыть:

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

Установка и настройка

Установка нью-релика на сервер состоит из двух несложных частей (уровня apt install). Во-первых, нужно установить демон, который отвечает за отправку данных на серверы нью-релика. Во-вторых, нужно подключить нью-релик к вашему веб-приложению. Для PHP нью-релик устанавливается как расширение (*.so) и начинает работать после того, как вы скопируете в php.ini лицензионный ключ из личного кабинета на сайте. Расширение отправляет данные в процесс демона (очевидно, через сокет), а демон пересылает данные асинхронно. Благодаря такому подходу нет заметной просадки производительности.

Расширение нью-релика автоматически определяет и регистрирует запросы к базам данных, запросы через curl к внешним системам. Оно даже понимает, какой фреймворк используется, и берет названия маршрутов (routing) как названия транзакций. Данные на всех скриншотах выше собраны автоматически, для их сбора я ничего дополнительно не настраивал.

Продвинутое использование через API

Расширение нью-релика предоставляет API. Через него я определял свои транзакции из долгоживущих процессов и регистрировал метрики. Например, в сервисе генерации формул я профилирую некоторые шаги генерации как будто это обращения к некоторым базам данных (за это отвечает функция newrelic_record_datastore_segment(); возможно, тут подошли бы другие функции, но меня и так всё устраивает):

<?php

class Helper
{
    public static function newRelicProfileDataStore(callable $callback, string $product, string $operation, string $collection = 'other')
    {
        if (\extension_loaded('newrelic')) {
            return \newrelic_record_datastore_segment($callback, [
                'product'    => $product,
                'operation'  => $operation,
                'collection' => $collection,
            ]);
        }

        return $callback();
    }
}

// запуск внешнего процесса
Helper::newRelicProfileDataStore(
    static fn() => shell_exec($command),
    'shell',
    Helper::getShortCommandName($command)
);
                
// запрос по http на localhost
$optimizedSvg = Helper::newRelicProfileDataStore(
    fn() => file_get_contents($this->httpSvgoUrl, false, $context),
    'runtime',
    'http-svgo'
);

// "долгая" операция сжатия
$gzEncodedSvg = Helper::newRelicProfileDataStore(
    static fn() => gzencode($optimizedSvg, 9),
    'runtime',
    'gzencode'
);

Результат на скриншоте. Мы видим, что шаг по запуску латеха и генерации dvi-файла занимает примерно столько же, сколько отрабатывает dvisvgm. А на оптимизацию получившегося svg-файла времени тратится немного (к тому же она еще и в фоне происходит).

Выводы

Мониторинг производительности — один из инструментов для обеспечения «наблюдаемости» внутренней работы приложений. Другие инструменты — это мониторинг технических и бизнес-метрик, логи, визуализация внутреннего состояния в административном интерфейсе. Но эти инструменты нужно вручную добавлять в код, они не появляются в момент инцидента. Если вы не залогировали событие, вы не узнаете, произошло ли оно. Если храните состояние в памяти процесса, а не в БД, не сможете сделать sql-запрос и получить это состояние. А на этапе разработки приложения заранее непонятно, что именно окажется полезным в логах, а что нет.

Нью-релик как расширение к языку программирования автоматически встраивается в ваше приложение и начинает собирать информацию о типовых событиях, таких как запросы к базам данных и обращения по HTTP ко внешним сервисам. Таким образом, он работает «на будущее»: во время инцидентов у вас уже будет информация о том, что происходит внутри приложения, были ли изменения и в какой момент, и на основе этой информации вы сможете отсеивать неправдоподобные гипотезы о причинах и фокусироваться на правдоподобных.

Я не знаю, есть ли альтернатива сервису APM нью-релика. Если вдруг знаете — напишите в комментариях. На волне «импортозамещения» мы аналогов не нашли. Но зато я узнал о бесплатной квоте в 100 гигабайт, что вдохновило меня написать эту заметку.

Поделиться

Ведущее ухо Ctrl Отложенная загрузка картинок через атрибут lazyload

Читайте также

Кеширование и условие гонки
Одна из важных идей в программировании — кеширование.
2020
Воскрешение access-токенов
Недавно Фёдор Борщёв написал о том, что разделение на access-токены и refresh-токены не очень-то и нужно, можно обойтись каким-то одним.
2023
Неудачная попытка включить JIT в PHP
Обновил на этом сервере версию PHP с 7.4 на 8.2. Решил включить JIT-компиляцию и посмотреть, будет ли от нее эффект.
2023

Оставьте свой комментарий


Формулы на латехе: $$f(x) = x^2-\sqrt{x}$$ превратится в $$f(x) = x^2-\sqrt{x}$$.
Выделение текста: [i]курсивом[/i] или [b]жирным[/b].
Цитату оформляйте так: [q = имя автора]цитата[/q] или [q]еще цитата[/q].
Других команд или HTML-тегов здесь нет.

Записи