Уроборос: что он записывает и когда это нужно
Это первая глава курса про инструмент, который показывает, как код исполнялся на самом деле. Здесь — что он делает и когда за ним стоит идти. Ставить и запускать начинаем со следующей главы.
Что он делает
Инструмент дописывает в ваш исходник строки, которые ничего не вычисляют, а только записывают случившееся. Программа после этого запускается как обычно, и каждый вызов обмазанной функции оставляет две записи: одну при входе, вторую при выходе.
Записи копятся в файле debug.info — по одному объекту JSON в строке. Набор
таких записей дальше называется трассой.
Три слова, которые встречаются в каждой главе:
- обмазать — дописать в исходник строки, которые ведут запись. Сам код при этом не переписывается: тело функции остаётся ровно таким, каким было.
- трасса — файл
debug.infoс записями одного прогона. - доводы — то, с чем функцию позвали.
Как выглядит запись
Вот две настоящие строки из прогона, который разбирается в следующей главе:
{"p":"in","t":"2026-09-10T19:59:29.262","id":"36c9ba0c-e827-4e03-9020-3f9745d1a37c","ci":-1,"th":"7.129140652823040","fn":"discount_rate","a":"9999, False","k":""}
{"p":"out","id":"36c9ba0c-e827-4e03-9020-3f9745d1a37c","fn":"discount_rate","r":"0.0","d":2e-06}
Ключи короткие нарочно: записей бывает много, и лишние байты в каждой строке стоят места.
| ключ | на какой строке | что означает |
|---|---|---|
p |
на обеих | in — в вызов вошли, out — из вызова вышли |
t |
in |
время входа |
id |
на обеих | номер вызова; по нему пара строк и связывается |
fn |
на обеих | имя функции |
a |
in |
позиционные доводы |
k |
in |
именованные доводы |
r |
out |
что вернули |
x |
out |
что бросили. Стоит вместо r, а не вместе с ним |
d |
out |
сколько вызов занял, в секундах |
ci |
in |
номер ядра процессора; -1 — узнать не удалось |
th |
in |
какой поток вызывал |
Три вещи в этой раскладке решены осознанно, и каждая пригодится дальше.
Записей две, а не одна. Записать только результат было бы вдвое дешевле, но
тогда вызов, который завис или упал так, что не вернулся, не оставил бы
следа вообще. А так он оставляет строку in без парной строки out — и это
самый дешёвый ответ на вопрос «где оно висит».
Доводы снимаются до тела функции. Функция, которая портит то, что ей передали, всё равно запишет то, с чем её позвали, а не то, во что она это превратила.
Имя функции стоит на обеих строках. Если трасса оборвалась на середине и
строка in потерялась, строка out всё равно говорит, что именно вернулось.
Три задачи, на которых это окупается
Разобраться в чужом коде. Прочитать сорок тысяч строк дорого, прогнать — дёшево. Через десять минут известно, какие функции живые, с чем их зовут и в каком порядке. Регулярно выясняется, что живых путей три, а остальное не исполнялось ни разу.
Найти причину падения, когда стека не хватает. Стек говорит, откуда позвали.
Трасса говорит, с чем позвали, — и обычно ответ там. В разборе из следующей
главы стек показывает TypeError в сравнении, а трасса показывает довод
'free' вместо числа: строку, которой в стеке нет.
Дать ИИ-агенту факты вместо догадок. Модель, читающая исходник, рассуждает о том, что может случиться. Трасса говорит, что случилось. Про это — глава про работу с агентом.
Чем это не является
Не профилировщик. Профилировщик меряет цену кода. Здесь записи сами стоят
работы, и прогон с ними идёт медленнее. Поле d — честная длительность вызова
в обмазанном прогоне, и читать её как цену того же кода без обмазки нельзя.
Не отладчик с точками останова. Программа не останавливается и ничего не ждёт от человека. Прогон идёт как обычно, записи копятся сами.
Не покрытие. Покрытие говорит, что строка исполнилась. Трасса говорит, с чем позвали функцию и что вышло.
Не доказательство правильности. Трасса записывает, как код себя вёл, а не как он должен себя вести. Это главное ограничение, и ему посвящена последняя глава.
Две стороны инструмента
Одна и та же начинка выставлена наружу двумя способами.
Командная строка — семнадцать команд. Для начала нужны четыре: обмазать файл, обмазать выбранные функции, прочитать трассу, свести её в сводку.
Сервер MCP — те же семнадцать операций, отданные ИИ-агенту. Это тот же способ подключения внешних инструментов, которым к агенту подключаются остальные серверы.
Курс идёт по командной строке: то же самое видно глазами, и повторить можно сразу. Работа через агента разобрана в четвёртой главе.
Что дальше
- Первый прогон — поставить, обмазать свой файл, запустить, прочитать записи.
- Отказы — когда инструмент не делает того, о чём его попросили, и почему это правильно.
- Что записывать и как найти нужное — весь файл или выбранные функции, и как отобрать вызовы из тысячи записей.
- Работа с ИИ-агентом — сервер MCP, песочница из чернового и чистового каталогов, формулировка задания.
- Восемь языков — одна схема записи и разные способы обмазки.
- Границы — чего инструмент не делает. Эту главу сокращать нельзя.
Короткое описание без курса — на странице Уробороса в разделе инструментов.