Настройка логирования серверных компонент
Серверные компоненты кластера YTsaurus пишут подробные логи, которые можно использовать для аудита и анализа проблем при эксплуатации. В продакшн-инсталляциях рекомендуется выделять под логи отдельные локации на персистентных томах. Отсутствие логов может существенно ограничить возможности поддержки.
Для анализа работы подсистемы логирования можно воспользоваться prometheus-метриками с префиксом yt_logging_*
.
Отладочные логи
Отладочные логи описываются в секции loggers
спецификации компонент YTsaurus.
Таблица 1 — Настройки отладочных логгеров YTsaurus
Поле | Возможные значения | Описание |
---|---|---|
name |
произвольная строка | Имя логгера; рекомендуется выбирать короткие и понятные названия debug , info и т. п. |
format |
plain_text (default), yson , json |
Формат строки лога. |
minLogLevel |
trace , debug , info , error |
Минимальный уровень записей, попадающих в лог. |
categoriesFilter |
Фильтр, позволяющий писать логи только от некоторых подсистем, см. ниже. | |
writerType |
file , stderr |
Писать логи в файл или в stderr. При записи в stderr настройки ротации будут игнорироваться. |
compression |
none (default), gzip , zstd |
Если задано значение, отличное от none , сервер YTsaurus будет писать сжатые логи. |
useTimestampSuffix |
true , false (default) |
Если true , к имени файла в момент открытия или ротации дописывается timestamp. При этом механизм нумерации старых сегментов при ротации не используется. Имеет смысл только при записи в файл. |
rotationPolicy |
Настройки ротации логов, см. ниже. Имеет смысл только при записи в файл. |
Путь к каталогу, куда будут записываться логи с writerType=file
, задаётся в описании локации типа Logs
. В случае, если локация Logs
не указана, логи будут записываться в каталог /var/log
.
Имена файлов с логом формируются следующим образом: [component].[name].log(.[format])(.[compression])(.[timestamp_suffix])
. Примеры:
controller-agent.error.log
master.debug.log.gzip
scheduler.info.log.json.zstd.2023-01-01T10:30:00
Записи отладочных логов содержат следующие поля:
instant
— время в локальной временной зоне;level
— уровень записи:T
— trace,D
— debug,I
— info,W
— warning,E
— error;category
— имя подсистемы, к которой относится запись, напримерChunkClient
,ObjectServer
илиRpcServer
;message
— тело сообщения;thread_id
— id (или имя) треда, породившего запись; пишется только в форматеplain_text
;fiber_id
— id файбера, породившего запись; пишется только в форматеplain_text
;trace_id
— trace_context id, в контексте которого появилась запись; пишется только в форматеplain_text
.
Пример записи
2023-09-15 00:00:17,215385 I ExecNode Artifacts prepared (JobId: d15d7d5f-164ff08a-3fe0384-128e0, OperationId: cd56ab80-d21ef5ab-3fe03e8-d05edd49, JobType: Map) Job fff6d4149ccdf656 2bd5c3c9-600a44f5-de721d58-fb905017
Рекомендации по настройке категорий
Существует два вида фильтра по категориям (categoriesFilter
):
- включающий — пишутся записи только тех категорий, которые были явно перечислены;
- исключающий — пишутся записи любых категорий, кроме тех, которые были перечислены.
Зачастую, в больших инсталляциях приходится исключать категории Bus
и Concurrency
.
Примеры фильтров
categoriesFilter:
type: exclude
values: ["Bus", "Concurrency"]
categoriesFilter:
type: include
values: ["Scheduler", "Strategy"]
Структурированные логи
Некоторые компоненты YTsaurus способны писать структурированные логи, которые можно использовать впоследствии для аудита, аналитики и автоматической обработки. Структурированные логи описываются в секции structured_loggers
спецификации компонент YTsaurus.
Для описания структурированных логгеров используются те же поля, что и для отладочных логов, кроме:
writerType
— не задаётся; структурированные логи всегда пишутся в файл;categoriesFilter
— вместо него задаётся обязательное полеcategory
— равно одна категория.
Структурированные логи рекомендуется всегда писать в одном из структурированных форматов — json
или yson
. События в структурированный лог обычно пишутся на уровне info
. Набор полей структурированного лога зависит от конкретного типа лога.
Основные типы структурированных логов:
master_access_log
— лог доступа к данным; пишется на мастере, категорияAccess
;master_security_log
— лог событий безопасности, например добавление пользователя в группу или изменение ACL; пишется на мастере, категорияSecurityServer
;structured_http_proxy_log
— лог запросов к http proxy, по одной строке на запрос; пишется на http proxy, категорияHttpStructuredProxy
;chyt_log
— лог запросов к CHYT, по одной строке на запрос; пишется на http proxy, категорияClickHouseProxyStructured
;structured_rpc_proxy_log
— лог запросов к rpc proxy, по одной строке на запрос; пишется на rpc proxy, категорияRpcProxyStructuredMain
;scheduler_event_log
— лог событий планировщика; пишется планировщиком, категорияSchedulerEventLog
;controller_event_log
— лог событий контроллер-агента; пишется на контроллер-агенте, категорияControllerEventLog
.
Лог доступа к таблице
Иногда возникает необходимость узнать, кто пользуется той или иной таблицей, — например, чтобы оценить последствия ее удаления или перемещения. Задача осложняется тем, что доступ может осуществляться посредством ссылок.
Для решения подобных задач существует специальный лог, в котором журналируются события с узлами Кипариса, которые могут представлять интерес для пользователей.
Лог пишут мастер-серверы, причем в силу технических особенностей несколько различных серверов производят одинаковую последовательность записей, так что дублирования стоит ожидать. Кроме того, некоторая активность (например, запись в таблицы) выглядит как последовательность нескольких разных событий на разных мастер-серверах (из разных шардов). Подробнее об этом далее.
Каждая запись в логе (каждая строка в таблице) фиксирует одну команду, примененную к тому или иному кипарисному узлу.
Журналируются только команды, примененные к следующим типам узлов:
- таблица;
- файл;
- документ;
- журнал.
Стоит явно отметить, что директории не входят в данный перечень.
Журналируются следующие команды:
- базовые (CRUD):
- Create
- Get
- GetKey
- Exists
- List
- Set
- Remove
- создание символической ссылки:
- Link
- блокировки:
- Lock
- Unlock
- копирование и перемещение:
- Copy
- Move
- BeginCopy, EndCopy
- чтение и запись данных:
- GetBasicAttributes
- Fetch
- BeginUpload
- EndUpload
- изменение состояния динамической таблицы:
- PrepareMount, CommitMount, AbortMount
- PrepareUnmount, CommitUnmount, AbortUnmount
- PrepareRemount, CommitRemount, AbortRemount
- PrepareFreeze, CommitFreeze, AbortFreeze
- PrepareUnfreeze, CommitUnfreeze, AbortUnfreeze
- PrepareReshard, CommitReshard, AbortReshard
- прочие:
- CheckPermission
Некоторые комментарии касательно семантики команд можно найти далее.
Содержательная часть записи в логе имеет поля (колонки в таблице), представленные в таблице 1.
Таблица 1 — Описание полей лога
Поле | Описание |
---|---|
instant |
Время события в формате YYYY-MM-DD hh:mm:ss,sss |
cluster |
Короткое имя кластера |
method |
Команда (см. список выше) |
path (см. примечание) |
Путь, переданный команде в качестве аргумента |
original_path (см. примечание) |
Путь, переданный команде в качестве аргумента |
destination_path (см. примечание) |
Для команд «Copy», «Move» и «Link» — путь назначения (для других команд отсутствует) |
original_destination_path (см. примечание) |
Для команд «Copy», «Move» и «Link» — путь назначения (для других команд отсутствует) |
user |
Пользователь, давший команду |
type |
Для команды «Create» — тип создаваемого узла (для других команд отсутствует) |
transaction_info |
Сведения о транзакции, в контексте которой была выполнена команда (если команда выполнялась вне транзакции, поле отсутствует) |
Примечание
Отличие поля original_path
от path
(а также original_destination_path
от destination_path
) заключается в следующем:
- если в качестве пути была указана ссылка (симлинк), в
original_path
будет путь к ссылке, а вpath
— «настоящий» путь к узлу; - далее, если этот путь ведет в шард, то в логе этого шарда в качестве
original_path
будет указан «настоящий» путь, а в качествеpath
— путь относительно корня шарда.
В общей сложности это означает, что условный grep по пути к симлинку всегда найдёт записи, содержащие настоящий путь к узлу, а grep по настоящему пути найдёт обращения в том числе и через симлинки. Важно лишь выполнять поиск как по path
, так и по original_path
.
Структура поля transaction_info
представлена в таблице 2.
Таблица 2 — Структура поля transaction_info
Поле | Описание |
---|---|
transaction_id |
ID транзакции |
transaction_title |
Человекочитаемое описание транзакции (указывается клиентом при запуске транзакции; поле отсутствует, если описание не было указано) |
operation_id |
ID операции, ассоциированной с транзакцией |
operation_title |
Человекочитаемое описание операции, ассоциированной с транзакцией |
parent |
Для вложенной транзакции — описание ее родителя (для верхнеуровневой транзакции поле отсутствует) |
Следует отметить, что поле parent
устроено так же, как и transaction_info
. Таким образом, transaction_info
содержит полное рекурсивное описание родословной транзакции, из-под которой была выполнена команда.
Замечания
- Стоит отличать чтение/запись метаданных от чтения/записи данных (чанков) в таблицы и файлы.
- С точки зрения мастера, чтение/запись данных выглядит как следующая последовательность команд:
- чтение:
- GetBasicAttributes — получение некоторых служебных атрибутов, без которых чтение невозможно;
- Fetch — получение списка чанков, из которых состоит файл или таблица;
- запись:
- GetBasicAttributes — получение некоторых служебных атрибутов, без которых запись невозможна;
- BeginUpload — открытие заливочной транзакции;
- EndUpload — завершение заливочной транзакции.
- чтение:
- При чтении/записи данных команда GetBasicAttributes приходит на один селл, а Fetch, BeginUpload и EndUpload — на другой; это нормально.
- В подавляющем большинстве случаев копирование или перемещение таблицы выглядят как команды Copy или Move. Команды BeginCopy и EndCopy используются, когда копирование/перемещение пересекает границы шардирования Кипариса. На практике пользователи с таким должны сталкиваться редко.
Лог запросов к HTTP-проксе
В данном логе журналируются записи о всех запросах, которые были обслужены HTTP-прокси.
Таблица 2 — Описание полей лога
Поле | Описание |
---|---|
instant |
Время события в формате YYYY-MM-DD hh:mm:ss,sss |
cluster |
Короткое имя кластера |
request_id |
Идентификатор данного запроса |
correlation_id |
Специальный идентификатор запроса, который генерируется клиентом и не изменяется в случае ретраев |
user |
Пользователь, выполняющий запрос |
method |
Метод HTTP-запроса |
http_path |
Путь HTTP-запроса |
user_agent |
Содержимое хедера User-Agent в запросе |
command |
Команда |
parameters |
Параметры данной команды |
path |
Значение параметра path |
error |
Стуктурированное описание ошибки, в случае если запрос завершился неуспешно |
error_code |
Код ошибки, в случае если запрос завершился неуспешно |
http_code |
HTTP-код ответа на данный запрос |
start_time |
Фактическое время начала исполнения запроса на проксе |
cpu_time |
Время, потраченное проксей на исполнение запроса (в него не входит время исполнения запроса в других компонентах кластера) |
duration |
Общая длительность запроса |
in_bytes |
Размер входных данных запроса в байтах |
out_bytes |
Размер выходных данных запроса в байтах |
remote_address |
Адрес, с которого пришел данный запрос |
Настройка ротации логов
Для отладочных и структурированных логов, которые пишутся в файл, можно настроить встроенный механизм ротации (поле rotationPolicy
). Настройки ротации приведены в таблице. Если не используется опция useTimestampSuffix
, в момент ротации файлы старых сегментов переименовываются, с дописыванием порядкового номера.
Таблица 3 — Настройки ротации логов
Поле | Описание |
---|---|
rotationPeriodMilliseconds |
Период ротации, в миллисекундах. Может задаваться вместе с maxSegmentSize . |
maxSegmentSize |
Ограничение на размер одного сегмента лога, в байтах. Может задаваться вместе с rotationPeriodMilliseconds . |
maxTotalSizeToKeep |
Ограничение на размер всех сегментов, в байтах. В момент ротации, удаляются самые старые логи так, чтобы уложиться в заданное ограничение. |
maxSegmentCountToKeep |
Ограничение на количество хранимых сегментов лога, в штуках. Самые старые сегменты сверх ограничения удаляются. |
Динамическая конфигурация
Компоненты, поддерживающие динамическую конфигурацию, позволяют дополнительно уточнить настройки системы логирования с помощью динамического конфига в Кипарисе, секция logging
.
Основные параметры:
enable_anchor_profiling
— включает prometheus-метрики по отдельным префиксам записей;min_logged_message_rate_to_profile
— минимальная частота сообщения, для попадания в отдельную метрику;suppressed_messaged
— список префиксов сообщений отладочных логов, которые будут исключены из логирования.
Пример конфигурации:
{
logging = {
enable_anchor_profiling = %true;
min_logged_message_rate_to_profile = 100;
suppressed_messaged = [
"Skipping out of turn block",
"Request attempt started",
"Request attempt acknowledged"
];
}
}
Пример настройки логирования
primaryMasters:
...
loggers:
- name: debug
compression: zstd
minLogLevel: debug
writerType: file
rotationPolicy:
maxTotalSizeToKeep: 50_000_000_000
rotationPeriodMilliseconds: 900000
categoriesFilter:
type: exclude
values: ["Bus", "Concurrency", "ReaderMemoryManager"]
- name: info
minLogLevel: info
writerType: file
rotationPolicy:
maxTotalSizeToKeep: 10_000_000_000
rotationPeriodMilliseconds: 900000
- name: error
minLogLevel: error
writerType: stderr
structuredLoggers:
- name: access
minLogLevel: info
category: Access
rotationPolicy:
maxTotalSizeToKeep: 5_000_000_000
rotationPeriodMilliseconds: 900000
locations:
- locationType: Logs
path: /yt/logs
- ...
volumeMounts:
- name: master-logs
mountPath: /yt/logs
- ...
volumeClaimTemplates:
- metadata:
name: master-logs
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 100Gi
- ...