Наблюдаемость cloud для такси нужна не ради красивых графиков. Её цель — быстро отвечать на вопросы в стиле “что сломалось”, “где узкое место” и “насколько это влияет на поездки”. В такси эти ответы должны приниматься почти в реальном времени: диспетчеризация, подбор водителя, расчёт цены, оповещения, платежи и трекинг событий идут параллельно.

В практической системе обычно есть несколько контуров наблюдаемости: метрики (что происходит с нагрузкой и временем ответа), трейсинг (как запрос проходит через сервисы) и SLO (какой уровень сервиса вы обещали пользователю и бизнесу). Без одного из контуров инциденты часто превращаются в угадайку.

Слои системы и типовые сценарии отказов

Для такси “cloud” почти всегда означает набор микросервисов и внешних зависимостей: карта и геокодинг, платежные провайдеры, сервис уведомлений, антифрод, хранилища, очередь событий. Типовые сбои легко сгруппировать:

  • Ошибки маршрутизации: сервис диспетчеризации не может найти ближайших водителей или не успевает обработать запросы.
  • Проблемы с временем: растёт задержка при подборе водителя или расчёте цены, а отмены растут следом.
  • Частичные деградации: часть команд в цепочке работает, часть нет (например, заказ создаётся, но уведомления не уходят).
  • “Шумные” сбои: кратковременные таймауты из-за сети выглядят как серьёзные падения, хотя пользователи почти не страдают.
  • Ошибки консистентности: повторные отправки, дедупликация, гонки между статусами заказа.

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

Чем наблюдаемость отличается от мониторинга

Мониторинг отвечает на вопрос “горит ли”. Наблюдаемость отвечает на “почему” и “что делать дальше”. Например, алерт по росту latency говорит, что время запроса увеличилось. Наблюдаемость должна подсказать, какой спан или какой downstream-сервис съедает время, какие атрибуты заказа ухудшили ситуацию (район, тип тарифа, нагрузка по конкретному кластеру), и какие шаги обычно восстанавливают сервис.

В такси это особенно важно из-за доменных метрик: даже если общий error rate небольшой, рост времени до подачи может заметно ухудшить конверсию в поездку.

Метрики: базовый набор для cloud такси

Метрики — фундамент. Без них трейсинг не привязан к контексту (где именно “болит”), а SLO не может быть проверен. Для такси полезно разделить метрики на несколько групп: запросные, доменные, инфраструктурные и метрики качества доставки событий.

RED/USE и их применение к диспетчеризации

Самый практичный подход — начать с моделей RED (Rate, Errors, Duration) или USE (Utilization, Saturation, Errors). Они хорошо ложатся на сервис диспетчеризации, маршрутизацию, расчет цены и обработку статусов заказа.

Что измерять в терминах RED/USE:

  • Rate: скорость обработки ключевых эндпоинтов и потоков событий (создание заказа, подтверждение, обновление статуса, запросы к геосервисам).
  • Errors: процент/число ошибок с разбиением по типам (timeout, 4xx, 5xx, бизнес-ошибки).
  • Duration: p50/p95/p99 времени ответа, отдельно для операций с внешними зависимостями.
  • Utilization: загрузка CPU, время в планировщике, активность обработчиков.
  • Saturation: длина очередей, переполнение пулов, backpressure, число ожидающих запросов.
  • Errors в контексте USE: метрики деградации, которые возникают не только как код ошибки, но и как отказ из-за ресурсов (например, 429/overload).

Важно не ограничиваться одной агрегацией на весь регион. Для такси критично разрезать по географическим сегментам, времени суток, типам тарифов и версиям приложений.

Метрики качества запроса: latency, errors, saturation

Для каждого ключевого API/handler в такси выведите “триаду”:

  • latency: p95 и p99 (а p50 — как вспомогательную, чтобы видеть ранний сдвиг);
  • error rate: общее и по категориям;
  • насыщение: признаки перегрузки (очереди, таймауты внутренних компонентов, рост времени ожидания в пуле потоков).

Пример того, как это выглядит для флоу “подбор водителя”:

  • latency подборки (время от начала до получения успешного предложения водителю);
  • ошибки таймаута при запросах к поиску кандидатов;
  • насыщение: очередь команд диспетчера, размер in-memory кеша кандидатов, глубина очереди событий для обновления статусов.

Типичная ошибка: измерять только длительность. Тогда при росте очередей и ожидания вы можете увидеть увеличение latency, но не поймёте, почему оно растёт (внешняя зависимость, внутренний пул, очередь, сеть).

Метрики домена: время до подачи и влияние на поездки

Одних техметрик недостаточно. В такси доменные показатели часто напрямую отвечают на вопрос “как это ударило по пользователю”. Минимальный набор обычно включает:

  • время до подачи: от момента подтверждения заказа до статуса “водитель назначен / прибыл” (выберите формулировку под вашу модель статусов);
  • время ожидания клиента: от создания заказа до “отменено/выполнено”;
  • процент отмен по причинам (клиент, водитель, отсутствие машин, ошибка расчёта, таймаут диспетчера);
  • конверсия: доля заказов, дошедших до назначения водителя и до выполнения поездки;
  • повторные попытки: сколько заказов создаётся повторно из-за сбоев, и какие из них являются корректными retry, а какие — симптомом проблем.

Чтобы метрики домена не стали “ещё одним дашбордом”, привязывайте их к конкретным SLI (об этом дальше, в SLO). Тогда команды разработки и инцидент-менеджмент начнут работать с одним источником правды: что считается улучшением, а что ухудшением.

Метрики инфраструктуры: очереди, autoscaling, сеть, БД

В облачной среде важны метрики, которые объясняют задержки и ошибки:

  • очереди: длина, возраст сообщений, время обработки;
  • autoscaling: задержка масштабирования, время до readiness, количество неуспевших инстансов;
  • базы: latency чтения/записи, доля slow queries, размер пулов, число активных соединений;
  • кэш: hit ratio, ошибки прогрева, время загрузки;
  • сеть: retransmits/packet drops на уровне метрик доступности (в зависимости от вашей сетевой модели);
  • служебные таймауты: какая доля запросов упирается в connect timeout, read timeout, total timeout.

Практический совет: не делайте алерты на всё подряд. Для инфраструктуры лучше иметь “сигналы-подсказки” и разрезы, которые помогают инженеру понять причину, а не только уведомить.

Как проектировать размер дашбордов и алертов

Если дашборд содержит 40 графиков, им никто не пользуется в инциденте. В такси лучше придерживаться принципа “минимум графиков, максимум причинности”. Для каждого ключевого journey обычно достаточно:

  • 1 график latency (p95/p99) по сервису или операции;
  • 1 график error rate по категориям;
  • 1 график насыщения (очереди/пулы);
  • 1 разрез по регионам/кластеру;
  • 1 связанный доменный индикатор (например, отмены или время до подачи).

Алерты проектируйте как систему “симптом → вероятная причина → действие”. Например:

  • если p99 диспетчера растёт и очереди растут — это вероятная перегрузка, и команда смотрит в сторону backpressure/очередей/пула;
  • если p99 растёт, а насыщение не растёт — ищите downstream-зависимости и таймауты внешних сервисов;
  • если error rate вырос, а latency нет — часто это ошибки в валидации/авторизации/бизнес-валидации, и трейсинг должен быстро найти конкретный код ошибки.

Трейсинг: сквозная диагностика от приложения до бэкенда

Трейсинг нужен, когда метрики показывают “что стало хуже”, но не отвечают на “какая часть цепочки сломалась”. В такси трейсинг особенно полезен из-за длинных цепочек: создание заказа запускает запись статуса, расчет цены, подбор водителя, оформление договора, уведомления, операции с платежами и последующее подтверждение событий.

Ключевые спаны в journey такси

Для трейсинга важно не “обвесить всё”, а определить несколько опорных спанов, по которым вы сможете быстро диагностировать инцидент. Для типового заказа можно выделить:

  • span “CreateOrder”: входной запрос на создание заказа или команду создания;
  • span “Dispatch/MatchDriver”: подбор водителя и запись кандидатов/назначения;
  • span “PriceQuote”: расчет цены и проверка тарифов/надбавок;
  • span “SendNotifications”: отправка push/SMS и фиксация результата отправки;
  • span “Payment”: создание платежа/платежная авторизация/закрытие (если у вас она асинхронная);
  • span “UpdateStatus”: обновление статусов и публикация событий в шину/очередь;
  • span “TrackDriver”: отдельный трейс для трекинга, если он критичен по SLA.

Затем вы добавляете подспаны к каждому этапу: вызовы downstream-сервисов, запросы в БД, взаимодействие с очередями и внешними API.

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

OpenTelemetry и контекст трассировки в практической схеме

В облачной системе самый устойчивый вариант — OpenTelemetry как единый стандарт для метрик/трейсов/логов. Практический принцип такой:

  • формируйте единый trace-id для “жизненного цикла” заказа или запроса;
  • прокидывайте контекст трассировки между сервисами через заголовки HTTP/gRPC или через message attributes для очередей;
  • используйте consistent naming: имена span должны отражать действие, а не внутреннюю реализацию.

Пример подхода к корреляции в такси:

  • клиентское приложение создаёт запрос с кореляционным идентификатором (можно использовать order_id как атрибут);
  • gateway/edge создаёт/продолжает span и добавляет атрибуты: orderid, region, appversion;
  • каждый сервис создаёт дочерние спаны для downstream вызовов и фиксирует ключевые атрибуты: причина отказа, тип тарифа, модель dispatch.

Если вы используете асинхронные события (например, статус заказа обновляется через очередь), обязательно переносите trace контекст. Иначе “сквозной” трейс превратится в набор несвязанных фрагментов.

Структура атрибутов и событий: что логировать в спанах

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

  • идентификаторы: orderid, rideid (если есть), driver_id (если применимо и безопасно);
  • география: region/city, zone_id;
  • тариф: тарифная схема, тип поездки (если это отдельная сущность);
  • статусы: исходный статус и новый статус (например, “Pending → Dispatched”);
  • результаты бизнес-операций: причина отмены, код ошибки бизнес-валидации;
  • внешние зависимости: имя downstream-сервиса, статус ответов, тип таймаута;
  • параметры производительности: размер батча (для очередей), количество кандидатов в dispatch (если это не персональные данные).

Типичная ошибка: добавлять в атрибуты всё подряд, включая массивы данных или большие тексты. Это раздувает стоимость хранения/индексации и делает поиск бессмысленным. Лучше фиксировать “скалярные” признаки, по которым фильтруют.

Корреляция трассировок с логами и метриками

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

  • логируйте ключевые события обработки, но добавляйте trace-id и span-id;
  • в метриках используйте идентичные разрезы: region, service_version, operation;
  • в дашбордах и инцидент-панелях обеспечьте “клик” или быстрый переход от графика к запросам/трейсам.

Когда latency растёт, вы открываете пример трассы с худшим временем, смотрите, какой downstream-сервис стал узким местом, и уже потом переходите к логам того сервиса за тот период.

SLO для такси: надежность, которую можно измерить

SLO в такси должны быть “жёсткими” по смыслу, но “гибкими” по реализации. Они не равны SLA юридически, но дают общую договорённость инженерных и продуктовых команд: что считается приемлемой работой и какой уровень ошибок допустим.

SLO — это связка: выбранный SLI (что измеряем), порог (что считаем успехом) и период (как часто оцениваем). Важно: SLO нужно строить на доменных метриках, а не только на времени ответов API. Пользователю важнее, что заказ доведён до назначения и поездка началась без длительных ожиданий.

Выбор SLI: из чего считать надежность

SLI лучше выбирать из “пользовательского пути” (user journey). Для такси типовые варианты SLI:

  • SLI по успешному созданию заказа: доля заказов, которые перешли в корректное состояние создания без ошибок.
  • SLI по назначению водителя: доля заказов, которые получили назначение в пределах целевого окна.
  • SLI по доставке уведомлений: доля ключевых уведомлений (например, “водитель назначен”), подтвержденных как отправленные.
  • SLI по времени до подачи: доля заказов, где “время до подачи” не превышает заданный порог.
  • SLI по выполнению поездки: доля заказов, завершившихся поездкой (не отменённых) в течение жизненного цикла.

Частая ошибка: выбрать SLI, который слишком легко “обойти”. Например, измерять только HTTP 200 на endpoint создания заказа, хотя доставка статуса водителю или уведомления всё равно могут ломаться. В результате SLO “зелёный”, а пользователь недоволен.

Формулировка SLO по метрикам и трейсингу

SLO обычно строится на метриках, потому что периодические оценки и алерты удобнее. Но трейсинг помогает валидировать, почему SLO нарушается и какие причины преобладают.

Практически SLO формулируют так:

  • SLI: например, доля заказов, в которых dispatch завершился успешно в целевом окне времени;
  • window: например, 28 дней или другой период, подходящий к вашему релизному циклу;
  • цель: порог “доля успехов не ниже X”.

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

Дополнительно полезно держать “корреляционные” метрики, чтобы в момент нарушения SLO понимать, что случилось: рост p99 dispatch, рост таймаутов downstream, отказ платежного сервиса, перегрузка очередей статусов.

Error budget и управление изменениями

Error budget — это инструмент управления риском. Когда SLO близко к нарушению, команда должна замедлить рискованные изменения и сфокусироваться на стабилизации.

В такси это особенно важно, потому что релизы часто затрагивают разные части цепочки: dispatch, тарификация, уведомления. С error budget удобно согласовать:

  • “можно ли выпускать релиз диспетчера” в момент, когда запас ошибок уже почти съеден;
  • какие изменения считаются “стабилизирующими” (например, миграции, rollback, восстановление очередей);
  • как проводить эксперименты, чтобы не ухудшить доменный пользовательский путь.

Пример SLO для ключевого флоу заказа

Возьмём флоу “назначение водителя”. Конкретная формулировка может выглядеть так:

  • SLI: доля заказов, для которых статус “водитель назначен” наступил в течение заданного времени от момента создания заказа (с учётом ваших статусов и определения момента старта).
  • Успех: событие назначения произошло корректно и не сопровождалось причинами отказа, которые вы исключили как “не зависящие от сервиса” (например, отмены пользователем по инициативе).
  • Отчётный период: скользящее окно (по вашей практике).
  • Цель: добиться заданного процента успехов.

Дальше вы строите алерт: “SLO ухудшается” или “burn rate превышен”. Burn rate — скорость потребления error budget. Это даёт более ранний сигнал, чем ожидание окончания периода SLO.

Важное замечание: SLO должно учитывать бизнес-исключения. Если заказ отменён пользователем до назначения, он не должен портить надежность dispatch так, как будто dispatch сломался.

SLO для пограничных случаев: отмены, повторные попытки, дедупликация

В такси много “неидеальных” жизненных циклов. Если вы не определите их в SLI, результаты будут плавающими и несправедливыми.

Продумайте заранее правила:

  • отмена пользователем: исключать из SLI назначения, иначе вы будете наказаны за поведение клиента;
  • отмена по причине “нет водителей”: это уже показатель доступности dispatch, и обычно его стоит учитывать как провал SLI или как отдельный SLI;
  • повторные попытки (retry): если пользователь нажал “создать заказ” повторно, решите, объединять ли попытки в один “ride journey” или считать отдельно;
  • дедупликация: если заказ создаётся повторно из-за сетевых ретраев, но фактически один и тот же order_id/корреляция — SLI должен учитывать это, иначе вы надуете метрики ошибок;
  • асинхронные статусы: если назначение фиксируется событием через очередь, важно измерять именно “время до события”, а не “время до публикации”.

Чем яснее правила, тем меньше споров на ретроспективе и тем легче инженерам проверять гипотезы.

Алертинг и процесс реагирования

Даже лучшие метрики и SLO ничего не дадут, если команда не имеет процесса реагирования. В такси инциденты должны разруливаться быстро и предсказуемо: кто смотрит какие дашборды, какие проверки делают первыми, как быстро восстанавливается сервис.

Модель алертов: симптом → причина → действие

Сформируйте типовые классы алертов:

  • деградация времени ответа: latency p99 по ключевым операциям;
  • рост ошибок: error rate, таймауты, 5xx, бизнес-ошибки;
  • перегрузка: насыщение (очереди, пул потоков, backpressure);
  • нарушение SLO: burn rate или другие индикаторы ухудшения;
  • деградация домена: рост отмен, рост времени до подачи.

Для каждого класса определите первое действие дежурного. Пример:

  • при нарушении SLO назначения открыть дашборд dispatch: latency/error/saturation и разрезы по регионам;
  • открыть трейс одного “худшего” заказа из региона, где провал;
  • проверить downstream: геосервис, кэш/поиск кандидатов, очередь обновления статусов;
  • проверить недавние релизы и конфигурации (особенно таймауты, лимиты, параметры маршрутизации).

Автоматическое подавление шума и группировка инцидентов

В такси много естественного шума: погодные пики, смена расписаний, всплески заказов по районам. Чтобы алерты были полезными:

  • группируйте алерты по service/region/operation;
  • используйте окна сглаживания для алертов по burst-нагрузке;
  • подавляйте алерты, если одновременно есть подтверждение, что это “изолированный” эффект для малого сегмента и он не влияет на SLI.

Ещё один практический подход: сигнализировать о нарушении SLO через burn rate, а не каждый раз поднимать тревогу на небольшие кратковременные выбросы latency.

Runbook для инженера дежурства

Runbook должен быть не теоретическим, а пошаговым. Для каждой категории инцидентов перечислите:

  • симптомы: какие графики и метрики увидеть первыми;
  • критерии подтверждения: как понять, что проблема реальная и влияет на доменные показатели;
  • диагностический маршрут: какой трейс/лог открыть, какие атрибуты проверить;
  • типовые причины: перегрузка очередей, деградация downstream, ошибки релиза, неверные таймауты;
  • действия восстановления: rollback, переключение на fallback, уменьшение нагрузки, восстановление очередей, временные лимиты;
  • критерии “успокоения”: когда можно считать, что SLO снова в норме.

Если runbook приходится каждый раз писать заново после инцидента, наблюдаемость превращается в “постфактум”. Наличие заранее оформленной карты действий экономит часы.

План внедрения observability за 4–6 недель

Лучше идти итерациями. В такси наблюдаемость должна появиться быстро в местах наибольшей боли: dispatch, статус заказа, уведомления. Попытка “с нуля всё покрыть” в одном релизе почти всегда приводит к провалу.

Неделя 1: инвентаризация и карта данных

Соберите карту системы и данные, которые уже есть:

  • список сервисов и ключевых эндпоинтов/команд;
  • существующие метрики и где они находятся;
  • источники логов и как они сейчас коррелируются (если коррелируются);
  • как работают очереди/шина событий и где можно переносить контекст трассировки;
  • какие SLI уже можно посчитать из текущих данных (обычно нет, но часто есть зацепки).

На этом этапе главное — определить 3–5 критических journey для такси и договориться о терминах статусов заказа.

Неделя 2: базовые метрики и SLI

Дальше внедрите “скелет” метрик:

  • latency/error/saturation для операций dispatch, price quote, update status, notifications (минимум);
  • доменные метрики, которые вы сможете использовать в SLI (времена и проценты);
  • разрезы по region/cluster/app_version (минимум);
  • единый формат кореляционных идентификаторов (orderid/rideid).

Параллельно определите первичные SLI и их формальные правила: что считается успехом, что исключается, как объединяются попытки.

Неделя 3–4: трейсинг и контекст

На третьей-четвёртой неделе включайте трейсинг в ключевых узлах:

  • добавьте OpenTelemetry в gateway/edge и распространение контекста в downstream;
  • измеряйте спаны по опорным этапам journey заказа;
  • фиксируйте атрибуты для поиска причин: region, тариф, причина отказа;
  • настройте sampling-стратегию, чтобы не переполнить хранилище трейсами.

На этом этапе уже нужно добиться способности “по метрикам увидеть ухудшение и тут же открыть один конкретный пример трейсинга” из проблемного сегмента.

Неделя 5–6: SLO, error budget и алерты

На последнем этапе закрепите договорённость:

  • сформулируйте SLO по ключевому journey (обычно dispatch или назначение);
  • включите burn rate алерты и определите пороги для “раннего сигнала” и “срочного реагирования”;
  • добавьте runbook для инженера и связку “алерт → дашборд → трейс → лог”;
  • протестируйте процесс на симуляции: например, смоделируйте рост таймаутов downstream или рост задержек очереди.

Результатом должно стать не “наличие систем”, а способность быстро локализовать и подтвердить восстановление SLO.

Метрики зрелости: что проверять

Чтобы понять, что наблюдаемость работает, используйте измеримые признаки:

  • MTTR по типовым инцидентам сократился (или хотя бы уменьшилось время до первичной локализации);
  • доля алертов, которые можно классифицировать как “перегрузка/внешняя зависимость/ошибка релиза” без долгих догадок;
  • время от алерта до открытия релевантного трейсинга;
  • процент заказов, для которых доступна “сквозная трасса” по ключевому journey.

Эти показатели — практичный аналог зрелости, который не зависит от конкретного вендора.

Типичные ошибки и как их избежать

Ошибка 1: слишком много метрик и слишком мало смысла Решение: ограничьте стартовый набор метрик на уровне ключевых операций такси. Каждый график должен отвечать на вопрос “что проверить дальше при инциденте”.

Ошибка 2: отсутствие корреляции и “разорванный” контекст Если trace-id не проходит через очереди или вы теряете order_id в части цепочки, трейсинг будет выглядеть как набор фрагментов. Решение: внедряйте единый контекст трассировки и кореляционные идентификаторы на раннем этапе.

Ошибка 3: SLO вместо надежности из-за неправильного SLI SLO “успехов” на API-уровне не гарантирует качество пользовательского пути. Решение: выбирайте SLI так, чтобы он отражал доменный результат заказа: назначение, ожидание, отмены по причинам, время до ключевого события.

Ошибка 4: трейсинг без sampling-стратегии С sampling может быть “слишком мало” и “слишком дорого” одновременно. Решение: начните с таргетного sampling для ошибочных запросов и для slow-path, а основную статистику можно получать метриками.

Ошибка 5: алерты на единичные выбросы В такси пики нагрузки и кратковременные таймауты случаются. Решение: используйте сглаживание, burn rate для SLO и группировку по сегментам.

Ошибка 6: отсутствие runbook и “рутинных” действий Когда каждый дежурный делает диагностику заново, время восстановления растёт. Решение: фиксируйте маршрут диагностики и критерии восстановления до того, как случится очередной инцидент.

Заключение: как прийти к наблюдаемости, которая помогает бизнесу

Наблюдаемость cloud для такси — это не набор инструментов, а система ответов: метрики показывают, что ухудшилось; трейсинг помогает понять, где именно; SLO задаёт измеримую цель и единый язык для команд. Если начать с ключевого journey заказа и связать метрики, трейсинг и SLO в одну цепочку, вы получите управляемую надёжность вместо бессистемного “чинения по ощущениям”.

Сделайте первый шаг практично: выберите 3–5 критических операций такси, заведите для них базовые метрики latency/error/saturation и доменные показатели, включите сквозной трейсинг через OpenTelemetry, после чего оформите SLO по выбранному SLI. Дальше останется дисциплина: burn rate, runbook и регулярная работа с error budget — именно она превращает observability в реальную операционную управляемость.