SSD Nodes Learn 🎉 VPS od $5.50/mies.
Przewodniki Matt ConnorAutor: Matt Connor · Zaktualizowano 2026-08-13

Własna instancja Langfuse na VPS: konfiguracja i hosting

Dowiedz się, jak samodzielnie hostować Langfuse na własnym VPS. Artykuł omawia optymalizację ClickHouse, zarządzanie retencją danych, konfigurację TLS oraz skuteczne kopie zapasowe.

Dlaczego warto śledzić działanie agenta AI

Samodzielne hostowanie Langfuse pozwala sprawdzić, co faktycznie wykonał agent podczas uruchomienia. Langfuse to narzędzie open source do monitorowania LLM (large language model). Rejestruje ono każdy prompt, każdą odpowiedź modelu, każde wywołanie narzędzia oraz każdy token, a następnie grupuje je w ramach jednego śledzenia (trace), które można otworzyć i przeanalizować. Uruchomienie narzędzia na własnym VPS gwarantuje, że prompty nigdy nie opuszczają serwera, nad którym sprawujesz kontrolę.

Powód, dla którego warto to robić, jest oczywisty. Nie można naprawić problemów z kosztami ani jakością, których nie można zaobserwować. Faktura od dostawcy informuje, że wtorek kosztował cztery razy więcej niż poniedziałek. Śledzenie wskazuje, które uruchomienie agenta było przyczyną, który prompt urósł do 40,000 tokenów oraz która pętla ponownych prób wykonała się dziewięć razy przed przerwaniem działania. Faktura podaje liczbę. Śledzenie wskazuje kod, który ją wygenerował.

W niniejszym przewodniku użyto trzech terminów. Trace (śledzenie) to jedno pełne uruchomienie agenta od początku do końca. Observation (obserwacja) to pojedynczy krok wewnątrz tego uruchomienia: span dla zwykłego kodu lub generation dla wywołania modelu. Score (wynik) to liczba przypisana do śledzenia, pochodząca z oceny ludzkiej lub automatycznego ewaluatora. Langfuse obsługuje OpenTelemetry (OTel), czyli niezależny od dostawcy standard śledzenia rozproszonego, dzięki czemu istniejąca już instrumentacja może być skierowana na to narzędzie.

Co faktycznie uruchamia self-hosted Langfuse

Langfuse v4 nie jest pojedynczym kontenerem. To dwa kontenery aplikacji i cztery usługi pamięci masowej. Na pojedynczym serwerze VPS wszystkie sześć działa na Twojej maszynie.

  • langfuse-web obsługuje interfejs WWW oraz API przyjmowania danych (ingestion API).
  • langfuse-worker przetwarza kolejkę w tle. Analizuje partie danych wejściowych, oblicza koszty i uruchamia nocne zadania retencji.
  • Postgres przechowuje dane transakcyjne, takie jak użytkownicy, organizacje, projekty, klucze API oraz prompty.
  • ClickHouse przechowuje same dane śledzenia (trace data), czyli obserwacje i wyniki. Jest to kolumnowa baza danych stworzona do zapytań analitycznych, dzięki czemu dashboardy działają szybko nawet przy setkach milionów wierszy.
  • Redis pełni rolę kolejki i pamięci podręcznej między interfejsem WWW a procesem roboczym (worker).
  • MinIO zapewnia pamięć obiektową zgodną z S3 na serwerze. Przechowuje wszystkie surowe zdarzenia przychodzące oraz wszelkie załączone multimedia.

Langfuse publikuje minimalne wymagania zasobowe dla trzech komponentów, które wykonują główną pracę.

ChartLangfuse published minimum resources per component
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
  }
]

Sam ClickHouse wymaga 8 GiB pamięci RAM. Kontener WWW oraz worker wymagają po 4 GiB każdy. Są to opublikowane wartości minimalne dla 3 komponentów, które Langfuse uwzględnia w szacunkach, a Postgres, Redis i MinIO wymagają dodatkowej pamięci. Oficjalny przewodnik Docker Compose dla tego projektu zaleca maszynę z 4 rdzeniami, 16 GiB pamięci RAM i około 100 GiB przestrzeni dyskowej, co odpowiada tym wyliczeniom bez zbędnego zawyżania.

Nie należy próbować uruchamiać tego na planie z 2 GiB RAM. ClickHouse uruchomi się, przez pewien czas będzie przyjmował zapisy, a następnie ulegnie awarii podczas scalania danych w tle (background merge), ponieważ operacja ta ładuje duże fragmenty tabeli do pamięci. Wtedy docker compose ps zgłosi kontener clickhouse jako restarting, dmesg wyświetli komunikat w rodzaju Out of memory: Killed process 1234 (clickhouse-serv), a każdy dashboard Langfuse będzie zwracał błąd 500. Przy mniejszym obciążeniu ClickHouse odrzuci zapytanie i zapisze w logach DB::Exception: Memory limit (total) exceeded. Osiem GiB jest wartością akceptowalną dla jednego programisty wysyłającego kilka tysięcy śladów dziennie. Szesnaście GiB to wartość, którą należy przyjąć w planowaniu.

Wdrożenie Langfuse przy użyciu Docker Compose

Sklonuj repozytorium. Stos, powiązania oraz domyślne środowisko znajdują się w pliku docker-compose.yml.

git clone https://github.com/langfuse/langfuse.git
cd langfuse

Każda wartość wymagająca zmiany jest oznaczona w tym pliku jako # CHANGEME. Najpierw wygeneruj trzy sekrety aplikacji.

openssl rand -base64 32   # NEXTAUTH_SECRET
openssl rand -base64 32   # SALT
openssl rand -hex 32      # ENCRYPTION_KEY

Wartość ENCRYPTION_KEY musi mieć 256 bitów zapisanych jako 64 znaki szesnastkowe, co dokładnie generuje polecenie openssl rand -hex 32. Służy ona do szyfrowania wrażliwych danych w spoczynku, w tym kluczy dostawców LLM przechowywanych w instancji. Zmiana tej wartości po zapisaniu danych uniemożliwi ich odszyfrowanie, dlatego należy traktować ją jako stałą od pierwszego uruchomienia. Wartość SALT służy do haszowania kluczy API Langfuse, więc jej zmiana unieważni wszystkie klucze używane obecnie przez agentów.

Następnie ustaw POSTGRES_PASSWORD, CLICKHOUSE_PASSWORD, REDIS_AUTH oraz MINIO_ROOT_PASSWORD. Hasło MinIO występuje w czterech miejscach: raz jako MINIO_ROOT_PASSWORD, a następnie jako LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY, LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY oraz LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY. Pominięcie jednego z nich spowoduje, że MinIO odrzuci klienta z błędem SignatureDoesNotMatch, który pojawi się w dzienniku procesu worker, podczas gdy interfejs webowy będzie wyglądał na poprawnie działający. Przechowywanie tych wartości w pliku env zamiast w śledzonym pliku compose to wzorzec opisany w plikach env i sekretach Docker Compose.

Przypnij tagi obrazów przed uruchomieniem

Dostarczony plik używa tagów langfuse/langfuse:4 oraz langfuse/langfuse-worker:4. Te tagi ulegają zmianie. Langfuse automatycznie wykonuje migracje Postgres i ClickHouse podczas startu, więc rutynowe polecenie docker compose pull wykonane po kilku miesiącach może wywołać nieplanowaną migrację schematu bazy danych, której nie wykonano kopii zapasowej tego samego dnia. Przypnij obie wartości do konkretnego wydania w pliku docker-compose.override.yml, który Compose scali z dostarczonym plikiem, dzięki czemu późniejsze polecenie git pull nie nadpisze wprowadzonych zmian.

services:
  langfuse-web:
    image: docker.io/langfuse/langfuse:4.3.1
  langfuse-worker:
    image: docker.io/langfuse/langfuse-worker:4.3.1

Wersja 4.3.1 była aktualnym wydaniem 4.3 w sierpniu 2026 roku (wersja 4.4.0 została już wydana). Sprawdź stronę wydań projektu na GitHubie, przypnij wersję aktualną w dniu wdrożenia, a następnie aktualizuj ten numer w sposób kontrolowany. Obrazy pamięci masowej w dostarczonym pliku są już przypięte do wersji głównych, postgres:17, clickhouse-server:25.12 oraz redis:7, i wymagają takiego samego traktowania.

Uruchom stos.

docker compose up -d
docker compose ps
docker compose logs -f langfuse-worker

Pierwsze uruchomienie wykonuje migracje, więc odczekaj minutę lub dwie, zanim usługa zacznie odpowiadać. Polecenie docker compose ps powinno wyświetlić sześć usług w stanie running. Jeśli proces worker restartuje się w pętli, przyczyna znajduje się w jego dzienniku: CLICKHOUSE_MIGRATION_URL używa natywnego protokołu ClickHouse na porcie 9000, a nie portu HTTP 8123. Wskazanie portu 8123 spowoduje błąd, mimo że kontener webowy będzie wyglądał na sprawny.

Sprawdź stan zdrowia z poziomu serwera.

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

Zwykłe wywołanie /api/public/health potwierdza jedynie, że proces API działa, ponieważ celowo pomija bazę danych, aby usługa mogła działać podczas chwilowych problemów z Postgres. Wartość failIfDatabaseUnavailable=true to forma, którą należy monitorować; zwraca ona kod 503, gdy baza danych jest nieosiągalna. Wartość /api/public/ready zwraca kod 200, gdy migracje zostaną zakończone, a kontener będzie gotowy do przyjmowania ruchu. Oba to standardowe testy HTTP, więc strona statusu Uptime Kuma może je monitorować i powiadomić o awarii stosu, zanim dowiedzą się o tym agenci.

Wdrożenie TLS i zamknięcie zbędnych portów

Dostarczony plik compose publikuje 3000:3000 dla kontenera web oraz 9090:9000 dla MinIO. Oba wiążą się z każdym interfejsem sieciowym. Na publicznym adresie IP oznacza to, że każdy, kto przeskanuje port 3000, uzyska dostęp do strony rejestracji, a każdy skanujący port 9090 połączy się z zasobnikiem przechowującym surowe prompty.

Sama reguła firewalla nie wystarczy, aby je zamknąć. Docker zapisuje własne reguły DNAT w tablicy nat, które są przetwarzane, zanim reguły filtrujące ufw otrzymają pakiet, dlatego ufw deny 3000 pozostawia opublikowany port otwartym. Problem ten jest na tyle powszechny, że posiada własny przewodnik: dlaczego opublikowane porty Dockera omijają ufw. Zamiast tego należy powiązać porty z interfejsem loopback w pliku override.

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 musi być dokładnym adresem publicznym, włącznie ze schematem, ponieważ proces logowania buduje adres URL wywołania zwrotnego (callback) na podstawie tej wartości. Pozostawienie http://localhost:3000 za proxy HTTPS spowoduje, że proces logowania przekieruje przeglądarkę w miejsce, które jest nieosiągalne.

Teraz należy skierować reverse proxy na 127.0.0.1:3000 i powierzyć mu obsługę certyfikatu. Traefik w tym samym projekcie Compose jest standardowym wyborem, a etykiety routingu są opisane w uruchamianie kilku aplikacji za jednym reverse proxy Traefik. Caddy wykonuje to samo zadanie w dwóch liniach, jeśli Langfuse jest jedyną usługą na serwerze. Należy zweryfikować konfigurację za pomocą curl -sI https://langfuse.example.com/api/public/ready, a następnie potwierdzić z innej maszyny, że curl http://YOUR_IP:3000 zwraca teraz błąd przekroczenia czasu połączenia (timeout).

Jedna uwaga dotycząca MinIO. Langfuse serwuje załączone media do przeglądarki poprzez wstępnie podpisane adresy URL (presigned URLs) wskazujące na ten endpoint S3. Jeśli używane są ślady multimodalne zawierające obrazy lub dźwięk, MinIO ograniczone do interfejsu loopback spowoduje, że załączniki nie będą się ładować. Przed skonfigurowaniem proxy należy zapoznać się ze stroną konfiguracji magazynu obiektów (blob storage), ponieważ endpoint zapisany w wstępnie podpisanym adresie URL musi być zgodny z tym, który jest publikowany. Ślady w formacie zwykłego tekstu pozostają bez zmian.

Podczas pierwszej wizyty należy utworzyć konto, a następnie ograniczyć dostęp do instancji. Należy ustawić LANGFUSE_ALLOWED_ORGANIZATION_CREATORS na własny adres e-mail, aby osoba postronna, która trafi na stronę, nie mogła utworzyć organizacji na serwerze. Jeśli korzystasz już z Authentik jako własnego dostawcy tożsamości, Langfuse obsługuje standardowe połączenie OIDC, dzięki czemu konta są zarządzane centralnie wraz z pozostałymi aplikacjami, zamiast znajdować się na liście haseł znanej tylko temu serwerowi.

Wysyłanie pierwszego śladu

Utwórz projekt w interfejsie webowym i skopiuj klucze publiczny oraz prywatny z ustawień projektu. Python SDK odczytuje trzy zmienne środowiskowe.

export LANGFUSE_PUBLIC_KEY="pk-lf-..."
export LANGFUSE_SECRET_KEY="sk-lf-..."
export LANGFUSE_BASE_URL="https://langfuse.example.com"

LANGFUSE_BASE_URL to nazwa zmiennej w SDK w wersji 4, wydanej w marcu 2026. Starszy kod i starsze poradniki używają LANGFUSE_HOST. Jeśli ślady trafiają do Langfuse Cloud zamiast na własny serwer, przyczyną jest nieustawiony bazowy adres URL, ponieważ wartość domyślna wskazuje na instancję hostowaną.

pip install langfuse opentelemetry-instrumentation-anthropic anthropic
import 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()

Dekorator @observe otwiera obserwację wokół funkcji, przechwytuje jej argumenty oraz wartość zwracaną i zagnieżdża ją w ramach już aktywnej obserwacji. AnthropicInstrumentor to instrumentacja OpenTelemetry dla klienta Anthropic; zamienia ona każde wywołanie messages.create w generację zawierającą nazwę modelu, zużycie tokenów oraz opóźnienie, bez konieczności wprowadzania zmian w miejscu wywołania.

Dwa wywołania pozwalają na weryfikację poprawności działania. langfuse.auth_check() zwraca False w przypadku błędnych kluczy lub nieprawidłowego bazowego adresu URL, co pozwala uniknąć analizowania przyczyn pustego pulpitu nawigacyjnego. langfuse.flush() blokuje działanie do momentu wysłania zakolejkowanych zakresów (spans); jest to niezbędne w procesach krótkotrwałych, ponieważ SDK grupuje dane w tle, a skrypt kończący działanie natychmiastowo usuwa niewysłane pakiety danych.

Dlaczego ClickHouse stale zwiększa zajętość dysku?

Ślady (traces) to najszybciej rosnący rodzaj danych, z jakim spotykają się użytkownicy rozwiązań self-hosted. Każde uruchomienie agenta zapisuje jeden wiersz na krok, a dane wejściowe i wyjściowe są przechowywane w całości. W efekcie "rozgadany" agent z długimi promptami generuje znacznie więcej bajtów dziennie niż monitorowana przez niego aplikacja. Pozostawiony bez nadzoru ClickHouse zapełnia dysk, a pełny dysk powoduje zatrzymanie przyjmowania danych (ingestion), zamiast jedynie spowolnienia procesu.

Problem wynika z dwóch niezależnych czynników, które wymagają odrębnych rozwiązań.

Pierwszym są własne dane śledzenia, a rozwiązaniem jest ustawienie retencji. Otwórz ustawienia projektu w interfejsie webowym i określ okres retencji danych w dniach. Langfuse wymaga minimum 3 dni. Zadanie uruchamiane w nocy wyszukuje ślady, obserwacje, wyniki i zasoby multimedialne starsze niż wskazany okres, a następnie usuwa je z ClickHouse oraz z pamięci obiektowej (blob storage). Zadanie to wymaga uprawnień DeleteObject do zasobnika (bucket), które domyślne dane uwierzytelniające root dla MinIO w pliku compose już posiadają. Usunięcie jest trwałe, więc jeśli potrzebujesz długoterminowej historii, najpierw skonfiguruj eksport do pamięci obiektowej. Nie wprowadzaj ręcznie klauzul TTL dla tabel Langfuse: zadanie retencji zapewnia spójność między ClickHouse a zasobnikiem, natomiast ręczne ustawienie TTL usunie dane tylko z jednej strony.

Dobierz okres retencji do faktycznych potrzeb. Analiza kosztów i jakości odbywa się na danych sprzed kilku dni, a nie miesięcy. 30 dni to rozsądny punkt wyjścia dla małego zespołu, a 14 dni wystarczy, jeśli sprawdzasz ślady tylko w przypadku awarii.

Drugim czynnikiem są systemowe tabele logów ClickHouse. To zaskakuje użytkowników, ponieważ dysk nadal rośnie mimo skonfigurowania retencji. ClickHouse zapisuje trace_log, text_log, opentelemetry_span_log, metric_log oraz asynchronous_metric_log na potrzeby własnej diagnostyki. Tabele te nie mają domyślnego TTL, a Langfuse nigdy ich nie odczytuje. Najpierw sprawdź, co faktycznie zajmuje miejsce na dysku.

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
)

Uruchom to polecenie z flagą docker compose exec clickhouse clickhouse-client --password "$CLICKHOUSE_PASSWORD". Jeśli tabele systemowe znajdują się na szczycie listy, wyłącz je za pomocą nakładki konfiguracyjnej, ponieważ ClickHouse podczas startu scala każdy plik z /etc/clickhouse-server/config.d/ ze swoją główną konfiguracją.

<clickhouse>
    <trace_log remove="1"/>
    <text_log remove="1"/>
    <opentelemetry_span_log remove="1"/>
    <asynchronous_metric_log remove="1"/>
    <metric_log remove="1"/>
</clickhouse>

Zamontuj plik i zrestartuj ClickHouse.

services:
  clickhouse:
    volumes:
      - ./clickhouse-config.d/system-logs.xml:/etc/clickhouse-server/config.d/system-logs.xml:ro

To zatrzyma nowe zapisy. Wiersze znajdujące się już na dysku pozostaną, więc odzyskaj miejsce jawnie za pomocą DROP TABLE IF EXISTS system.trace_log oraz analogicznie dla każdej usuniętej tabeli. Jeśli wolisz zachować diagnostykę, alternatywą jest ustawienie agresywnego TTL dla każdej tabeli zamiast remove="1", co zostało opisane w dokumentacji skalowania Langfuse.

Warto również zwrócić uwagę na jeszcze jedną tabelę. blob_storage_file_log śledzi pliki zdarzeń przesłane do zasobnika. Jeśli ustawisz politykę cyklu życia (lifecycle policy) dla zasobnika, nadaj tej tabeli pasujący TTL, aby oba źródła danych pozostały spójne.

ALTER TABLE blob_storage_file_log MODIFY TTL created_at + INTERVAL 30 DAY DELETE;

Ustaw również zwykły alert df -h na dysku z danymi. Ślady nie rosną w sposób liniowy. Ich przyrost następuje w dniu wdrożenia nowego agenta i to nie powinno być pierwszym sygnałem, że przyjmowanie danych przestało działać.

Tworzenie kopii zapasowych Postgres i ClickHouse

Kopia zapasowa Langfuse składa się z trzech części. Postgres przechowuje użytkowników, organizacje, projekty oraz klucze API. ClickHouse przechowuje ślady (traces). MinIO przechowuje surowe zdarzenia. Przywrócenie tylko bazy Postgres pozwala na zalogowanie się, ale bez historii. Przywrócenie tylko bazy ClickHouse daje dostęp do historii, do której nikt nie może się zalogować.

Postgres jest zwykłym pg_dump, co jest zalecane w dokumentacji kopii zapasowych Langfuse.

docker compose exec -T postgres pg_dump -U postgres postgres \
  | gzip > langfuse-pg-$(date +%F).sql.gz

ClickHouse wymaga większej uwagi, ponieważ katalog danych skopiowany w trakcie trwania operacji scalania (merges) nie stanowi spójnej kopii zapasowej. Najprostszym podejściem na pojedynczej maszynie jest zatrzymanie kontenera i zarchiwizowanie wolumenu.

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

Należy użyć nazwy wolumenu wyświetlanej przez docker volume ls, a nie tej zapisanej w pliku YAML. Plik deklaruje langfuse_clickhouse_data, a Compose dodaje do niej prefiks z nazwą projektu, więc klonowanie w katalogu o nazwie langfuse tworzy langfuse_langfuse_clickhouse_data. Błąd w tym miejscu sprawi, że docker run utworzy nowy, pusty wolumen bez zgłaszania błędów, a archiwum będzie puste.

Kontener web zapisuje każde przychodzące zdarzenie do bucketa, zanim worker je przetworzy, więc krótkie zatrzymanie ClickHouse oznacza zazwyczaj, że worker ponowi próbę później. Operację należy wykonać w godzinach o niskim natężeniu ruchu i ograniczyć czas jej trwania. W przypadku bardziej obciążonych instancji, instrukcja BACKUP DATABASE default TO S3(...) wbudowana w ClickHouse pozwala na wykonanie spójnej kopii zapasowej bez zatrzymywania serwera. MinIO jest trzecim elementem, a mc mirror lub replikacja MinIO do zewnętrznego bucketa zapewnia jego ochronę. Niezależnie od metody, kopię należy przenieść poza serwer, do czego służą szyfrowane kopie zapasowe restic na VPS.

Redis nie wymaga kopii zapasowej. Przechowuje on kolejkę i pamięć podręczną, więc jego utrata skutkuje jedynie utratą zdarzeń aktualnie przetwarzanych, bez wpływu na starsze dane.

Ostrzeżenie dotyczące spójności jest istotne i należy je jasno sformułować. Postgres i ClickHouse są zrzucane w różnych momentach, więc przywrócenie danych może pozostawić wiersz projektu bez powiązanych śladów lub ślady należące do projektu, który już nie istnieje. Langfuse toleruje takie sytuacje, jednak zrzuty obu baz należy wykonywać w krótkim odstępie czasu i w oknie o niskim natężeniu ruchu. Bucket ze zdarzeniami stanowi właściwą siatkę bezpieczeństwa, ponieważ Langfuse utrwala w nim każde przychodzące zdarzenie przed jego przetworzeniem.

Należy przynajmniej raz przeprowadzić przywracanie danych w środowisku testowym. Pozwala to na wykrycie błędnej nazwy wolumenu teraz, a nie w trakcie awarii.

Na co zwrócić uwagę w pierwszej kolejności

Cztery elementy zasługują na uwagę w pierwszym tygodniu.

  • Koszt pojedynczego śladu (trace). Langfuse oblicza koszt na podstawie nazwy modelu i zużycia tokenów, dlatego warto posortować ślady według kosztu i przeanalizować najbardziej kosztowny od początku do końca. Przyczyną jest zazwyczaj rozrośnięty prompt: cały dokument wklejony do kontekstu lub historia konwersacji, która nie jest przycinana. Gdy już to widać, kontrolowanie kosztów agenta AI staje się zadaniem inżynieryjnym, a nie zgadywaniem.
  • Podział zużycia tokenów na wejściowe i wyjściowe. Tokeny wejściowe są liczne i tanie, wyjściowe są nieliczne i drogie, a buforowane dane wejściowe są jeszcze tańsze. Ten sam sposób rozliczania został wyjaśniony w sposobie zliczania tokenów w Claude Code i ma zastosowanie do każdego agenta stworzonego samodzielnie.
  • Percentyle opóźnień. Mediana ukrywa problem. Wartości p95 i p99 to miejsca, w których występują przekroczenia limitów czasu (timeouts), a w pętli agenta wolne wywołanie narzędzia przy p95 jest mnożone przez liczbę iteracji.
  • Nieudane wywołania narzędzi. Przefiltruj obserwacje według poziomu ERROR. Narzędzie, które zawodzi w 5% przypadków, jest niewidoczne w zagregowanym wskaźniku sukcesu, ale bardzo widoczne w śladach, gdzie można zaobserwować, jak model ponawia próbę, a następnie zużywa tokeny na obejście problemu.

Ustaw okres retencji i wybierz pulpit nawigacyjny, który będziesz sprawdzać co tydzień, w tym samym dniu, w którym wdrażasz zmiany. Narzędzie do obserwowalności, którego nikt nie otwiera, to tylko baza danych zapełniająca dysk.

FAQ

Ile pamięci RAM wymaga samodzielnie hostowany Langfuse?

Należy zaplanować 4 rdzenie CPU oraz 16 GiB pamięci RAM, zgodnie z zaleceniami przewodnika Langfuse Docker Compose dla pojedynczej maszyny wirtualnej, oraz około 100 GiB przestrzeni dyskowej. Opublikowane minima dla komponentów to 8 GiB dla ClickHouse oraz 4 GiB odpowiednio dla kontenerów web i worker; dodatkowej pamięci wymagają również Postgres, Redis oraz MinIO. Osiem GiB wystarcza do uruchomienia instancji deweloperskiej. Dwa GiB są niewystarczające: proces ClickHouse jest przerywany przez jądro systemu podczas scalania danych w tle, co obrazuje dmesg oraz Out of memory: Killed process.

Dlaczego dysk ClickHouse zapełnia się mimo ustawienia retencji danych?

Ustawienie retencji dotyczy wyłącznie danych Langfuse. ClickHouse zapisuje niezależnie tabele diagnostyczne trace_log, text_log, opentelemetry_span_log, metric_log oraz asynchronous_metric_log, które nie posiadają domyślnego TTL. Należy wykonać zapytanie system.parts pogrupowane według tabeli, aby zidentyfikować największą z nich, a następnie wyłączyć nieużywane tabele za pomocą wpisu remove="1" w pliku znajdującym się w /etc/clickhouse-server/config.d/. Po restarcie ClickHouse należy usunąć istniejące tabele, aby odzyskać zajęte miejsce.

Jaki jest minimalny okres retencji danych w Langfuse?

Trzy dni. Retencję konfiguruje się dla każdego projektu w ustawieniach projektu lub poprzez API projektów. Zadanie uruchamiane każdej nocy usuwa ślady (traces), obserwacje, wyniki (scores) oraz zasoby multimedialne starsze niż zdefiniowany okres zarówno z ClickHouse, jak i z pamięci obiektowej (blob storage). Usunięcia nie można cofnąć, dlatego w przypadku potrzeby zachowania historii wykraczającej poza ten okres, należy najpierw skonfigurować eksport do pamięci obiektowej.

Czy muszę tworzyć kopie zapasowe zarówno Postgres, jak i ClickHouse?

Tak, ponieważ przechowują one różne dane. Postgres zawiera informacje o użytkownikach, organizacjach, projektach oraz klucze API, natomiast ClickHouse przechowuje dane o śladach (trace data). Przywrócenie wyłącznie bazy Postgres skutkuje instancją, do której można się zalogować, ale która jest pusta. Należy również tworzyć kopie zapasowe bucketu MinIO, ponieważ przechowuje on surowe zdarzenia zapisywane przez Langfuse w momencie ich nadejścia, co stanowi najbardziej wiarygodne źródło danych w całym stosie technologicznym.

Czy mogę skierować istniejącą konfigurację OpenTelemetry na samodzielnie hostowany Langfuse?

Tak. Langfuse w wersji v4 oraz odpowiadające jej SDK bazują na OpenTelemetry, a instrumentacje OTel dla Anthropic i OpenAI eksportują dane bezpośrednio do tego systemu. W języku Python należy wykonać pip install langfuse opentelemetry-instrumentation-anthropic, wywołać AnthropicInstrumentor().instrument() jednokrotnie podczas uruchamiania oraz ustawić LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY i LANGFUSE_BASE_URL na własny host. Przed rozpoczęciem poszukiwań brakującego dashboardu należy zweryfikować poprawność konfiguracji za pomocą langfuse.auth_check().