Трассировка в YDB
Примечание
Подробно трассировка описана на сайте opentelemetry в разделе observability primer.
Трассировка – инструмент, позволяющий детально посмотреть путь следования запроса по распределенной системе. Путь следования одного запроса (трасса) описывается набором спанов. Спан является отрезком времени, обычно связанным с временем выполнения определенной операции (например запись информации на диск, выполнение транзакции). Спаны образуют дерево, часто поддерево спана является его детализацией, однако это не всегда так.
Для аггрегации разрозненных спанов в трассы они отправляются в коллектор. Это сервис, который аггрегирует и сохраняет получаемые спаны для последующего анализа трасс. YDB не включает в себя этот сервис, администратор должен поднять его самостоятельно. Обычно в качестве коллектора используется jaeger.
Минимальная конфигурация
Для включения трассировки в YDB добавьте в конфигурацию следующую секцию:
tracing_config:
backend:
opentelemetry:
collector_url: grpc://example.com:4317
service_name: ydb
external_throttling:
- max_traces_per_minute: 10
В ней поле collector_url
задает url OTLP-совместимого коллектора спанов. Более подробно с описанием секции backend можно ознакомиться в соответствующей секции.
При данной настройке никакие запросы не сэмплируются, не более 10 запросов в минуту с внешним trace-id трассируются каждым узлом кластера.
Описание секций
Backend
Пример секции
tracing_config:
# ...
backend:
opentelemetry:
collector_url: grpc://example.com:4317
service_name: ydb
Описание
В этой секции описывается коллектор спанов. На данный момент единственная опция – opentelemetry
. Отправка спанов с узла кластера в коллектор происходит по push-модели, от коллектора требуется совместимость с OTLP.
В секции opentelemetry
:
collector_url
— URL коллектора спанов. Схема может быть либоgrpc://
для небезопасного подключения, либоgrpcs://
для TLS-подключения.service_name
— имя сервиса, которым будут подписываться все спаны.
Оба параметра являются обязательными.
Uploader
Пример секции
tracing_config:
# ...
uploader:
max_exported_spans_per_second: 30
max_spans_in_batch: 100
max_bytes_in_batch: 10485760 # 10 MiB
max_export_requests_inflight: 3
max_batch_accumulation_milliseconds: 5000
span_export_timeout_seconds: 120
Описание
Uploader – компонент узла кластера, который отвечает за отправку спанов в коллектор. Во избежание перегрузки коллектора спанов, uploader не будет отправлять больше, чем max_exported_spans_per_second
спанов в секунду в среднем.
В целях оптимизации uploader отправляет спаны батчами. Каждый батч содержит не более max_spans_in_batch
спанов с суммарным сериализованным размеров не более max_bytes_in_batch
байт. Каждый батч накапливается на протяжении не более, чем max_batch_accumulation_milliseconds
миллисекунд. Батчи могут отправляться параллельно, максимальное количество одновременно отправляемых батчей контролируется параметром max_export_requests_inflight
. Если с момента получения спана uploader'ом прошло больше span_export_timeout_seconds
секунд, uploader может удалить его в пользу отправки более свежих спанов.
Значения по умолчанию:
max_exported_spans_per_second = inf
(отсутствуют какие-либо ограничения)max_spans_in_batch = 150
max_bytes_in_batch = 20000000
max_batch_accumulation_milliseconds = 1000
span_export_timeout_seconds = inf
(никакие спаны не удаляются uploader'ом)max_export_requests_inflight = 1
Секция uploader
может полностью отсутствовать, в таком случае для каждого параметра будет использоваться значение по умолчанию.
Примечание
Uploader – локальный для узла компонент, как следствие, описанные ограничения применяются к каждому узлу отдельно, а не ко всему кластеру в целом.
External throttling
Пример секции
tracing_config:
# ...
external_throttling:
- scope:
database: /Root/db1
max_traces_per_minute: 60
max_traces_burst: 3
Описание
YDB поддерживает передачу внешних trace-id для построения цельной трассы запроса. Способ передачи внешнего trace-id описан на странице Передача внешнего trace-id в YDB. Для избежания перегрузки коллектора, в YDB есть механизм ограничения количества трассируемых извне запросов. Ограничения описываются в данной секции и являются последовательностью правил, каждое правило содержит:
scope
– набор селекторов для фильтрации запроса.max_traces_per_minute
– наибольшее среднее количество запросов в минуту, трассируемое по данному правилу. Ожидается положительное целое число.max_traces_burst
– максимальный всплеск количества трассируемых извне запросов. Ожидается неотрицательное целое число.
Обязательным параметром является только max_traces_per_minute
.
Подробное описание этих опций приведено в секции Семантика правил
Секция external_throttling
не является обязательной, в случае ее отсутствия все trace-id в запросах игнорируются (никакие внешние трассы не продолжаются).
Данную секцию можно изменять без перезагрузки узла с помощью механизма динамической конфигурации.
Sampling
Пример секции
tracing_config:
# ...
sampling:
- fraction: 0.01
level: 10
max_traces_per_minute: 5
max_traces_burst: 2
- scope:
request_types:
- KeyValue.ExecuteTransaction
- KeyValue.Read
fraction: 0.1
level: 15
max_traces_per_minute: 5
max_traces_burst: 2
Описание
Для диагностирования проблем в системе, может быть полезно посмотреть на пример трассы запроса вне зависимости от того, трассируют пользователи свои запросы, или нет. Для этого в YDB есть механизм сэмплирования запросов. Для сэмплированного запроса генерируется случайный trace-id. Данная секция контролирует сэмплирование запросов в формате аналогичном external_throttling
, каждое правило имеет два дополнительные поля:
fraction
– доля запросов, сэмплированных по данному правилу. Ожидается дробное число от 0 до 1.level
— уровень детализации трассы. Ожидается целое число от 0 до 15 включительно. Подробнее этот параметр описан в секции Уровни детализации
Оба поля являются обязательными.
Секция sampling
не является обязательной, в случае ее отсутствия никакие запросы не будут сэмплироваться.
Данную секцию можно изменять без перезагрузки узла с помощью механизма динамической конфигурации.
Семантика правил
Селекторы
Каждое правило включает в себя опциональное поле scope
с набором селекторов, которые определяют, к каким запросам применяется данное правило. На данный момент поддерживаются селекторы:
-
request_types
Принимает список типов запросов. Запрос подходит под данный селектор если его тип содержится в списке.
Возможные значения
- KeyValue.CreateVolume
- KeyValue.DropVolume
- KeyValue.AlterVolume
- KeyValue.DescribeVolume
- KeyValue.ListLocalPartitions
- KeyValue.AcquireLock
- KeyValue.ExecuteTransaction
- KeyValue.Read
- KeyValue.ReadRange
- KeyValue.ListRange
- KeyValue.GetStorageChannelStatus
- Table.CreateSession
- Table.KeepAlive
- Table.AlterTable
- Table.CreateTable
- Table.DropTable
- Table.DescribeTable
- Table.CopyTable
- Table.CopyTables
- Table.RenameTables
- Table.ExplainDataQuery
- Table.ExecuteSchemeQuery
- Table.BeginTransaction
- Table.DescribeTableOptions
- Table.DeleteSession
- Table.CommitTransaction
- Table.RollbackTransaction
- Table.PrepareDataQuery
- Table.ExecuteDataQuery
- Table.BulkUpsert
- Table.StreamExecuteScanQuery
- Table.StreamReadTable
- Table.ReadRows
- Query.ExecuteQuery
- Query.ExecuteScript
- Query.FetchScriptResults
- Query.CreateSession
- Query.DeleteSession
- Query.AttachSession
- Query.BeginTransaction
- Query.CommitTransaction
- Query.RollbackTransaction
- Discovery.WhoAmI
- Discovery.NodeRegistration
- Discovery.ListEndpoints
Примечание
Трассировка поддерживается не только для типов запросов, приведенных выше. В этом списке перечислены типы запросов, которые поддерживатюся селектором request_types
.
Важно
Обратите внимание, что QueryService API экспериментальное и может быть изменено в будущем.
-
database
Фильтрует запросы к указанной базе данных.
Запрос подходит под правило, если он подходит под все селекторы. scope
может отсутствовать, это равносильно пустому набору селекторов, все запросы будут попадать под это правило.
Rate limiting
Параметры max_traces_per_minute
и max_traces_burst
используются для ограничения сверху на количество запросов. В случе sampling они ограничивают количество запросов, сэмплированных по данному правилу. В случае external throttling они ограничивают количество внешних трасс, которые попадают в систему.
Для ограничений используется вариация leaky bucket с размером бакета равным max_traces_burst + 1
. Например, если max_traces_per_minute = 60
и max_traces_burst = 0
, то при потоке в 10000 запросов в минуту будет трассироваться один запрос каждую секунду. Если же max_traces_burst = 20
, то при поступлении аналогичного потока запросов первые 21 будут оттрассированы, далее аналогично будет трассироваться один запрос в секунду.
Важно
Ограничения на количество трассируемых запросов локальные для узла кластера. Например, если на каждом узле кластера есть правило, в котором указано max_traces_per_minute = 1
, по этому правилу будет трассироваться не больше одного запроса в минуту с каждого узла кластера.
Уровни детализации
Как и в случае с логами, для диагностирования большинства проблем с системой не требуется наличие максимально подробной трассы, поэтому в YDB каждый спан имеет свой уровень, описываемый целым числом от 0 до 15 включительно. Каждое правило в секции sampling
должно включать в себя уровень детализации генерируемой трассы (level
), в нее будут включаться спаны с уровнем меньшим, либо равным level
.
В разделе об архитектуре YDB приводится разделение системы на 5 слоев:
Слой | Копоненты |
---|---|
1 | gRPC Proxies |
2 | Query Processor |
3 | Distributes Transactions |
4 | Tablet, System tablet |
5 | Distributed Storage |
Для каждого слоя существует 7 уровней детализации:
Уровень | Значение |
---|---|
Off |
Отсутствие трассировки |
TopLevel |
Самая низкая детализация, не более 2 спанов на каждый запрос к компоненту |
Basic |
Спаны главных операций компонента |
Detailed |
Самая высокая детализация, применимая для диагностирования проблем в production |
Diagnostic |
Детальная отладочная информация для разработчиков |
Trace |
Очень детальная отладочная информация |
Ниже приведено распределение уровней детализации слоев системы по уровням детализации трассы:
Уровень детализации трассы | gRPC Proxies | Query Processor | Distributed Transactions | Tablets | Distributed Storage |
---|---|---|---|---|---|
0 | TopLevel |
Off |
Off |
Off |
Off |
1 | TopLevel |
TopLevel |
Off |
Off |
Off |
2 | TopLevel |
TopLevel |
TopLevel |
Off |
Off |
3 | TopLevel |
TopLevel |
TopLevel |
TopLevel |
Off |
4 | TopLevel |
TopLevel |
TopLevel |
TopLevel |
TopLevel |
5 | Basic |
TopLevel |
TopLevel |
TopLevel |
TopLevel |
6 | Basic |
Basic |
TopLevel |
TopLevel |
TopLevel |
7 | Basic |
Basic |
Basic |
TopLevel |
TopLevel |
8 | Basic |
Basic |
Basic |
Basic |
TopLevel |
9 | Basic |
Basic |
Basic |
Basic |
Basic |
10 | Detailed |
Detailed |
Basic |
Basic |
Basic |
11 | Detailed |
Detailed |
Detailed |
Basic |
Basic |
12 | Detailed |
Detailed |
Detailed |
Detailed |
Basic |
13 | Detailed |
Detailed |
Detailed |
Detailed |
Detailed |
14 | Diagnostic |
Diagnostic |
Diagnostic |
Diagnostic |
Diagnostic |
15 | Trace |
Trace |
Trace |
Trace |
Trace |
Правила
External Throttling
Семантика каждого правила такова: оно выделяет квоту на количество запросов данной категории. Например, если секция external_throttling
выглядит следующим образом:
tracing_config:
external_throttling:
- max_traces_per_minute: 60
- scope:
request_types:
- KeyValue.ReadRange
max_traces_per_minute: 20
При достаточном потоке запросов с внешним trace-id, будут трассироваться хотя бы 60 запросов в минуту и хотя бы 20 запросов в минуту типа KeyValue.ReadRange
. Всего трассироваться будут не более 80 запросов в минуту.
Алгоритм решения следующий: для запроса, имеющего внешний trace-id, определяется набор правил, под которые подходит данный запрос. Запрос потребляет квоту у всех правил, у которых она еще есть. Запрос не трассируется только в том случае, если ни в у одного из правил не осталось квоты.
Sampling
В случае сэмплирования семантика правила аналогична: при достаточно маленьком потоке запросов данной категории, будет сэплироваться хотя бы fraction
запросов с уровнем хотя бы level
.
Алгоритм решения аналогичный: для запроса, не имеющего внешнего trace-id (либо из-за его изначального отсутствия, либо из-за принятого ранее решения о не трассировании данного запроса), определяется набор правил, под которые подходит данный запрос. Запрос потребляет квоту у всех правил, у которых она еще есть и которые случайным образом "решили" его сэмплировать. Если ни по одному правилу запрос не нужно сэмлировать (во всех правилах, которые случайным образом "решили" сэмплировать запрос, не осталось квоты), он не сэмплируется. В противном случае уровень детализации определяется, как максимальный среди правил, в квоту которых попал запрос.
Например, при данной конфигурации sampling
:
tracing_config:
sampling:
- scope:
database: /Root/db1
fraction: 0.5
level: 5
max_traces_per_minute: 100
- scope:
database: /Root/db1
fraction: 0.01
level: 15
max_traces_per_minute: 5
При достаточно маленьком потоке запросов к базе /Root/db1
, будут сэмплироваться:
- 1% запросов с уровнем детализации 15
- 49.5% запросов с уровнем детализации 5
При достаточно большом потоке запросов к базе /Root/db1
, будут сэмплироваться:
- 5 запросов в минуту с уровнем детализации 15
- от 95 до 100 запросов в минуту с уровнем детализации 5