Langfuse на власному VPS: розгортання та TLS
Розгорніть Langfuse на власному VPS: мінімальні ресурси, pinned image tags, TLS, retention для ClickHouse до заповнення диска та робочі backups.
Навіщо взагалі відстежувати роботу AI-агента
Ви розгортаєте Langfuse на власному сервері, щоб бачити, що саме агент зробив під час запуску. Langfuse — це open source інструмент observability для LLM (large language model). Він записує кожен prompt, кожну відповідь моделі, кожен виклик інструмента та кожен token, а потім об’єднує їх в один trace, який можна відкрити й переглянути. Якщо запускати його на власному VPS, ці prompt не залишають сервер, яким ви керуєте.
Причина проста. Неможливо виправити проблему з витратами або якістю, якої ви не бачите. Рахунок від провайдера показує, що у вівторок витрати були вчетверо більшими, ніж у понеділок. Trace показує, який запуск агента це спричинив, який prompt виріс до 40,000 token і який цикл повторних спроб виконався дев’ять разів, перш ніж завершитися помилкою. Рахунок дає число. Trace показує код, який це число сформував.
У цьому посібнику використовуються три терміни. Trace — це один повний запуск агента від початку до кінця. Observation — це один крок у межах такого запуску: span для звичайного коду або generation для виклику моделі. Score — це число, пов’язане з trace, отримане під час перевірки людиною або автоматизованим evaluator. Langfuse підтримує OpenTelemetry (OTel) — нейтральний щодо постачальників стандарт для розподіленого tracing, тому наявну instrumentation можна спрямувати до нього.
Що насправді запускає self-hosting Langfuse
Langfuse v4 — це не один контейнер. Це два контейнери застосунку та чотири сервіси зберігання. На одному VPS усі шість компонентів працюють на вашому сервері.
langfuse-webобслуговує вебінтерфейс і API приймання даних.langfuse-workerу фоновому режимі обробляє чергу. Він розбирає пакети даних, обчислює вартість і запускає нічне завдання очищення за політикою зберігання.- Postgres зберігає транзакційні дані, зокрема користувачів, організації, проєкти, API keys і prompts.
- ClickHouse зберігає самі дані трасувань, тобто observations і scores. Це колонкове сховище, призначене для аналітичних запитів, тому dashboard із понад ста мільйонами рядків усе ще швидко повертає результати.
- Redis — це черга та кеш між web і worker.
- MinIO надає S3 compatible object storage на сервері. Він зберігає кожну необроблену вхідну подію, а також усі прикріплені медіафайли.
Langfuse публікує мінімальні вимоги до ресурсів для трьох компонентів, які виконують основну роботу.
The data behind this chart
[
{
"label": "ClickHouse",
"cpu_cores": 2,
"memory_gib": 8
},
{
"label": "Langfuse web",
"cpu_cores": 2,
"memory_gib": 4
},
{
"label": "Langfuse worker",
"cpu_cores": 2,
"memory_gib": 4
}
]Лише ClickHouse потребує 8 GiB пам’яті. Контейнер web і worker потребують по 4 GiB кожен. Це опубліковані мінімальні значення для 3 компонентів, для яких Langfuse наводить вимоги. Postgres, Redis і MinIO також потребують додаткової пам’яті. Власний посібник проєкту з Docker Compose рекомендує машину з 4 ядрами, 16 GiB пам’яті та приблизно 100 GiB сховища. Це відповідає наведеному розрахунку, а не містить додаткового запасу.
Не запускайте це на тарифі з 2 GiB. ClickHouse запускається та деякий час приймає записи, але потім завершує роботу під час фонового злиття, оскільки злиття завантажує великі частини таблиці в пам’ять. Ви побачите, що docker compose ps повідомляє про контейнер clickhouse як restarting, dmesg містить рядок на кшталт Out of memory: Killed process 1234 (clickhouse-serv), а кожен dashboard Langfuse повертає 500. За меншого навантаження ClickHouse натомість відхиляє запит і записує в журнал DB::Exception: Memory limit (total) exceeded. Вісім GiB достатньо для одного розробника, який надсилає кілька тисяч трасувань на день. Плануйте 16 GiB.
Розгортання Langfuse за допомогою Docker Compose
Клонуйте репозиторій. Стек, конфігурація взаємодії та середовище за замовчуванням зберігаються у його docker-compose.yml.
git clone https://github.com/langfuse/langfuse.git
cd langfuseУсі значення, які потрібно змінити, позначені в цьому файлі як # CHANGEME. Спочатку згенеруйте три секрети застосунку.
openssl rand -base64 32 # NEXTAUTH_SECRET
openssl rand -base64 32 # SALT
openssl rand -hex 32 # ENCRYPTION_KEYENCRYPTION_KEY має мати довжину 256 біт і бути записаним як 64 шістнадцяткові символи. Саме такий результат виводить openssl rand -hex 32. Цей ключ шифрує конфіденційні значення в стані спокою, зокрема ключі провайдерів LLM, які ви зберігаєте в інстансі. Якщо змінити його після появи даних, ці рядки більше не можна буде розшифрувати, тому вважайте його незмінним від першого запуску. SALT використовується для хешування API-ключів Langfuse, тому його зміна зробить недійсними всі ключі, які вже використовують ваші агенти.
Потім задайте POSTGRES_PASSWORD, CLICKHOUSE_PASSWORD, REDIS_AUTH і MINIO_ROOT_PASSWORD. Пароль MinIO з’являється в чотирьох місцях: спочатку як MINIO_ROOT_PASSWORD, а потім як LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY, LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY і LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY. Якщо пропустити одне з них, MinIO відхилить запит цього клієнта з помилкою SignatureDoesNotMatch. Ця помилка з’явиться в журналі worker, хоча вебінтерфейс і далі виглядатиме справним. Зберігання цих значень в env-файлі, а не у tracked compose-файлі, описано в розділі env-файли та секрети Docker Compose.
Зафіксуйте теги образів перед запуском
У файлі, що постачається, використовуються langfuse/langfuse:4 і langfuse/langfuse-worker:4. Ці теги змінюються. Langfuse автоматично запускає міграції Postgres і ClickHouse під час запуску, тому звичайне docker compose pull через кілька місяців перетворюється на незаплановану міграцію схеми бази даних, резервну копію якої ви не створили того ранку. Зафіксуйте обидва образи на одному релізі у docker-compose.override.yml. Compose накладає цей файл поверх файлу, що постачається, тому подальший git pull не перезапише ваші зміни.
services:
langfuse-web:
image: docker.io/langfuse/langfuse:4.3.1
langfuse-worker:
image: docker.io/langfuse/langfuse-worker:4.3.1Версія 4.3.1 була поточною версією гілки 4.3 станом на August 2026 (відтоді випущено 4.4.0). Перевірте сторінку релізів проєкту на GitHub, зафіксуйте версію, актуальну в день розгортання, а потім змінюйте цей номер свідомо. Образи сховищ у файлі, що постачається, уже зафіксовані на рівні major-версій: postgres:17, clickhouse-server:25.12 і redis:7. До них слід застосувати такий самий підхід.
Запустіть стек.
docker compose up -d
docker compose ps
docker compose logs -f langfuse-workerПід час першого запуску виконуються міграції, тому зачекайте одну-дві хвилини, перш ніж перевіряти доступність сервісів. docker compose ps має показати шість сервісів у стані running. Якщо worker перезапускається в циклі, причина буде в його журналі: CLICKHOUSE_MIGRATION_URL використовує нативний протокол ClickHouse на порту 9000, а не HTTP-порт 8123. Якщо вказати порт 8123, worker завершиться з помилкою, хоча web-контейнер і далі виглядатиме справним.
Перевірте стан із самого сервера.
curl -s "http://localhost:3000/api/public/health?failIfDatabaseUnavailable=true"
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/api/public/readyЗвичайний виклик /api/public/health підтверджує лише те, що процес API працює, оскільки цей endpoint навмисно не перевіряє базу даних. Завдяки цьому сервіс продовжує обслуговування під час короткочасних збоїв Postgres. Форма failIfDatabaseUnavailable=true підходить для моніторингу. Вона повертає 503, якщо база даних недоступна. /api/public/ready повертає 200 після завершення міграцій, коли контейнер готовий приймати трафік. Обидві перевірки є звичайними HTTP-перевірками, тому сторінка стану Uptime Kuma може відстежувати їх і повідомити про недоступність стека раніше, ніж це помітять ваші агенти.
Налаштуйте TLS перед сервісом і закрийте додаткові порти
Файл compose, що постачається з комплектом, публікує 3000:3000 для вебконтейнера та 9090:9000 для MinIO. Обидва порти прив’язані до всіх інтерфейсів. На публічній IP-адресі це означає, що будь-хто, хто просканує порт 3000, відкриє сторінку реєстрації, а будь-хто, хто просканує 9090, отримає доступ до бакета із вашими необробленими prompt.
Одного правила firewall недостатньо, щоб закрити ці порти. Docker записує власні правила DNAT у таблицю nat. Вони обробляються ще до того, як пакет потрапляє до правил filter ufw, тому ufw deny 3000 залишає опублікований порт відкритим. Це трапляється досить часто, тому для цього є окремий посібник: чому опубліковані Docker порти обходять ufw. У файлі override прив’яжіть порти до loopback-інтерфейсу.
services:
langfuse-web:
ports:
- "127.0.0.1:3000:3000"
environment:
NEXTAUTH_URL: https://langfuse.example.com
minio:
ports:
- "127.0.0.1:9090:9000"
- "127.0.0.1:9091:9001"NEXTAUTH_URL має містити точну публічну адресу разом зі схемою, оскільки процес входу формує URL зворотного виклику на основі цього значення. Якщо за HTTPS-проксі залишити значення http://localhost:3000, під час входу браузер буде перенаправлено на адресу, до якої він не зможе підключитися.
Тепер налаштуйте reverse proxy на 127.0.0.1:3000 і передайте йому керування сертифікатом. Traefik у тому самому Compose-проєкті є типовим вибором, а routing labels описані в розділі як запустити кілька застосунків за одним reverse proxy Traefik. Якщо на сервері працює лише Langfuse, Caddy виконає це завдання у двох рядках. Перевірте налаштування за допомогою curl -sI https://langfuse.example.com/api/public/ready, а потім з іншої машини переконайтеся, що curl http://YOUR_IP:3000 тепер завершується тайм-аутом.
Є один нюанс щодо MinIO. Langfuse передає приєднані медіафайли у браузер через presigned URL, які вказують на цей S3 endpoint. Тому якщо ви використовуєте multimodal traces із зображеннями або аудіо, MinIO, доступний лише через loopback, не дасть завантажити ці вкладення. Перед проксуванням прочитайте сторінку про налаштування blob storage, оскільки endpoint, записаний у presigned URL, має відповідати опублікованій адресі. Текстові traces це не зачіпає.
Під час першого відвідування створіть власний обліковий запис і надалі контролюйте цей інстанс. Встановіть LANGFUSE_ALLOWED_ORGANIZATION_CREATORS на власну email-адресу, щоб стороння людина, яка відкриє сторінку, не могла створити організацію на вашому сервері. Якщо ви вже використовуєте Authentik як власний identity provider, Langfuse підтримує стандартне OIDC-підключення. Тоді облікові записи створюються та видаляються разом з обліковими записами інших ваших застосунків, а не зберігаються в окремому списку паролів, який відомий лише цьому серверу.
Надішліть свій перший trace
Створіть проєкт у вебінтерфейсі та скопіюйте його public і secret keys у налаштуваннях проєкту. Python SDK читає три змінні середовища.
export LANGFUSE_PUBLIC_KEY="pk-lf-..."
export LANGFUSE_SECRET_KEY="sk-lf-..."
export LANGFUSE_BASE_URL="https://langfuse.example.com"LANGFUSE_BASE_URL — це назва змінної в SDK v4, випущеному в березні 2026 року. У старішому коді та старіших посібниках використовується LANGFUSE_HOST. Якщо ваші trace потрапляють у Langfuse Cloud, а не на ваш сервер, причина полягає в тому, що base URL не задано: за замовчуванням використовується hosted instance.
pip install langfuse opentelemetry-instrumentation-anthropic anthropicimport os
from anthropic import Anthropic
from langfuse import get_client, observe
from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
AnthropicInstrumentor().instrument()
langfuse = get_client()
client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
@observe(as_type="tool")
def lookup_order(order_id: str) -> str:
return f"order {order_id}: shipped"
@observe()
def handle_request(question: str) -> str:
context = lookup_order("A-1042")
message = client.messages.create(
model="claude-haiku-4-5",
max_tokens=512,
messages=[{"role": "user", "content": f"{context}\n\n{question}"}],
)
return message.content[0].text
if __name__ == "__main__":
assert langfuse.auth_check()
print(handle_request("Where is my order?"))
langfuse.flush()Декоратор @observe відкриває observation навколо функції, записує її аргументи та значення, яке вона повертає, і вкладає його в поточний observation, якщо такий уже активний. AnthropicInstrumentor — це інструмент OpenTelemetry для клієнта Anthropic. Він перетворює кожен виклик messages.create на generation із назвою моделі, використанням токенів і затримкою без змін у місці виклику.
Дві команди виконують перевірку за вас. langfuse.auth_check() повертає False для неправильних ключів або помилкового base URL. Це швидше, ніж з’ясовувати, чому dashboard порожній. langfuse.flush() блокує виконання, доки queued spans не буде надіслано. Це потрібно для процесів із коротким часом роботи, оскільки SDK надсилає дані пакетами у фоновому режимі, а скрипт, який завершується одразу, завершується разом із ненадісланим пакетом.
Чому ClickHouse постійно займає дедалі більше місця?
Трейси — це дані, обсяг яких у більшості self-hosted систем зростає найшвидше. Кожен запуск агента записує один рядок для кожного кроку. Вхідні та вихідні дані зберігаються повністю, тому агент із великою кількістю повідомлень і довгими промптами створює за день значно більше даних, ніж застосунок, роботу якого він відстежує. Якщо нічого не налаштувати, ClickHouse заповнить диск, а заповнений диск призведе до зупинки запису даних, а не просто до його уповільнення.
Тут збільшуються два окремі типи даних. Для них потрібні різні рішення.
Перший тип — ваші власні дані трасування. Для них потрібно налаштувати період зберігання. Відкрийте налаштування проєкту у вебінтерфейсі та задайте період зберігання даних у днях. Langfuse приймає мінімальний період 3 дні. Після цього нічне завдання вибирає трейси, спостереження, оцінки та медіаактиви, старші за вказаний період, і видаляє їх із ClickHouse та blob storage. Для цього завданню потрібен дозвіл DeleteObject на bucket. Облікові дані root MinIO у типовому compose-файлі вже мають цей дозвіл. Видалення є незворотним, тому спочатку налаштуйте експорт у blob storage, якщо потрібна довготривала історія. Не додавайте TTL-умови вручну до власних таблиць Langfuse. Саме завдання зберігання підтримує узгодженість між ClickHouse і bucket, а ручний TTL видалить дані лише з одного боку.
Вибирайте період з урахуванням фактичного використання даних. Перевірка вартості та якості виконується на даних за останні дні, а не за кілька місяців. Для невеликої команди розумно почати з 30 днів. Якщо ви відкриваєте трейси лише тоді, коли щось перестає працювати, достатньо 14 днів.
Другий тип — власні системні таблиці журналів ClickHouse. Це часто стає несподіванкою, оскільки диск продовжує заповнюватися навіть після налаштування зберігання даних. ClickHouse записує trace_log, text_log, opentelemetry_span_log, metric_log і asynchronous_metric_log для власної діагностики. Вони постачаються без TTL, а Langfuse ніколи їх не читає. Спочатку з’ясуйте, що саме займає місце на диску.
SELECT table, formatReadableSize(size) AS size, rows FROM (
SELECT table, database, sum(bytes) AS size, sum(rows) AS rows
FROM system.parts
WHERE active
GROUP BY table, database
ORDER BY size DESC
)Виконайте цю команду з docker compose exec clickhouse clickhouse-client --password "$CLICKHOUSE_PASSWORD". Якщо системні таблиці перебувають серед найбільших, вимкніть їх за допомогою config overlay, оскільки під час запуску ClickHouse об’єднує кожен файл із /etc/clickhouse-server/config.d/ з основною конфігурацією.
<clickhouse>
<trace_log remove="1"/>
<text_log remove="1"/>
<opentelemetry_span_log remove="1"/>
<asynchronous_metric_log remove="1"/>
<metric_log remove="1"/>
</clickhouse>Підключіть цей файл і перезапустіть ClickHouse.
services:
clickhouse:
volumes:
- ./clickhouse-config.d/system-logs.xml:/etc/clickhouse-server/config.d/system-logs.xml:roЦе зупинить нові записи. Рядки, які вже є на диску, залишаться, тому звільніть місце явно за допомогою DROP TABLE IF EXISTS system.trace_log і виконайте те саме для кожної видаленої таблиці. Якщо діагностичні дані потрібно зберегти, замість remove="1" можна налаштувати агресивний TTL для кожної таблиці. Цей варіант описано в документації Langfuse щодо масштабування.
Варто знати ще про одну таблицю. blob_storage_file_log відстежує файли подій, завантажені у ваш bucket. Якщо для bucket також налаштовано політику життєвого циклу, задайте для таблиці відповідний TTL, щоб ці налаштування не розійшлися.
ALTER TABLE blob_storage_file_log MODIFY TTL created_at + INTERVAL 30 DAY DELETE;Також налаштуйте звичайне оповіщення df -h для диска з даними. Трейси не збільшуються рівномірно. Їхній обсяг різко зростає в день розгортання нового агента, і першим проявом цього не має бути збій запису даних.
Резервне копіювання Postgres і ClickHouse
Резервна копія Langfuse складається з трьох частин. Postgres зберігає користувачів, організації, проєкти та API keys. ClickHouse зберігає traces. MinIO зберігає необроблені події. Якщо відновити лише Postgres, ви отримаєте робочий вхід без історії. Якщо відновити лише ClickHouse, ви отримаєте історію, яку ніхто не зможе переглянути без входу.
Postgres — це звичайний pg_dump, як і рекомендує документація Langfuse щодо резервного копіювання.
docker compose exec -T postgres pg_dump -U postgres postgres \
| gzip > langfuse-pg-$(date +%F).sql.gzДля ClickHouse потрібно більше обережності, оскільки копіювання активного каталогу даних під час виконання злиттів не створює узгодженої резервної копії. Простий підхід на одному сервері — зупинити контейнер і заархівувати volume.
docker compose stop clickhouse
docker volume ls | grep clickhouse
docker run --rm -v langfuse_langfuse_clickhouse_data:/data -v "$PWD":/backup alpine \
tar czf /backup/langfuse-ch-$(date +%F).tar.gz -C /data .
docker compose start clickhouseВикористовуйте ім’я volume, яке виводить docker volume ls, а не ім’я, записане в YAML. Файл оголошує langfuse_clickhouse_data, а Compose додає до нього префікс із назви проєкту, тому клон у каталозі з назвою langfuse створює langfuse_langfuse_clickhouse_data. Якщо вказати неправильне ім’я, docker run без повідомлення про помилку створить новий порожній volume, і ваш архів не міститиме даних.
Вебконтейнер записує кожну вхідну подію у bucket до того, як worker її обробить, тому коротка зупинка ClickHouse переважно означає, що worker повторить спробу пізніше. Виконуйте це в період низького навантаження та не затягуйте операцію. Для завантаженішого екземпляра власна інструкція ClickHouse BACKUP DATABASE default TO S3(...) створює узгоджену резервну копію без зупинки сервера. MinIO — третя частина, і mc mirror або реплікація MinIO до зовнішнього bucket забезпечує її резервування. Незалежно від способу створення резервної копії, зберігайте її поза сервером. Саме для цього призначені зашифровані резервні копії restic на VPS.
Redis не потребує резервного копіювання. Він зберігає чергу та cache, тому його втрата призводить до втрати лише подій, які обробляються в цей момент, а не старих даних.
Обмеження щодо узгодженості є реальним, і його потрібно чітко враховувати. Postgres і ClickHouse експортуються в різні моменти часу, тому після відновлення може залишитися рядок проєкту без traces або traces, що належать проєкту, якого більше не існує. Langfuse це допускає, але створюйте обидві резервні копії з невеликим інтервалом і в період низького навантаження. Bucket подій є основним захистом, оскільки Langfuse зберігає в ньому кожну вхідну подію до початку обробки.
Хоча б один раз відновіть дані в тестовому стеку. Так ви виявите неправильне ім’я volume зараз, а не під час аварії.
На що звернути увагу спочатку
Першого тижня зосередьтеся на чотирьох показниках.
- Вартість одного trace. Langfuse обчислює вартість за назвою моделі та використанням токенів. Відсортуйте trace за вартістю й повністю перегляньте найдорожчий. Зазвичай причина — надмірно розрослий prompt: у контекст вставлено цілий документ або історію розмови ніхто не скорочує. Коли це видно, контроль витрат на AI agent стає інженерним завданням, а не припущенням.
- Розподіл використання токенів між input і output. Input-токенів багато, і вони дешеві. Output-токенів мало, але вони дорогі. Кешований input коштує ще дешевше. Цю саму систему обліку детально описано в матеріалі як обліковується використання токенів у Claude Code. Вона також застосовна до будь-якого agent, якого ви напишете самостійно.
- Перцентилі затримки. Медіана приховує проблему. Саме на рівнях p95 і p99 виникають timeouts. У циклі agent повільний виклик tool на рівні p95 множиться на кількість ітерацій.
- Невдалі виклики tool. Відфільтруйте observations за рівнем
ERROR. Tool, який завершується помилкою у 5% випадків, непомітний у загальному показнику успішності, але добре помітний у trace: модель повторює спробу, а потім витрачає токени на обхід проблеми.
Встановіть період зберігання даних і виберіть dashboard, який перевірятимете щотижня в той самий день, коли виконуєте deployment. Інструмент observability, який ніхто не відкриває, перетворюється на базу даних, що заповнює диск.
FAQ
Скільки пам’яті потрібно для self-hosted Langfuse?
Плануйте 4 ядра CPU і 16 GiB пам’яті. Саме такі ресурси рекомендує посібник Langfuse Docker Compose для однієї віртуальної машини. Також потрібно близько 100 GiB сховища. Опубліковані мінімальні вимоги компонентів становлять 8 GiB для ClickHouse і по 4 GiB для web- і worker-контейнерів. Postgres, Redis і MinIO додатково потребують пам’яті. Вісім GiB достатньо для інстансу одного розробника. Двох GiB недостатньо: ядро завершує роботу ClickHouse під час фонових злиттів, а dmesg показує Out of memory: Killed process.
Чому диск ClickHouse продовжує заповнюватися після налаштування зберігання даних?
Налаштування retention поширюється лише на власні дані Langfuse. ClickHouse окремо записує діагностичні таблиці trace_log, text_log, opentelemetry_span_log, metric_log і asynchronous_metric_log, для яких TTL не налаштовано. Виконайте запит system.parts із групуванням за таблицею, щоб визначити найбільшу таблицю. Потім вимкніть непотрібні таблиці за допомогою запису remove="1" у файлі в каталозі /etc/clickhouse-server/config.d/, перезапустіть ClickHouse і видаліть наявні таблиці, щоб звільнити вже зайнятий простір.
Який мінімальний період зберігання даних у Langfuse?
Три дні. Retention налаштовується окремо для кожного проєкту в параметрах проєкту або через projects API. Нічне завдання видаляє з ClickHouse і blob storage traces, observations, scores та media assets, старші за встановлений період. Видалення неможливо скасувати, тому спочатку налаштуйте експорт у blob storage, якщо потрібна історія за межами цього періоду.
Чи потрібно створювати резервні копії і Postgres, і ClickHouse?
Так, оскільки вони зберігають різні дані. Postgres зберігає користувачів, організації, проєкти та API keys, а ClickHouse — самі trace data. Відновлення лише Postgres дасть інстанс, у який можна увійти, але в ньому не буде даних. Також створюйте резервну копію bucket MinIO, оскільки в ньому зберігаються raw events, які Langfuse записує під час надходження. У цій системі це найближче до джерела істини.
Чи можна підключити наявне налаштування OpenTelemetry до self-hosted Langfuse?
Так. Langfuse v4 і його v4 SDK побудовані на OpenTelemetry, а інструментації Anthropic і OpenAI OTel експортують дані безпосередньо до нього. У Python виконайте pip install langfuse opentelemetry-instrumentation-anthropic, один раз викличте AnthropicInstrumentor().instrument() під час запуску та задайте LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY і LANGFUSE_BASE_URL для власного хоста. Перед пошуком відсутнього dashboard перевірте результат за допомогою langfuse.auth_check().