ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ. Это не исчерпывающая статья о регистрации или отслеживании.
Сервис, который мы создадим, очень прост, с конечной точкой и примерами, показывающими журналы в нашей командной строке, журналы JSON, трассировку и способы создания файлов журналов.
Для этой задачи мы будем использовать пакеты Tracing
, tracing-subscriber
и tower-http
.
груз.томл
[dependencies] axum = "0.6.1" tokio = { version = "1.21.2", features = ["full"] } tracing = "0.1.37" tracing-subscriber = { version = "0.3.16", features = ["env-filter"]} tower-http = { version = "0.3.4", features = ["trace"] }
Журналы
Вот простой пример того, как добавить ведение журнала.
Согласно документации, когда мы используем compact()
, вывод оптимизируется для коротких строк. Поля из текущего контекста диапазона добавляются к полям отформатированного события.
Если мы выполним cargo run
и перейдем к locahost:3000
, мы должны увидеть следующее сообщение в нашем терминале.
Теперь позвольте мне немного объяснить роль Tower-http, Tracing и Tracing-subscriber.
Отслеживание
Трассировка — это фреймворк для инструментирования программ Rust для сбора структурированной диагностической информации на основе событий.
Мы можем использовать tracing
для:
- Отправка распределенных трассировок в сборщик Open Telemetry.
- Отлаживайте свое приложение с помощью Tokio Console.
- Профиль, где ваше приложение проводит время.
Согласно статье Начало работы с трассировкой, крейт tracing
предоставляет API, который мы будем использовать для создания трассировок. Пакет tracing-subscriber
предоставляет некоторые базовые утилиты для пересылки этих трассировок внешним слушателям (например, stdout
).
Кроме того, в той же статье упоминается, что подписчики — это типы, которые обрабатывают трассировки, создаваемые приложением и его зависимостями, и могут выполнять метрики, отслеживать ошибки и повторно отправлять трассировки во внешний мир.
В нашем случае крейт tracing
собирает события нашего приложения, но мы хотим выводить трассировки и журналы на наш терминал, это задача для крейта tracing-subscriber
.
Башня-http
Согласно документации, tower-http
— это библиотека, которая предоставляет промежуточное программное обеспечение и утилиты для HTTP, созданные поверх tower
.
В документации также упоминается, что все промежуточное ПО использует крейты http
и http-body
в качестве абстракций HTTP. Это означает, что они совместимы с любой библиотекой или фреймворком, которые также используют эти крейты, такие как гипер, тоник и деформация.
Аксум построен с гипер, поэтому мы можем использовать tower-http
.
Эта библиотека предназначена для предоставления богатого набора промежуточного программного обеспечения для решения распространенных проблем при создании HTTP-клиентов и серверов, таких как добавление высокоуровневой трассировки и ведения журнала в наши приложения. Кроме того, автоматически сжимайте или распаковывайте тела ответов и автоматически выполняйте ответы на перенаправления.
Информацию о tower-http
можно найти в его документации и в этой статье.
Теперь вернемся к нашему коду.
let app = Router::new() .route("/", get(hello_world)) .layer( TraceLayer::new_for_http() .make_span_with(trace::DefaultMakeSpan::new() .level(Level::INFO)) .on_response(trace::DefaultOnResponse::new() .level(Level::INFO)), );
Здесь мы создаем экземпляр маршрутизатора. И используйте метод layer
, который применяет tower::Layer
ко всем маршрутам в маршрутизаторе. Он используется для добавления промежуточного программного обеспечения к маршрутам.
Мы передали TraceLayer
в качестве аргумента. Цитирование официальной документации:
Layer
, который добавляет высокоуровневую трассировку кService
.
Служба, о которой идет речь в цитате, — это служба башни. Кроме того, мы используем new_for_http()
, он создает новый TraceLayer
с использованием ServerErrorsAsFailures
, который поддерживает классификацию обычных HTTP-ответов на основе кода состояния, согласно документации.
Чтобы это работало, нам нужно преобразовать наш экземпляр маршрутизатора в службу башни. И мы сделали это, когда использовали into_make_service()
.
axum::Server::bind(&addr) .serve(app.into_make_service()) .await .unwrap();
Теперь мы объясним, что делают make_span_with()
и on_response()
.
В документации говорится, что on_response()
настраивает действия при получении ответа. И make_span_with()
настраивает, как сделать Span
, в которые будет включена вся обработка запросов.
Этим функциям мы передали нужный уровень логирования. Используя метод level
в обоих случаях, DefaulMakeSpan
и DefaultOnResponse
, мы устанавливаем уровень LEVEL::INFO
. По умолчанию LEVEL::DEBUG
.
Подробнее о DefaultMakeSpan
и DefaultOnResponse
здесь и здесь соответственно.
Симпатичный
Согласно документации, Pretty генерирует очень красивые многострочные журналы, оптимизированные для удобочитаемости человеком. Предназначен для использования в локальной разработке и отладке или для приложений командной строки, где читабельность и визуальная привлекательность являются приоритетом.
Джейсон
Чтобы добавить вывод JSON, мы должны изменить наш файл Cargo.toml
и добавить функцию json
в tracing_subscriber
.
груз.томл
... tracing-subscriber = { version = "0.3.16", features = ["env-filter", "json"]} ...
Json выводит журналы JSON с разделителями строк. Предназначен для производственного использования с системами, в которых структурированные журналы используются в виде JSON средствами анализа и просмотра.
Реестр
Цитирую документацию:
Этот модуль предоставляет тип
Registry
, реализациюSubscriber
, которая отслеживает данные по промежутку и предоставляет ихLayer
s. КогдаRegistry
используется в качестве базыSubscriber
стекаLayer
, типlayer::Context
будет предоставлять методы, позволяющиеLayer
s искать данные диапазона, хранящиеся в реестре. ХотяRegistry
является разумным значением по умолчанию для хранения диапазонов и событий, другие хранилища, которые сами реализуютLookupSpan
иSubscriber
(сSpanData
, реализуемым данными для каждого диапазона, которые они хранят), могут использоваться в качестве замены.
Создание файлов журнала
Чтобы создать файлы журнала, мы должны добавить tracing_appender
в наш файл Cargo.toml
.
Груз.томл
... tracing-appender = "0.2"
Я только что изменил этот пример из репозитория tracing.
Здесь мы создаем переменную для определения периода прокрутки и передаем ей каталог, в котором мы хотим хранить наши файлы, и имя файлов. И устанавливаем уровень логирования, в данном случае INFO
.
Затем мы передаем переменную info_file
в функцию with_writer()
.
with_writer()
устанавливает MakeWriter
и используется fmt::Layer
или fmt::Subscriber
для печати форматированных текстовых представлений событий.
Теперь, если мы установим уровень trace, вот так.
Файл будет выглядеть так.
Заключение
Tracing
предлагает множество настроек. И для меня было сложной задачей найти, какие примеры будут самыми простыми для этой статьи. К счастью, у tracing_subscriber есть хорошая документация, а в репозитории есть полезные примеры. Кроме того, я просто использую info и trace в качестве уровней журнала, но они не единственные, мы можем использовать debug, warn, error, и выключить.
Было весело писать эту статью. Я сделал это, чтобы узнать больше о структуре трассировки и крейте Tower-http и о том, как они работают вместе.
Спасибо, что нашли время прочитать эту статью.
Если у вас есть какие-либо рекомендации по другим пакетам, архитектурам, как улучшить мой код, мой английский или что-то в этом роде; оставьте комментарий или свяжитесь со мной через Twitter или LinkedIn.
Исходный код находится здесь
Ссылка
Отслеживание абонентской документации.
трассировочно-дополняющая документация.
Проблема № 296: Где самый простой пример ведения журнала HTTP-запросов?
Первоначально опубликовано на https://carlosmv.hashnode.dev.