Страница 1

Более быстрый робот в первом задании MTS True Tech Champ

posted on 2025-11-20

Как я писал в предыдущей заметке, первая моя попытка провести робота через две комнаты из первого задания хакатона МТС True Tech была неудачной. Робот ехал медленно и сбивался с пути. Но в какой-то момент один из участников подсказал мне в чате, что нужно действовать иначе.

Первая моя ошибка была в том, как я пытался вывести робота из тупика, откуда он начинает свой путь. Я сначала делал разворот на 180 градусов. И это было медленно. Чертовски медленно. На разворот уходила почти минута. А надо было просто выезжать задом!

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

Второй совет заключался в том, что надо ориентироваться не на путь по точкам, а на лазерные лучи. У робота на борту был лидар, у которого угол обзора составлял 90 градусов. Ну и вот, я написал очень простой код, который позволял роботу двигаться с определенной скоростью и углом поворота до тех пор, пока не выполнится условие.

Когда условие выполнялось, робот переходил к следующему шагу. Мог изменить скорость, угол разворота и проверял новые условия, которые должны наступить, чтобы перейти к дальнейшему шагу. Для того, чтобы это было удобно описывать в коде, я написал маленький макрос, который позволял указать параметры движения и условия выхода. Причем в условии выхода можно было написать любой лисп-код, в том числе логирование или какие-то сложные вычисления.

В дальнейшем я даже усовершенствовал этот макрос и сделал так, что и скорость с углом поворота тоже можно вычислять на каждом шаге. Вот пример такого кода, которому следовал робот. Каждый блок go-until соответствует шагу, который выполняется до тех пор, пока тело макроса не вернет true. Под капотом у каждого из таких блоков лежит цикл:

;; Выезжаем из тупика
(go-until (2.0)
  (log-step 1)
  ;; Меряем расстояние по центрально точке лидара
  (> front 4.5))

;; Начинаем поворачивать вправо
(go-until (2.0 :turn-angle 45.0)
  (log-step 2)
  ;; Используем крайние точки лидара
  (and (around left 2.80)
       (around right 4.35)))

;; Движемся по прямой до стены
(go-until (2.0)
  (log-step 3)
  (around front 8.0))

;; Поворачиваем налево, к мосту
(go-until (2.0 :turn-angle -30.0)
  (log-step 4)
  (and (around left 2.71 :delta 0.2)
       (around front 3.49 :delta 0.2)
       (around right 6.26 :delta 0.2)))

То есть робот в цикле, роботу отправляется команда ехать с указанной скоростью и углом разворота. И в цикле же проверяется условие выхода из цикла. Вот и всё! На такой простой идее получилось достичь достаточно стабильных результатов и проехать уровень не сбавляя скорости.

Как я это отлаживал? Запускал в симуляторе робота и смотрел по крайним точкам лидара на расстояния. В момент, когда мне нужно было, например, перейти из прямолинейного движения робота в поворот, я смотрел примерное положение, которое показывает лидар и вносил эти значения в условия выхода из последнего блока робота. Следом за ним добавлял следующий блок с измененными характеристиками движения. И смотрел дальше, какие параметры мне нужно отследить, чтобы посчитать условия выхода для этого нового блока.

Так получилось проложить всю траекторию от начала до конца. На видео, которое приложено выше, как раз и показано, как робот проходит весь путь из комнаты 1 в комнату 2, обходя все препятствия.

В следующем посте расскажу, как обстояли дела со вторым заданием хакатона MTS True Tech Champ 2025.

Первый этап хакатона МТС True Tech Champ 2025

posted on 2025-11-16

Как и обещал, начинаю серию постов про хакатон MTS True Tech 2025. Это технический хакатон, который разделен на две части. Первая часть алгоритмическая, а вторая часть робототехническая. Участвовать можно только в какой-то одной. Я решил попробовать себя в робототехнике. При этом опыта на момент старта было примерно ноль. Никогда раньше ничего не делал для роботов и было очень интересно попробовать.

Хакатон начался в сентябре, но присоединился я к нему только лишь в начале октября, пропустив довольно большое количество времени просто из-за того, что в сентябре участвовал в другом хакатоне, лидеры цифровой трансформации, да и не было полной уверенности еще в том, что я хочу попробовать себя в робототехнике. MTS TrueTech состоит из нескольких этапов.

Первый этап, отборочный, представлял собой три задачи, которые нужно было решить. В каждой задаче требовалось управлять роботом внутри симулятора. При этом код можно было писать на любом языке и, конечно, я выбрал в качестве языка Common Lisp. Было интересно попробовать, как вообще на нем можно делать что-то для роботов.

Cоздатели MTS TrueTech подготовили для участников специальную прослойку, которая позволяла запускать код, управляющий роботом, как отдельный процесс, и она могла взаимодействовать с симулятором, получая от него информацию и подавая управляющие воздействия на робота.

На видео, которое приложено к этому посту, видно одно из моих первых решений. Это решение для первой задачи, первого отборочного этапа, где нужно было проехать роботом из одной виртуальной комнаты в другую, обойдя все препятствия. Мы называли эту задачу "уточки", потому что робот стартовал из тупика ограниченного игрушечными уточками.

В этом решении участникам заранее организаторы сказали, что можно, в общем-то, и захардкодить путь робота. Это я и пытался сделать почти неделю – хотел написать алгоритм, который проведет робота по точкам. Но дело осложнялось тем, что у робота была большая инерция, а так же не было точных координат этого робота. Из-за этого он постоянно пролетал мимо точек, либо доворачивался не на тот угол, который нужно. В итоге, к концу трека робот часто сбивался c пути и не выходил на заданную точку – до центра второй комнаты, где нарисован белый прямоугольник.

Затем мне один из участников в чате подсказал, что на самом деле нужно использовать другой подход. Я переключился на другой подход и сделал решение не за неделю, а всего за полдня. В этот раз робот ехал ориентируясь на лидар.

Лидар это такое устройство, которое с помощью лазера измеряет расстояние до других объектов. Вот у робота был такой лидар, который направлен вперед. И по этому лидару я замерял расстояние до стен. Причем использовал всего три точки лидара. Одну, которая смотрит прямо, и два крайних луча, которые смотрят под 45 градусов. Я написал специальный DSL-чик на Лиспе, который позволяет описать последовательность условий, при которых нужно изменять управляющее воздействие на робота.

И с помощью такого нехитрого алгоритма робот гораздо более стабильно начал доходить до цели. При чём мой робот проехал уровень достаточно быстро, чтобы попасть на 45 строчку лидерборда из 124 участников!

Если вам интересно, напишите в комментариях, и я следующим постом приложу ролик, который показывает, как робот ехал по новому алгоритму, и покажу кусочек кода того, как выглядел на DSL для описания шагов робота.

Каково это, быть многоруким Шивой?

posted on 2025-11-09

Иногда меня спрашивают: "Саша, как ты все успеваешь?" Но обычно эти люди не подозревают, что успеваю я очень малую часть того, что задумано. У меня постоянно, есть куча каких-то проектов и идей, над которыми хочется поработать. Снаружи может казаться, что я успеваю многое, но на самом деле я делаю лишь небольшую часть из того, что запланировал. А все остальные планы копятся и копятся.

Причем свойство характера у меня такое, что когда возникает какая-то новая идея, я ею загораюсь и начинаю работать над ней, отбросив всё остальное. Иногда это мешает доводить дела до конца. Например, уже в начале сентября я доделал свой проект по созданию статических сайтов из телеграм-каналов до того состояния, когда его можно давать пробовать другим людям. Но вместо того, чтобы заняться раскруткой этого проекта маркетингом, писать статьи для Хабра, я переключился на другой проект, потому что начался осенний хакатон "Лидеры цифровой трансформации 2025".

Над ЛЦТ проектом я поработал несколько недель, но, к сожалению, в финал мы так и не вышли. Поэтому данный проект был оставлен в стороне, хотя получился, безусловно, прикольный продукт – мы сделали HR-систему для привлечения кандидатов в игровой форме.

Далее я увлекся следующей идеей – переключился на хакатон, который устраивал МТС. Этот хакатон был ориентирован на создание ПО для автономного управления роботами.

МТС второй год уже проводит такой хакатон. Называется он "МТС True Tech". Наверное, в серии следующих нескольких постов я расскажу, как и что делал в рамках этого хакатона. С начала октября по начало ноября я учился программировать роботов. В том году я не стал ввязываться в этот хакатон, потому что казалось, что у меня вообще же нет опыта, как я буду делать что-то, связанное с робототехникой? А в этом году я просто загорелся этой идеей, махнул рукой на то, что опыта ровно ноль и решил как-нибудь поучаствовать.

Удивительно, что даже при отсутствии опыта мне удалось пройти в полуфинал. Но детали подробности расскажу в следующих постах.

Но какой же ответ на заголовок этого поста? Каково быть многоруким Шивой и браться за всё, что хочется?

Как по мне, это очень прикольно, потому что разнообразит кругозор, позволяет попробовать много разного и не закиснуть в рутине. Так что, ребята, не бойтесь и пробуйте себя во всём!

Почему я использую package-inferred ASDF стиль в своих библиотеках

posted on 2025-08-24

C package-inferred ASDF, тебе не надо задумываться о том, какие зависимости есть между твоими файлами. Точнее задумываеться конечно надо, но исключается ситуация, когда ты прописал их в неправильном порядке.

Например, если ты добавляешь в один из файлов использование символа, который определен в другом файле как функция, то нужно поменять местами эти модули в описании ASDF системы.

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

В случае же с в package-inferred system, все зависимости между компонентами системы прописываются явно в каждом файле. За счёт этого легко отследить какие символы из какого файла проимпортированы, а загрузчик библиотеки загружает файлы в правильном порядке согласно импортам в DEFPACKAGE.

Но даже в случае с package-inferred system зависимости надо прописывать в каждый файл и это можно забыть сдеалать. В таком случае, при загрузке библиотеки с нуля может возникнуть ошибка в духе "такой-то пакет не найден". Чтобы предотвратить случаи, когда для какого-то из используемых символов я забыл прописать IMPORT-FROM, я сделал линтер, который проверяет (в том числе и в PR), что:

• Ни одна из зависимостей не забыта • Нет неиспользуемых импортов

Это позволяет поддерживать ASDF систему в здоровом состоянии.

Конечно, для небольшой системы, состоящей из одного файла, использование старого способа описания ASDF системы не вызывает проблем. Однако со временем системы склонны разрастаться.

Когда система становится большой, рефакторить ее и переделывать из old-school ASDF систем в package-inferred system может быть довольно проблематично.

Также, то что package-inferred ASDF система требует явного описания и указания пространства имён, в которое помещаются символы. Это помогает пользователям библиотек лучше понимать, к какой области относится определённый символ.

Конечно, то же самое можно сделать, определив несколько пакетов и описав их в системе в старом стиле. Однако это потребует дополнительных усилий, так как нет чётких правил о том, в каком пакете должны находиться символы из определённого файла.

Как я вижу, тут коммон-лисперы разделяются на два лагеря. Одни - любят и используют package-inferred, другие - ненавидят. А к какому лагерю относишься ты?

Обсудить пост в Telegram канале.

Современный i18n с Fluent

posted on 2025-08-17

Периодически я просматриваю новые библиотеки, которые добавляются в репозиторий https://ultralisp.org. Недавно мне попалась Common Lisp библиотека для интернационализации программ на Common Lisp. Она называется Fluent.

Я начал разбираться, как она работает, и оказалось, что Fluent — это стандарт, подход к интернационализации, предложенный несколько лет назад компанией Mozilla. С тех пор для этого формата переводов создали библиотеки для разных языков программирования. Теперь такая библиотека появилась и для Common Lisp.

Чем Fluent отличается от давно известного всем gettext и ему подобных? Формат Fluent предлагает более гибкий подход к формированию переводов. Под каждый язык и его грамматические особенности можно сделать свой шаблон. Fluent чем-то напоминает язык шаблонов Mustache.

Для примера покажу, как это выглядит на Common Lisp. Сначала нужно создать директорию для хранения переводов. Для примера сделаем поддержку английского и русского языков.

Для английского перевода создадим файл /tmp/i18n/en-US/app.ftl с таким содержимым:

apples-and-leafs = { $apple-count ->
    [one] {$apple-count} apple
   *[many] {$apple-count} apples
} and { $leaf-count ->
    [one] {$leaf-count} leaf.
   *[many] {$leaf-count} leafs.
}

Аналогичный файл /tmp/i18n/ru-RU/app.ftl создадим для русского языка:

apples-and-leafs = { $apple-count ->
    [one] {$apple-count} яблоко
    [few] {$apple-count} яблока
   *[many] {$apple-count} яблок
} и { $leaf-count ->
    [one] {$leaf-count} лист.
    [few] {$leaf-count} листа.
   *[many] {$leaf-count} листов.
}

Обратите внимание, что в русском языке три формы множественного числа, а в английском только две. Благодаря гибкости формата Fluent, можно описать в файле целое предложение, даже если оно зависит от нескольких чисел.

Когда директория с переводами готова, мы можем загрузить эти переводы и получить текст на нужном языке. В Common Lisp это выглядит так:

CL-USER> (let ((ctx (fluent:fluent (fluent:read-all-localisations #P"/tmp/i18n/")
                                   :locale :ru-ru)))
           (fluent:resolve ctx "apples-and-leafs" :apple-count 21 :leaf-count 33))
"21 яблоко и 33 листа."

CL-USER> (let ((ctx (fluent:fluent (fluent:read-all-localisations #P"/tmp/i18n/")
                                   :locale :en-us)))
           (fluent:resolve ctx "apples-and-leafs" :apple-count 21 :leaf-count 33))
"21 apples and 33 leafs."

По-моему, довольно гибкое решение.

Если мне когда-нибудь понадобится делать приложение с переводами, я обязательно буду использовать Fluent. А был ли у вас опыт создания мультиязычных приложений? Если да, расскажите комментариях, какой подход к хранению переводов использовали?

Обсудить пост в Telegram канале.

Свой Code Assistant

posted on 2025-07-20

Все выходные я провозился с созданием своего собственного Code Assistant. Очень интересно было разобраться в том, как вообще все это работает. К сожалению, статей именно про устройство кодовых ассистантов не так уж много.

В основном попадаются восторженные статьи про то, как круто работает вайб-кодинг, как с его помощью написали первый Hello World и тому подобное говно. Но мне повезло найти одну очень интересную статью, где автор анализирует работу IDE Cursor и устройство его промпта.

Я начал писать своего кода-ассистента, ориентируясь на исходники проекта Aider, но посматриваю и на другие проекты с открытым кодом, типа RooCode, Cline и прочих.

Сегодня случился замечательный момент — мой ассистент смог отредактировать файл. Он самостоятельно нашел место для правки, составил патч, наложил его с помощью инструментов и внес изменения. На демо прикрепленном к этому посту, видно, что сначала ассистент попытался найти упоминание функции по кодовой базе, затем прочитал часть найденного файла с помощью инструмента read_file, а затем сгенерировал и наложил на него патч.

Я изучил, как устроено редактирование файлов в Aider и Cursor. Там правки происходят через вызовы к LLM — формируется небольшой патч в кастомном формате, где указаны старые и новые исходники, затем эти инструкции скармливаются более быстрой LLM, которая уже и меняет исходник.

Я пошел другим путем — для редактирования использую CLI команду patch, научив LLM формировать правильный diff. Пока работает неидеально: иногда дифф получается некорректным, и команда патч ломается. Но если показать LLM ошибку, она делает следующую попытку с исправленным патчем. Обычно ко второй-третьей попытке всё получается.

Я планирую дальше развивать код-ассистент. Теперь нужно добавить цикл проверки изменений через тестирование.

Особенно интересно работать с таким проектом в Common Lisp — можно быстро экспериментировать: смотреть внутренний стейт, править функции, добавлять новые инструменты и сразу тестировать изменения. Такой режим работы очень удобен. Даже для интерфейса я пока использую CL REPL, но планирую добавить веб-интерфейс и может быть консольный, как у Aider. Пока, это площадка для экспериментов!

Обсудить пост в Telegram канале.

Как продвигаются дела с MCP фреймфорком для Common Lisp

posted on 2025-06-29

Привет, друзья! Сегодня хочу дать небольшой апдейт по тому, как продвигаются дела с MCP-фреймворком для того, чтобы можно было писать MCP-сервера на Common Lisp.

На этих выходных я закончил реализацию протокола с Streamable-HTTP. Для чего это нужно было? Почему нельзя было обойтись просто поддержкой STDIN/STDOUT протокола? Streamable-HTTP позволяет создавать MCP-сервера, к которым смогут подключаться клиенты удаленно. То есть этот MCP-сервер может быть развернут где-то в облаке.

Одна из моих ближайших целей - сделать MCP-сервер для сайта https://ultralisp.org. Идея пока такая, что Ultralisp будет предоставлять MCP-сервер для поиска Common Lisp библиотек, а также для поиска функций, макросов и прочего, что внутри этих библиотек есть.

То есть этот MCP-сервер будет давать код-ассистенту доступ к док-стрингам всех Lisp библиотек. И тогда код-ассистент сможет находить нужные ему библиотеки и функции внутри этих библиотек, даже если эти библиотеки еще не установлены в его окружении. И далее с помощью других инструментов код-ассистент сможет эти библиотеки поставить и воспользоваться теми функциями, что он нашел.

Для этого я добавил в свой MCP-фреймворк поддержку Streamable-HTTP. Чтобы это сделать, пришлось написать еще одну библиотечку, которая реализует поддержку Server-Sent Events протокола для CLACK - clack-sse.

Server-Sent-Events - это такой упрощенный аналог WebSocket, который позволяет серверу отправлять события на клиент по HTTP. В Streamable-HTTP протоколе MCP-сервера этот метод используется для того, чтобы отправлять уведомления об изменениях внутри сервера.

В видео, которое закреплено в этом посте, я как раз показываю, для чего используются такие пуши с сервера. Там демонстрируется, как при изменении инструментов внутри Common Lisp образа уведомления автоматически доставляются в IDE, и оно мгновенно узнает о том, что поменялось описание инструмента или, например, добавился новый инструмент.

Выглядит все это довольно круто, теперь можно с помощью моего фреймворка интерактивно разрабатывать MCP-сервера и тут же их тестировать в IDE.

Обсудить пост в Telegram канале.

VoiceInk - opensource альтернатива для SuperWhisper

posted on 2025-06-16

Некоторое время назад я посетил семинар, посвященный вайб-кодингу. Там коллега в лайв-режиме показывал, как он создает код с помощью нейросети, используя голосовой ввод. Я очень удивился, потому что стандартный голосовой ввод на маке часто путает слова. Когда ты диктуешь ему по-русски, он часто неправильно воспринимает текст, если в нем используются английские термины, например, названия функций. Голосовой ввод на маках все это путает и выводит в лучшем случае что-то неразборчивое или далекое от того, что ты просил.

После семинара я спросил коллегу, что он использует для голосового ввода. Оказалось, что он использует программу SuperWhisper. Я посмотрел на эту программу и увидел, что она требует подписки, а платежи из России, как понимаете, выполняются сложно. Кроме того, мне не хотелось вязываться в какой-то vendor-lock, когда производители программы могут просто отказаться принимать платежи от россиян или как-то иначе заблокировать свой продукт на нашей территории. Поэтому я решил поискать open-source решение, аналогичное SuperWhisper.

И такое решение я нашел! Программа называется VoiceInk. VoiceInk выполняет похожую задачу и достаточно качественно разбирает текст. Настолько хорошо, что после того, как я надиктовал сообщение для блога, мне требуется всего лишь немного его отредактировать, поправив кое-где формулировки.

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

Например, вы можете сделать отдельный промпт для того, чтобы писать заметки в блог. Можно сделать отдельный промпт для того, чтобы отвечать на e-mail коллегам или для того, чтобы твиты писать. Вот, например, я для VoiceInk сделал себе промпт, который вы видите на скриншоте к этому посту.

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

Возможно, можно даже дальше пойти и научиться сделать какого-то агента, в котором можно просто целиком этот текст надиктованный закидывать и получать готовую публикацию в Телеграме уже с картинкой. Но эту автоматизацию я, может быть, сделаю позже. У меня есть идея попробовать N8N сервис для того, чтобы делать подобные штуки. Так что следите за обновлениями в блоге. Пока-пока!

Обсудить пост в Telegram канале.

Почему я ломаю обратную совместимость

posted on 2025-06-15

Сначала хотел сделать пост про то, почему я редко сохраняю обратную совместимость в своих open-source библиотеках. Вот недавно как раз сделал обновление библиотеки Reblocks, в которой поломал обратную совместимость, причем довольно серьезно.

Переделал одновременно и макрос, который отвечает за рендеринг в HTML, и еще более серьезно переделал роутинг — то есть часть, которая отвечает за преобразование URL и выбор того, какую страницу по этому URL показать.

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

В итоге иногда с программным обеспечением проще отказаться от сохранения обратной совместимости. Но даже если вы так делаете, то лучше качественно описать те изменения, которые были сделаны, и предложить пути по миграции со старого кода на новый. Я обычно в своих проектах всегда веду change log, в котором подробно такие изменения описываю.

И вот недавно мне эта обратная несовместимость как раз-таки довольно больно стрельнула. Мне потребовалось обновлять сайт https://ultralisp.org, и в нем довольно много пришлось переделывать из-за того, что как раз-таки обратной совместимости в новом Reblocks не было. Но зато сам по себе код Reblocks остался чистым, хотя мне пришлось перепилить для поддержки новой версии еще несколько библиотек, которые его используют.

Иногда обратную совместимость сохранить полезно. Но это стоит делать в том случае, если поддержать ее достаточно дешево и там не будет каких-то адовых костылей.

Приходилось ли вам ломать обратную совместимость в своих библиотеках или каком-то ином программном коде? Если да, то расскажите, чем это обернулось. Были ли какие-то серьезные последствия? Или, наоборот, вы рады принятому решению?

Обсудить пост в Telegram канале.

Про структурное логгирование в Python и Yandex Cloud Function

posted on 2025-06-14

Сегодня я продолжал возиться со своим pet-project, который одной ногой работает в SaleBot, а второй - использует Yandex Cloud Functions и YDB для того, чтобы запускать более сложную бизнес-логику.

И сегодня полдня я провел за тем, что пытался правильно настроить структурное логирование так, чтобы в Яндекс.Облаке было хорошо и красивенько видно все ошибки и отладочные сообщения от моего бота. Очень странно, что документация самого Яндекс Клауда не дает подробных примеров того, как настроить логирование в Python правильным образом.

Оно говорит очень просто: логируйте все в stdout, и мы как-то сохраним эти логи. Но при этом сами примеры, которые они приводят, таковы, что, например, если у вас логируется stacktrace, то он размазывается по всем сообщениям. Stacktrace при этом разделяется на отдельные сообщения лога, и совершенно непонятно, что происходит. В интерфейсе Yandex Cloud просто какая-то каша.

Вот, я покопал немножечко эту тему и нашел, что на самом-то деле Яндекс Клауд умеет разбирать логи в виде JSON. Так что странно, что нет у них в документации по использованию Python для Cloud Functions примера, как правильно настроить логгинг правильно.

Итого я нашел библиотечку, которая реализует JSON handler для стандартного модуля логинг. И еще я нашел библиотеку, которая добавляет к этому возможности структурного логирования.

Структурное логирование полезно тем, что помимо сообщения в виде текста, вы можете в свои логи добавлять какие-то дополнительные поля. Да, конечно, это можно и так делать с помощью аргумента extra. Но в этом случае вы вынуждены передавать этот аргумент extra в каждое сообщение лога.

А представьте, например, у нас в API пришел запрос в котором известен client_id. И мы хотим, чтобы этот client_id присутствовал во всех записях логов. Например, там, каких-то отладочных логов, при обращении к базе. Короче, если ошибка произойдет, там обязательно должен быть client_id, чтобы можно было по конкретному клиенту выбрать все логи, связанные с этим клиентом.

И вот, чтобы не прописывать при логировании client_id в каждое сообщение, можно использовать структурное логирование. Он работает, как контекстный менеджер, которому вы один раз на входе в API метод говорите, что пришел такой-то client_id, а далее, во все логи внутри этого контекстного менеджера автоматически подставится это поле client_id.

И вот я сегодня использовал этот подход, объединил JSON Logger и вот эту утилиту для структурного логирования, и получилось, по-моему, очень классно.

Думаю даже сделать такую заготовку, которая позволит быстро стартануть и создать Yandex Cloud Function на Python со всеми готовыми настройками для логирования и для работы с YDB.

Что думаете насчет такой заготовочки? Была бы она кому-нибудь еще полезна? Если что, пишите в комментариях, выложу куда-нибудь на GitHub. Пока!

Обсудить пост в Telegram канале.

Created with passion by 40Ants