[Разбор] У Langfuse 10-20 минут лага в UI. Почему я оставил свой трейсер в продакшене

На прошлой неделе закрыл задачу: интеграция Langfuse в свой опен-сорсный агентный фреймворк Tuplet. Через два дня после деплоя понял, что без встроенного трейсера работать невозможно.

[Разбор] У Langfuse 10-20 минут лага в UI. Почему я оставил свой трейсер в продакшене

В итоге оба остались в проде. Один моментальный локальный, второй облачный. Не один вместо другого, а два параллельно. Расскажу, почему так получилось и почему это не костыль.

Контекст: зачем агенту трейсинг

Tuplet - TypeScript-фреймворк для построения AI-агентов внутри приложений. Один пользователь моего калорийного бота тратит на месяц от $0.50 до $4 - в зависимости от того, как агент ходит по тулам. Без трейсинга вы не поймёте, почему две одинаковые задачи отличаются по стоимости в восемь раз.

Поэтому я добавил полноценную интеграцию с Langfuse - стандартом индустрии. 24 тысячи звёзд на GitHub, OpenTelemetry-нативный, в январе 2026 их купил ClickHouse за $400 млн. Если кто-то из CTO спрашивает, чем трейсить агентов, первый ответ обычно Langfuse.

Интеграция оказалась чистой

Я не использовал их SDK, потому что он тянет 4-5 транзитивных зависимостей. Сделал свой провайдер на голом fetch:

  • agent.run -> trace
  • LLM-вызов -> generation с input/output токенами и cost
  • Tool-вызов -> span с input/output JSON
  • Sub-agent -> вложенное наблюдение

Батчинг событий, флаш по таймеру или размеру очереди, корректное завершение через shutdown. Сессии, теги, userId работают. Получился полнофункциональный TraceProvider в 300 строках кода.

Задеплоил. Запустил пару прогонов. Открыл UI.

Что обнаружил

Пусто. Жду минуту - пусто. Пять минут - пусто. Двенадцать минут - наконец появилось.

Проверил на трёх запусках в разное время суток, на свежем проекте: устойчивый лаг 10-20 минут между событием и его появлением в UI Langfuse Cloud.

Для production-обсервабилити это не критично. Вы смотрите вчерашние данные, считаете cost retrospectively, строите дашборды, гоняете evals на накопленных трейсах. 15 минут лага никто не замечает.

Для итерации промпта это смерть.

Почему 20 минут ломают цикл итерации

Когда вы допиливаете промпт агента, цикл выглядит так: правка - запуск - смотрю trace - правка - запуск. Между итерациями 30-60 секунд. За час 30-50 проходов.

Если на каждый прогон ждать 18 минут, чтобы увидеть результат, цикл итерации становится 18 минут вместо 60 секунд. Скорость работы падает в 18 раз. Это не дебаг, это саботаж.

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

Решение: два трейсера параллельно

Я не выкинул Langfuse. Оставил его, но добавил в Tuplet второй провайдер - встроенный, который пишет события в локальный JSON моментально.

Архитектура:

  • Встроенный трейсер - JSON-файл рядом с проектом. Открываю в редакторе, фильтрую по нужному запуску, читаю в человеческом виде. Лаг меньше секунды.
  • LangfuseTraceProvider - те же события уходят в облако параллельно. С задержкой 10-20 минут, но в проде это уже не критично.

Оба провайдера получают идентичные события через единый интерфейс TraceProvider. Хост-приложение подключает любой из них или оба сразу.

Вывод: dev-observability и prod-observability - это разные задачи

Dev-цикл требует моментального локального фидбека. Толерантность к задержке - ноль. Объём - один прогон, который вы сейчас смотрите.

Production требует durable, query-able, распределённый сбор данных. Толерантность - минуты. Объём - все запуски за месяц с поиском, фильтрами, метриками.

Натягивать один инструмент на оба сценария - проигрыш. Большинство фреймворков предлагают только облачный вариант, потому что про dev-цикл просто не думают. И зря: цикл итерации промпта самый болезненный в AI-инженерии, и ждать 18 минут на каждый прогон - роскошь, которую нельзя позволить.

Что взять у себя

Если вы строите агента и проектируете observability:

  1. Встроенный или локальный трейсер для dev-цикла. Любой, который пишет результат сразу - JSON в файл, sqlite, локальный SSE.
  2. Облачный для прода: Langfuse, Phoenix, Helicone, Laminar. Им можно простить лаг.
  3. Не выбирайте между ними - запускайте оба через единый интерфейс.

Решение про два трейсера в Tuplet выглядело как избыточность. На практике оказалось, что это просто признание того, что у dev и prod разные SLA, и пытаться их объединить дороже, чем держать оба.

А вы как дебажите агентов? Используете облачный трейсер и миритесь с лагом, или нашли что-то моментальное?

Начать дискуссию