summaryrefslogtreecommitdiffstats
path: root/library/cpp/unified_agent_client/client_impl.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Serialize TGrpcTimer on completion queue threadandybg6 days1-4/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ## 1. В чём была проблема У сессии gRPC-клиента (`TClientSession`) несколько таймеров на базе **`TGrpcTimer`** используют один и тот же механизм: внутри лежит **`grpc::Alarm`**, привязанный к **одному** `CompletionQueue`, события с которого обрабатывает **отдельный поток** poller (в логах и стеках — `ua_grpc_cq`). **Публичные методы** `TGrpcTimer::Set` и `Cancel` вызывались **и с этого потока** (после срабатывания alarm, из колбэков завершения gRPC-операций, из `Poll` и т.д.), **и с других потоков** — например, при старте сессии из потока пула (`DoStart` → первый `MakeGrpcCallTimer->Set`). В результате **один и тот же** `grpc::Alarm` и связанные с ним поля таймера менялись **конкурентно без синхронизации**. ThreadSanitizer фиксировал **data race** внутри реализации alarm в gRPC; с точки зрения контракта это **недопустимое параллельное использование** обёртки над alarm. Типичный конфликт: на потоке приложения выполняется **`Set`** (первый запуск таймера переподключения), параллельно на **`ua_grpc_cq`** обрабатывается завершение вызова и снова вызывается **`Set`** для отложенного переподключения — оба попадают в **`Alarm::Set`** для одного объекта. --- ## 2. Изменение архитектуры (как починили) Инвариант: **любое изменение состояния `TGrpcTimer`, которое трогает `grpc::Alarm` и служебные поля таймера, выполняется только на потоке, который крутит `CompletionQueue::Next` для этого клиента** (тот же поток, что обрабатывает срабатывания alarm). Для этого: - Введены внутренние **`ApplySet` / `ApplyCancel`** — в них перенесена прежняя логика работы с alarm; вызывать их разрешено **только** в контексте poller. - Публичные **`Set` / `Cancel`**: если вызов уже идёт **из** poller (определяется **thread-local** флагом на время обработки события из CQ), сразу вызываются **`Apply*`**; иначе работа **ставится в ту же** `CompletionQueue` через **искусственное завершение** (`grpc_cq_begin_op` / `grpc_cq_end_op`), а колбэк на стороне poller выполняет **`Apply*`**. - Чтобы отложенная операция не обращалась к уже уничтоженной сессии, перед постановкой в очередь делается **`TryRef`** на **`TAsyncJoiner`** сессии; после выполнения **`Apply*`** — **`UnRef`**. Если сессия уже уходит в закрытие и joiner недоступен, отложенный **`Set`/`Cancel`** тихо отбрасывается. С точки зрения **`client_impl`**, вызовы **`MakeGrpcCallTimer->Set`**, **`ForceCloseTimer->Set`**, **`PollTimer->Set`**, **`->Cancel`** **не менялись** — меняется только реализация внутри **`TGrpcTimer`** и конструктор (передаётся ссылка на **`AsyncJoiner`** сессии). --- ## 3. Новая архитектура: sequence diagram и пример {% cut "Таблица потоков, примеры A/B и диаграммы Mermaid" %} Ниже — **два типичных сценария** для одного таймера, например **`MakeGrpcCallTimer`** (переподключение после завершения gRPC-вызова). ### Где именно теперь «живёт» работа с таймером | Действие | Поток | | :--- | :--- | | Публичный **`Set` / `Cancel`** с **стороны приложения** (не poller) | Постановка задачи в **CQ**; реальное **`Apply*`** — на **`ua_grpc_cq`**. | | Публичный **`Set` / `Cancel`** уже **внутри** обработчика события CQ (вложенный вызов) | Сразу **`Apply*`** на том же потоке (**без** повторной постановки). | | Срабатывание **`grpc::Alarm`** | Доставка в poller → **`TGrpcTimer::OnIOCompleted`** → при необходимости снова **`Alarm.Set`** / вызов пользовательского колбэка — **всё на `ua_grpc_cq`**. | ### Пример A: первый `Set` при старте сессии (поток приложения) Сессия стартует в **`DoStart`** на **рабочем** потоке; **`MakeGrpcCallTimer->Set(Now())`** не трогает alarm напрямую — **ставит** в CQ задачу «выполнить **`ApplySet`**»; poller **выполняет** её и выставляет alarm. ```mermaid sequenceDiagram participant App as AppThread participant Timer as TGrpcTimer participant CQ as CompletionQueue participant Poller as ua_grpc_cq App->>Timer: Set(now) Timer->>Timer: not poller thread Timer->>Timer: TryRef(AsyncJoiner) Timer->>CQ: enqueue synthetic op CQ-->>Poller: Next delivers op Poller->>Timer: deferred callback Timer->>Timer: ApplySet(now) Timer->>Timer: Alarm.Set + schedule Timer->>Timer: UnRef(AsyncJoiner) ``` ### Пример B: перепланирование после завершения вызова (уже на poller) **`OnGrpcCallFinished`** вызывается с **CQ** после обработки тега gRPC; **`MakeGrpcCallTimer->Set(reconnectTime)`** попадает в **fast path** и сразу вызывает **`ApplySet`** на **`ua_grpc_cq`** — без очереди. ```mermaid sequenceDiagram participant Poller as ua_grpc_cq participant Session as TClientSession participant Timer as TGrpcTimer Poller->>Session: OnGrpcCallFinished Session->>Timer: Set(reconnectTime) Timer->>Timer: poller thread (TLS) Timer->>Timer: ApplySet(reconnectTime) ``` ### Срабатывание alarm (напоминание) Когда срабатывает **внутренний** alarm gRPC, poller получает тег **`TGrpcTimer`**, вызывает **`OnIOCompleted`**: там снова возможны **`Alarm.Set`** (перенос по **`NextTriggerTime`**) или переход к **пользовательскому** колбэку (**`MakeGrpcCall`**, **`Poll`**, **`BeginClose`** и т.д.) — **всё на том же потоке `ua_grpc_cq`**. {% endcut %} --- {% cut "Технические детали (файлы, API gRPC, TSAN, lifetime)" %} ### Файлы в Arcadia | Файл | Роль | | :--- | :--- | | `library/cpp/unified_agent_client/grpc_io.h`, `grpc_io.cpp` | `TGrpcTimer`, `TPostedCompletion` / `TPostedBridge`, `PostIIOCallbackToCompletionQueue`, `TlsInUaGrpcCompletionQueuePoller` в цикле poller. | | `library/cpp/unified_agent_client/client_impl.cpp` | Создание трёх `TGrpcTimer` с передачей `AsyncJoiner` сессии. | ### Низкоуровневая постановка в CQ Паттерн тот же, что у **`TGrpcNotification::Trigger`**: **`grpc_core::ApplicationCallbackExecCtx`**, **`grpc_core::ExecCtx`**, **`grpc_cq_begin_op`**, **`grpc_cq_end_op`**. Тег **`CompletionQueueTag`** — отдельный объект; в **`FinalizeResult`** в poller передаётся **`IIOCallback`** (мост), который выполняет отложенную лямбду и освобождает себя после **`OnIOCompleted`**. ### TSAN () В отчёте TSAN конкурирующие записи шли в **`grpc::internal::AlarmImpl::Set`** из потока **`ua_grpc_cq`** (цепочка **`OnGrpcCallFinished` → `MakeGrpcCallTimer->Set`**) и из потока приложения (**`DoStart` → `MakeGrpcCallTimer->Set(Now())`**). После фикса оба пути сериализуют **`ApplySet`** на poller. ### Поведение при закрытии сессии Если **`TryRef(AsyncJoiner)`** не удался, отложенный **`Set`/`Cancel`** не ставится — сессия уже в фазе **`Join`**. Уже стоящие в CQ задачи удерживают ref до выполнения **`Apply*`** и **`UnRef`**. ### Заглушка счётчика для `MakeIOCallback` Для отложенной лямбды используется **`TNoOpRefStub`**: **`Ref`/`UnRef`** пустые; удержание сессии обеспечивается парой **`TryRef`/`UnRef`** на **`TAsyncJoiner`**, а не счётчиком **`TIOCallback`**. {% endcut %} commit_hash:ba05e9c98e41bcf748270a48a818cc7d233a161b
* gRPC inactivity watchdog only for negotiated protocol v1+andybg2026-04-241-18/+62
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Unified Agent: новый протокол стриминга и изменения в клиенте Документ опирается на `library/cpp/unified_agent_client/proto/unified_agent.proto` и реализацию `TClientSession` в `client_impl.cpp`. --- ## 1. Новый протокол **Legacy** — сессия без согласования версии: в ответе `Initialized` поле `protocol_version` отсутствует или равно **0**. Поведение соответствует старому контракту до появления опциональных полей согласования. **Версионированный режим (v1 и выше)** — клиент объявляет максимально поддерживаемую версию (`accept_protocol_version`), агент возвращает **согласованную** версию `protocol_version` и опционально **opaque**-токен привязки сессии. Дальнейшие реконнекты с тем же `session_id` требуют передачи **доказательства** привязки (`session_binding_proof`), чтобы сервер мог отличить легитимное продолжение от подмены. Семантика потока данных не меняется: после `Initialized` идут `DataBatch` / `Ack`, ретраи по `seq_no` и дедупликация на стороне агента при совпадении `session_id` и повторной отправке записей. --- ### 1.2. Новые поля **Запрос `Request.Initialize`** | Поле | Тип | Назначение | |------|-----|------------| | `accept_protocol_version` | `optional uint32` | Верхняя граница версии, которую клиент готов использовать (стиль HTTP Accept). **Не задано или 0** — клиент не предлагает новый протокол (legacy-only). | | `session_binding_proof` | `bytes` | Доказательство привязки при реконнекте; используется, когда согласована версия **> 0** и у клиента есть токен от предыдущего `Initialized`. | Поля `session_id`, `meta`, `shared_secret_key` — как раньше; `session_id` при реконнекте передаётся для дедупликации. **Ответ `Response.Initialized`** | Поле | Тип | Назначение | |------|-----|------------| | `protocol_version` | `optional uint32` | Согласованная версия: **min**(accept клиента, максимум сервера). **Не задано или 0** — сессия считается **legacy**. | | `session_binding_token` | `bytes` | Непрозрачный токен: клиент обязан вернуть его в следующем `Initialize` как `session_binding_proof` при переподключении (для версий протокола **≥ 1**). | Остальное без изменений: `session_id`, `last_seq_no`. --- ### 1.3. Процесс и логика выбора версии 1. Клиент задаёт **`MaxAcceptProtocolVersion`** (в коде: `SetMaxAcceptProtocolVersion`). Значение **0** означает: поле `accept_protocol_version` в `Initialize` **не отправляется** — только legacy. 2. Если `MaxAcceptProtocolVersion > 0`, в первом (и последующих) сообщении `Initialize` выставляется `accept_protocol_version = MaxAcceptProtocolVersion`. 3. Агент вычисляет согласованную версию как **min**(`accept_protocol_version`, собственный потолок поддерживаемых версий) и возвращает её в `Initialized.protocol_version`. Если клиент не прислал accept (legacy-only) или сервер отвечает **0** / не задаёт поле — на клиенте фиксируется **legacy** (`NegotiatedProtocol` сбрасывается). 4. При успешном `Initialized` с **`protocol_version > 0`** клиент сохраняет число версии в `NegotiatedProtocol` и копирует `session_binding_token` во внутреннее состояние для следующих коннектов. #### Диаграмма обмена (Mermaid sequence) Первое подключение с согласованием версии и привязкой: ```mermaid sequenceDiagram participant C as Клиент (TClientSession) participant G as gRPC stream participant A as Unified Agent C->>G: открыть Session(stream Request / stream Response) C->>A: Request.initialize<br/>accept_protocol_version = N (если N>0)<br/>session_id (опц.)<br/>meta, shared_secret_key, … Note over A: min(N, server_max) → negotiated A->>C: Response.initialized<br/>session_id<br/>last_seq_no<br/>protocol_version = negotiated<br/>session_binding_token (opaque) C->>C: сохранить NegotiatedProtocol,<br/>SessionBindingToken, SessionId loop Данные C->>A: Request.data_batch (seq_no, payload, …) A->>C: Response.ack (seq_no) end Note over C,A: обрыв стрима → реконнект ``` Реконнект при согласованной версии **> 0**: ```mermaid sequenceDiagram participant C as Клиент participant A as Unified Agent C->>A: Request.initialize<br/>session_id = сохранённый<br/>accept_protocol_version = N<br/>session_binding_proof = прежний token<br/>… A->>C: Response.initialized<br/>session_id, last_seq_no,<br/>protocol_version, session_binding_token (может обновиться) C->>A: Request.data_batch … ``` --- ### 1.4. Восстановление сессии и обмен ключами - **Идентификатор сессии:** `session_id` приходит от сервера в `Initialized` и дальше передаётся в `Initialize` при реконнекте — основа для дедупликации и продолжения с теми же `seq_no`. - **Shared secret:** по-прежнему `shared_secret_key` в `Initialize` (если задан в параметрах клиента) — отдельный канал авторизации/проверки, не смешивается с биндингом стрима. - **Привязка сессии (protocol v1+):** после первого успешного `Initialized` с `protocol_version > 0` клиент хранит `session_binding_token`. При следующем `PrepareInitializeRequest`, если есть `NegotiatedProtocol > 0` и непустой токен, в запрос кладётся `session_binding_proof` (содержимое токена). Так сервер связывает новый gRPC-стрим с прежней логической сессией. - **Конфликт сессии:** при завершении gRPC-вызова с кодом **`ALREADY_EXISTS`** клиент **сбрасывает** `SessionId`, `NegotiatedProtocol` и `SessionBindingToken`, чтобы следующий коннект не повторял конфликтующий идентификатор и не слал устаревшее proof (см. `OnGrpcCallFinished` в `client_impl.cpp`). --- ### 1.5. Совместимость клиентов и серверов | Клиент | Сервер | Результат | |--------|--------|-----------| | `MaxAcceptProtocolVersion = 0` | любой | Поле `accept_protocol_version` не отправляется; ожидается legacy-ответ (`protocol_version` 0 / отсутствует). Биндинг по токену не используется. | | `MaxAcceptProtocolVersion > 0` | только legacy | Обычно `protocol_version` в ответе 0 или отсутствует — клиент остаётся в legacy для этой сессии. | | `MaxAcceptProtocolVersion > 0` | поддерживает v1+ | Согласуется конкретное число (например 1); включаются `session_binding_token` / `session_binding_proof` на реконнектах. | | Новый клиент | старый агент | Безопасный откат: нет обязательных новых полей в wire-format для legacy; сервер игнорирует неизвестные optional-поля (proto3). | Важно: поведение «только новый протокол» для отдельных механизмов (например принудительная отмена стрима по неактивности) в клиенте завязано на **фактически согласованную** версию **`NegotiatedProtocol > 0`**, а не только на настройку `MaxAcceptProtocolVersion`. --- ## 2. Изменения в клиенте — исправления и защита от регрессий Ниже — логика, связанная с новым протоколом и устойчивостью сессий (файл `client_impl.cpp`, заголовки `client.h` / `client_impl.h`). 1. **Согласование версии и биндинг** — `PrepareInitializeRequest` выставляет `accept_protocol_version` только при `MaxAcceptProtocolVersion > 0`; при наличии согласованной версии и токена добавляет `session_binding_proof`. `OnGrpcCallInitialized` выставляет `NegotiatedProtocol` и `SessionBindingToken` только если `protocol_version` задан и **> 0**, иначе очищает их (строгий legacy). 2. **Конфликт `ALREADY_EXISTS`** — при таком статусе завершения стрима сбрасываются `SessionId`, `NegotiatedProtocol` и `SessionBindingToken`, чтобы не зациклиться на неверной паре (session_id, proof) и не провоцировать повторные конфликты на стороне агента. 3. **Watchdog неактивности gRPC (`GrpcCallInactivityTimeout`)** — принудительное закрытие активного вызова (`BeginClose(true)`) и счётчик `GrpcCallsClosedByInactivity` выполняются **только** при `NegotiatedProtocol.Defined() && *NegotiatedProtocol > 0`. Для legacy и до первого успешного `Initialized` с ненулевой версией отмена по этому таймеру **не** выполняется; таймер перепланируется как раньше. Это устраняет нежелательное принудительное реконнект-поведение на транспортах, где ранее допускалось «молчание» без отмены (см. план по этому пути). 4. **Пост-fork дочерний процесс** — сброс `SessionId`, `NegotiatedProtocol`, `SessionBindingToken` вместе с очередями, чтобы дочерний процесс не унаследовал привязку чужой сессии. Документация в публичном API: комментарий к `SetGrpcCallInactivityTimeout` в `client.h` описывает ограничение по согласованной версии протокола. --- *При необходимости уточнения формулы `min(accept, server_max)` на стороне агента смотрите реализацию сервера в репозитории `logbroker/unified_agent` (обработка `Initialize` в gRPC-сессии).* commit_hash:9d5ef1cdc0faf793b4f56bfd2bafa362d7995ac5
* C++ client reconnect after agent SIGKILL/long outageandybg2026-04-101-0/+60
| | | | | | | | | | | | | | | | | | | | | | | | ## Проблема После аварийного завершения агента (SIGKILL) или длительной недоступности C++ клиент Unified Agent не восстанавливал соединение сам. Сессия оставалась в состоянии «активна», сообщения накапливались в буфере (inflight), при достижении лимита начинались потери (dropped messages), и доставка не возобновлялась даже после поднятия агента — требовался перезапуск приложения-клиента. ## Как исправлено Добавлен механизм «страховки»: если у сессии есть не подтверждённые сообщения (inflight), но по активному gRPC-стриму долго нет никакой активности (ни read, ни write, ни finish), клиент принудительно отменяет текущий вызов и запускает обычный путь реконнекта (повторные попытки установки сессии). «Длительность молчания» задаётся новым параметром; по умолчанию механизм включён (30 с) — зависание сессии никому не нужно, отключить можно явно, выставив таймаут в 0. {% cut "Технические детали" %} **Корневая причина:** реконнект планировался только в `OnGrpcCallFinished`, то есть после завершения активного stream-вызова. При «зависшем» транспорте (transport stall после падения агента) gRPC мог не вызывать финальный callback, `ActiveGrpcCall` оставался занятым, и новый `MakeGrpcCall` не запускался. **Изменения в коде:** - В `TClientParameters` добавлен параметр `GrpcCallInactivityTimeout` (по умолчанию 30 с; 0 = отключено). - В сессии заведён периодический watchdog-таймер; при срабатывании проверяется: есть ли активный `TGrpcCall`, есть ли inflight-сообщения и не было ли активности дольше заданного таймаута. При выполнении условий вызывается принудительное закрытие текущего call (`BeginClose(true)`), что приводит к `OnGrpcCallFinished` и планированию следующего `MakeGrpcCall` по `GrpcReconnectDelay`. - Время последней активности обновляется при любом успешном событии стрима (Accept, Read, Write, Finish, а также при инициализации сессии и при ack). **Тестирование:** добавлен интеграционный тест `TestReconnectAfterLongStall` (агент поднимается → сессия и первая доставка → убийство агента → отправка во время даунтайма → пауза → повторный запуск агента → проверка, что inflight обнуляется и сессия переинициализируется без рестарта приложения). Регрессии по существующим reconnect-тестам не наблюдаются. {% endcut %} commit_hash:f55efec2cff20fa975500e73d60ee57654abb2e0
* /2: Use our internal logger header, add logging metricsiofik2026-02-191-3/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | # Улучшения библиотеки логирования и переход на троттлинг логов ## Описание Этот PR содержит улучшения системы логирования unified\_agent с акцентом на предотвращение флуда логов и добавление метрик логирования. ## Основные изменения ### 1. Улучшения библиотеки логирования (`library/cpp/unified_agent_client/logger`) - **Встроенный троттлинг логов**: Добавлена поддержка ограничения частоты логирования на уровне библиотеки - Новые макросы `YLOG_*_T` с автоматическим троттлингом (20 логов на 10 секунд по умолчанию) - Независимый троттлинг для каждой точки логирования (по `__FILE__:__LINE__`) - Автоматический подсчет подавленных сообщений с выводом `[+N suppressed]` - **Метрики логирования**: Добавлены счетчики для мониторинга активности логирования - `RecordsReceived` - общее количество попыток логирования - `RecordsDropped` - количество подавленных сообщений из-за троттлинга - Счетчики передаются через `TLogger::TCounters` при создании логгера - **Оптимизация производительности**: - Использование `GetCycleCount()` для быстрого получения времени (вместо системных вызовов) - Relaxed memory ordering для атомарных операций (достаточно для троттлинга) - Минимальные накладные расходы при отключенном логировании ### 2. Переход всех логов агента на троттлинг - **Унификация макросов**: Все макросы `YLOG_*` в `logbroker/unified_agent/common/util/logger.h` теперь используют троттлинг - `YLOG_DEBUG`, `YLOG_INFO`, `YLOG_WARNING`, `YLOG_ERROR` и т.д. теперь автоматически применяют троттлинг - Старые макросы `YLOG_*_F` теперь алиасы для новых троттлированных версий - Обратная совместимость полностью сохранена - **Обновление документации**: Файл `for_ai_cpp.md` обновлен с новыми рекомендациями по логированию ### 3. Интеграция метрик логирования в телеметрию - **Новые счетчики в `TAgentLogCounters`**: - `RecordsReceived` - rate метрика `agent.log.records_received` - `RecordsDropped` - rate метрика `agent.log.records_dropped` - **Экспорт метрик**: Метрики логирования автоматически собираются и отправляются в телеметрию агента - **Рефакторинг конструктора `TAgent`**: - Упрощена передача счетчиков через структуру `TAgent::TCounters` - Счетчики логирования передаются в `TLogger` при инициализации ### 4. Тесты - **Перенос тестов**: Тесты логирования перемещены из `logbroker/unified_agent/tests/gtests/logger_tests` в `library/cpp/unified_agent_client/ut` - **Расширенное покрытие**: - Тесты базового троттлинга - Тесты счетчика подавленных сообщений - Тесты независимого троттлинга для разных точек логирования - Тесты форматирования сообщений - Тесты счетчиков метрик ### 5. Исправления и улучшения - **Удаление дублирования кода**: Логика троттлинга теперь находится только в `library/cpp/unified_agent_client/logger.cpp` - **Упрощение API**: Удален отдельный файл `logbroker/unified_agent/common/util/logger.cpp` - **Обновление импортов**: Все файлы обновлены для использования правильных заголовочных файлов ## Преимущества 1. **Защита от флуда логов**: Автоматическое ограничение частоты логирования предотвращает переполнение логов 2. **Наблюдаемость**: Метрики логирования позволяют отслеживать активность и проблемы с логированием 3. **Производительность**: Минимальные накладные расходы благодаря оптимизированной реализации 4. **Простота использования**: Троттлинг работает автоматически, не требует изменений в коде 5. **Обратная совместимость**: Все существующие макросы продолжают работать ## Тестирование - ✅ Все unit-тесты логирования проходят - ✅ Integration тесты обновлены (исключение нестабильной метрики `RecordsReceived` из сравнений) - ✅ Проверена работа троттлинга в реальных условиях commit_hash:75fc97a8576114446bfb9ec11efbb80df322e443
* Add throttling for max inflight error logsandybg2026-01-151-2/+17
| | | | | | | | | | | | | | ## Problem Log spam with repeated ``'max inflight of [***] bytes reached, [***] bytes dropped'`` errors appearing multiple times within the same second, causing log flooding. ## Solution Implemented one-second throttling mechanism for this specific error message to prevent log spam while maintaining accurate counter tracking. ## Testing - Added `TestMaxInflightBytesThrottling` integration test - Confirms throttling limits log entries to ≤3 for 50 rapid message drops (vs 50 without throttling) - Ensures all dropped message counters remain accurate regardless of throttling commit_hash:58f44ca8ce2b8b416586f8ca7a3d3ca971f1e9cb
* Use lower case for TString methods Data, Size and Empty in extsearch, ↵mikhnenko2024-10-101-2/+2
| | | | | | | fintech, games, geobase, infra, ipreg, juggler, kernel, keyboard, laas, library, logbroker, logos, mail If you think that this pr has broken something for you, roll it back commit_hash:df8e48b2a4ecbbc74a504aa3ff62ebb8f464218d
* Y_VERIFY->Y_ABORT_UNLESS at ^lilnurkh2023-10-091-22/+22
| | | | https://clubs.at.yandex-team.ru/arcadia/29404
* unified-agent: add log for SeqNoaleksei-le2023-08-201-1/+1
|
* client-cpp for unified-agent: changing log levelaleksei-le2023-07-031-18/+18
|
* [unified agent] fix printf specifiers for 32 bit arch /gluk472023-06-261-13/+13
|
* feat grpc: correct order of the fork variable setleonidlazarev2023-05-221-1/+10
| | | Correct order of the GRPC_ENABLE_FORK_SUPPORT set
* Log backend movehor9112023-02-091-0/+1274