Langfuse کو اپنے VPS پر self-host کرنے کا طریقہ
اپنے VPS پر Langfuse چلائیں: کم از کم resources، pinned image tags، TLS، disk بھرنے سے پہلے ClickHouse retention، اور قابلِ اعتماد backups کی عملی وضاحت۔
AI agent کی tracing کیوں کریں
آپ Langfuse کو self-host کرتے ہیں تاکہ معلوم ہو سکے کہ آپ کے agent نے کسی run میں حقیقتاً کیا کیا۔ Langfuse ایک open source LLM (large language model) observability tool ہے۔ یہ ہر prompt، ہر model response، ہر tool call اور ہر token ریکارڈ کرتا ہے، پھر انہیں ایک trace کے تحت گروپ کرتا ہے جسے آپ کھول کر پڑھ سکتے ہیں۔ اسے اپنے VPS پر چلانے سے یہ prompts کبھی بھی آپ کے زیرِ انتظام server سے باہر نہیں جاتے۔
اس کی ضرورت کی وجہ واضح ہے۔ جس cost problem یا quality problem کو آپ دیکھ نہیں سکتے، اسے حل نہیں کر سکتے۔ Provider invoice سے صرف یہ معلوم ہوتا ہے کہ Tuesday کی لاگت Monday کی لاگت سے چار گنا تھی۔ Trace بتاتا ہے کہ یہ کس agent run کی وجہ سے ہوا، کون سا prompt 40,000 tokens تک بڑھا، اور کون سا retry loop ناکام ہونے سے پہلے نو بار چلا۔ Invoice آپ کو number دیتا ہے۔ Trace آپ کو وہ code دکھاتا ہے جس نے یہ نتیجہ پیدا کیا۔
اس guide میں تین اصطلاحات استعمال ہوں گی۔ trace آپ کے agent کا ایک end to end run ہے۔ observation اس run کے اندر ایک step ہے: عام code کے لیے ایک span، اور model کو call کرنے کے لیے ایک generation۔ score کسی trace کے ساتھ منسلک number ہے، جو human review یا automated evaluator سے حاصل ہوتا ہے۔ Langfuse OpenTelemetry (OTel) استعمال کرتا ہے، جو distributed tracing کے لیے vendor neutral standard ہے، اس لیے آپ کی موجودہ instrumentation اسے target کر سکتی ہے۔
Langfuse کی self-hosting میں اصل میں کیا چلتا ہے
Langfuse v4 صرف ایک container نہیں ہے۔ یہ دو application containers اور چار storage services پر مشتمل ہے، اور single VPS پر یہ تمام چھ اجزا آپ کے سرور پر چلتے ہیں۔
langfuse-webweb interface اور ingestion API فراہم کرتا ہے۔langfuse-workerپس منظر میں queue خالی کرتا ہے۔ یہ ingestion batches کو parse کرتا ہے، لاگت کا حساب لگاتا ہے، اور nightly retention job چلاتا ہے۔- Postgres transactional data محفوظ کرتا ہے، جس میں users، organisations، projects، API keys اور prompts شامل ہیں۔
- ClickHouse خود trace data محفوظ کرتا ہے، یعنی observations اور scores۔ یہ analytical queries کے لیے بنایا گیا column store ہے، اسی لیے سو ملین rows سے زیادہ کے dashboard کا جواب بھی تیزی سے ملتا ہے۔
- Redis وہ queue اور cache ہے جو web اور worker کے درمیان کام کرتا ہے۔
- MinIO سرور پر S3 compatible object storage فراہم کرتا ہے۔ یہ ہر raw incoming event کے علاوہ attach کی جانے والی media بھی محفوظ کرتا ہے۔
Langfuse ان تین components کے لیے minimum resources شائع کرتا ہے جو اصل processing کرتے ہیں۔
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 memory درکار ہوتی ہے۔ Web container اور worker کو ہر ایک کے لیے 4 GiB memory درکار ہوتی ہے۔ یہ ان 3 components کے لیے شائع کردہ کم از کم مقداریں ہیں جن کے resources Langfuse بتاتا ہے، جبکہ Postgres، Redis اور MinIO کو بھی اضافی memory درکار ہوتی ہے۔ Project کی اپنی Docker Compose guide ایسی machine تجویز کرتی ہے جس میں 4 cores، 16 GiB memory اور تقریباً 100 GiB storage ہو۔ یہ تجویز بھی اسی حساب سے مطابقت رکھتی ہے، اس میں اضافی گنجائش شامل نہیں کی گئی۔
اسے 2 GiB plan پر چلانے کی کوشش نہ کریں۔ ClickHouse start ہو جاتا ہے اور کچھ وقت تک writes قبول کرتا ہے، پھر background merge کے دوران بند ہو جاتا ہے، کیونکہ merge table کے بڑے parts کو memory میں load کرتا ہے۔ آپ docker compose ps میں clickhouse container کی حالت restarting دیکھیں گے، dmesg میں Out of memory: Killed process 1234 (clickhouse-serv) جیسی line ہوگی، اور ہر Langfuse dashboard 500 واپس کرے گا۔ کم دباؤ میں ClickHouse اس کے بجائے query مسترد کر دیتا ہے اور DB::Exception: Memory limit (total) exceeded log کرتا ہے۔ ایک developer کے روزانہ چند ہزار traces بھیجنے کے لیے 8 GiB قابلِ استعمال ہے۔ منصوبہ بندی کے لیے 16 GiB کو بنیاد بنائیں۔
Docker Compose کے ساتھ Langfuse تعینات کریں
repository کو clone کریں۔ stack، اس کی wiring اور default environment سب اس کی docker-compose.yml میں موجود ہیں۔
git clone https://github.com/langfuse/langfuse.git
cd langfuseاس file میں تبدیل کی جانے والی ہر value کو # CHANGEME سے نشان زد کیا گیا ہے۔ پہلے application secrets کے تین values generate کریں۔
openssl rand -base64 32 # NEXTAUTH_SECRET
openssl rand -base64 32 # SALT
openssl rand -hex 32 # ENCRYPTION_KEYENCRYPTION_KEY کی value 256 bits ہونی چاہیے، جسے 64 hex characters کی صورت میں لکھا جاتا ہے۔ openssl rand -hex 32 بالکل یہی output دیتا ہے۔ یہ rest پر موجود حساس values کو encrypt کرتا ہے، جن میں instance میں محفوظ کی گئی LLM provider keys بھی شامل ہیں۔ Data موجود ہونے کے بعد اسے تبدیل کرنے سے وہ rows دوبارہ decrypt نہیں ہو سکتیں۔ اس لیے پہلے boot سے ہی اسے مستقل value سمجھیں۔ SALT آپ کی Langfuse API keys کو hash کرنے کے لیے استعمال ہوتا ہے۔ اسے تبدیل کرنے سے آپ کے agents کی استعمال کردہ تمام موجودہ keys invalid ہو جاتی ہیں۔
اس کے بعد POSTGRES_PASSWORD، CLICKHOUSE_PASSWORD، REDIS_AUTH اور MINIO_ROOT_PASSWORD set کریں۔ MinIO password چار جگہوں پر ظاہر ہوتا ہے: پہلی بار MINIO_ROOT_PASSWORD کے طور پر، پھر LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY، LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY اور LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY کے طور پر۔ ان میں سے ایک value بھی رہ جائے تو MinIO اس client کو SignatureDoesNotMatch کے ساتھ reject کر دیتا ہے۔ یہ error worker log میں درج ہوتی ہے، جبکہ web interface بظاہر درست رہتا ہے۔ ان values کو tracked compose file میں رکھنے کے بجائے env file میں رکھنا وہی طریقہ ہے جس کا احاطہ Docker Compose env files اور secrets میں کیا گیا ہے۔
شروع کرنے سے پہلے image tags pin کریں
فراہم کردہ file میں langfuse/langfuse:4 اور langfuse/langfuse-worker:4 استعمال ہوتے ہیں۔ یہ tags تبدیل ہوتے رہتے ہیں۔ Langfuse start کے وقت اپنے Postgres اور ClickHouse migrations خودکار طور پر چلاتا ہے۔ اس لیے چند ماہ بعد کیا جانے والا معمول کا docker compose pull اس database پر غیر منصوبہ بند schema migration بن سکتا ہے، جس کا آپ نے اسی صبح backup نہیں لیا تھا۔ دونوں کو ایک docker-compose.override.yml میں ایک ہی release پر pin کریں۔ Compose اسے فراہم کردہ file کے اوپر merge کرتا ہے، اس لیے بعد کا git pull آپ کی edits سے متصادم نہیں ہوگا۔
services:
langfuse-web:
image: docker.io/langfuse/langfuse:4.3.1
langfuse-worker:
image: docker.io/langfuse/langfuse-worker:4.3.1August 2026 تک version 4.3.1 موجودہ 4.3 release تھا، جبکہ 4.4.0 اس کے بعد جاری ہو چکا ہے۔ project کے GitHub releases page کو دیکھیں، deployment کے دن جو version موجودہ ہو اسے pin کریں، پھر اس number کو جان بوجھ کر تبدیل کریں۔ فراہم کردہ file میں storage images پہلے ہی major versions، postgres:17، clickhouse-server:25.12 اور redis:7 پر pinned ہیں، اور ان کے ساتھ بھی یہی طریقہ اختیار کرنا چاہیے۔
اب stack شروع کریں۔
docker compose up -d
docker compose ps
docker compose logs -f langfuse-workerپہلا boot migrations چلاتا ہے، اس لیے کسی بھی response سے پہلے ایک یا دو منٹ انتظار کریں۔ docker compose ps کو state running میں چھ services دکھانی چاہییں۔ اگر worker مسلسل restart ہوتا رہے تو اس کی log وجہ بتائے گی: CLICKHOUSE_MIGRATION_URL ClickHouse native protocol کو port 9000 پر استعمال کرتا ہے، HTTP port 8123 پر نہیں۔ اسے port 8123 کی طرف point کرنے سے worker fail ہو جاتا ہے، جبکہ web container بظاہر درست رہتا ہے۔
خود اسی server سے health check کریں۔
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 call صرف یہ ثابت کرتی ہے کہ API process چل رہا ہے، کیونکہ یہ جان بوجھ کر database کو check نہیں کرتی۔ اس طرح Postgres عارضی طور پر unavailable ہونے کے باوجود service requests فراہم کرتی رہتی ہے۔ failIfDatabaseUnavailable=true form وہ ہے جس کی نگرانی کے لیے monitor کو point کرنا چاہیے۔ Database تک رسائی نہ ہونے پر یہ 503 واپس کرتی ہے۔ migrations مکمل ہونے کے بعد /api/public/ready، 200 واپس کرتا ہے اور container traffic قبول کرنے کے لیے تیار ہوتا ہے۔ دونوں عام HTTP checks ہیں، اس لیے Uptime Kuma status page انہیں monitor کر کے آپ کے agents سے پہلے بتا سکتی ہے کہ stack down ہے۔
TLS کو سامنے رکھیں اور اضافی ports بند کریں
فراہم کردہ compose file web container کے لیے 3000:3000 اور MinIO کے لیے 9090:9000 شائع کرتی ہے۔ دونوں ہر interface پر bind ہوتے ہیں۔ Public IP پر اس کا مطلب ہے کہ port 3000 scan کرنے والا ہر شخص آپ کے sign up page تک پہنچ سکتا ہے، اور port 9090 scan کرنے والا ہر شخص اس bucket سے رابطہ کر سکتا ہے جس میں آپ کے raw prompts موجود ہیں۔
صرف firewall rule سے یہ ports بند نہیں ہوتے۔ Docker خود nat table میں DNAT rules لکھتا ہے، اور یہ rules ufw کے filter rules تک packet پہنچنے سے پہلے ہی لاگو ہو جاتے ہیں، اس لیے ufw deny 3000 کے بعد بھی شائع شدہ port کھلا رہتا ہے۔ یہ مسئلہ اتنے لوگوں کو پیش آتا ہے کہ اس کے لیے الگ guide موجود ہے: Docker کے شائع شدہ ports ufw کو bypass کیوں کرتے ہیں۔ اس کے بجائے اپنی override file میں loopback پر bind کریں۔
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 میں scheme سمیت عین public address ہونا چاہیے، کیونکہ login flow اسی value سے callback URL بناتا ہے۔ اگر HTTPS proxy کے پیچھے اسے http://localhost:3000 رہنے دیں تو sign in کا round trip browser کو ایسی جگہ بھیج دے گا جہاں وہ پہنچ نہیں سکتا۔
اب reverse proxy کو 127.0.0.1:3000 کی طرف point کریں اور certificate اسی کے پاس رہنے دیں۔ اسی Compose project میں Traefik عام انتخاب ہے، اور routing labels کی وضاحت ایک Traefik reverse proxy کے پیچھے متعدد ایپس چلانا میں موجود ہے۔ اگر server پر صرف Langfuse ہے تو Caddy یہی کام دو lines میں کر دیتا ہے۔ curl -sI https://langfuse.example.com/api/public/ready سے تصدیق کریں، پھر دوسرے machine سے بھی تصدیق کریں کہ curl http://YOUR_IP:3000 اب timeout ہو جاتا ہے۔
MinIO کے بارے میں ایک اہم بات ہے۔ Langfuse attached media کو presigned URLs کے ذریعے آپ کے browser تک پہنچاتا ہے، اور یہ URLs اسی S3 endpoint کی طرف point کرتے ہیں۔ اس لیے اگر آپ images یا audio والے multi-modal traces استعمال کرتے ہیں تو صرف loopback پر چلنے والا MinIO ان attachments کو load نہیں ہونے دے گا۔ اسے proxy کرنے سے پہلے blob storage configuration page پڑھیں، کیونکہ presigned URL میں لکھا endpoint اس address سے مطابقت رکھنا چاہیے جسے آپ public کرتے ہیں۔ Plain text traces متاثر نہیں ہوتے۔
پہلی visit پر اپنا account بنائیں، پھر instance کا کنٹرول اپنے پاس رکھیں۔ LANGFUSE_ALLOWED_ORGANIZATION_CREATORS میں اپنا email address مقرر کریں، تاکہ page تک پہنچنے والا کوئی اجنبی آپ کے server پر organisation نہ بنا سکے۔ اگر آپ پہلے ہی اپنے identity provider کے طور پر Authentik چلا رہے ہیں تو Langfuse standard OIDC connection استعمال کرتا ہے۔ اس طرح accounts آپ کی باقی apps کے ساتھ بنائے اور ختم کیے جاتے ہیں، بجائے اس کے کہ وہ صرف اسی box کو معلوم password list میں موجود رہیں۔
اپنا پہلا trace بھیجیں
Web interface میں ایک project بنائیں اور project settings سے اس کی public اور secret keys copy کریں۔ Python SDK تین environment variables پڑھتا ہے۔
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 میں variable name ہے، جو March 2026 میں release ہوا تھا۔ پرانا code اور پرانی guides LANGFUSE_HOST استعمال کرتی ہیں۔ اگر آپ کے traces آپ کے server کے بجائے Langfuse Cloud میں جا رہے ہیں تو اس کی وجہ unset base URL ہے، کیونکہ default 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 decorator function کے گرد ایک observation کھولتا ہے، اس کے arguments اور return value capture کرتا ہے، اور اسے پہلے سے active observation کے اندر nest کرتا ہے۔ AnthropicInstrumentor، Anthropic client کے لیے OpenTelemetry instrumentation ہے۔ یہ ہر messages.create call کو ایک generation میں تبدیل کرتا ہے، جس میں model name، token usage اور latency شامل ہوتے ہیں، جبکہ call site میں کوئی تبدیلی نہیں کرنی پڑتی۔
دو calls آپ کے لیے checking انجام دیتی ہیں۔ langfuse.auth_check() غلط keys یا غلط base URL کی صورت میں False return کرتا ہے۔ یہ dashboard خالی ہونے کی وجہ تلاش کرنے سے زیادہ تیز ہے۔ langfuse.flush() queued spans کے بھیجے جانے تک انتظار کرتا ہے۔ کم مدت تک چلنے والے processes کے لیے یہ ضروری ہے، کیونکہ SDK پس منظر میں batching کرتا ہے اور فوراً exit ہونے والا script اپنے unsent batch کو بھی ساتھ ختم کر دیتا ہے۔
ClickHouse کیوں مسلسل بڑھتا رہتا ہے؟
Traces وہ data ہیں جو زیادہ تر لوگ self-host کرتے وقت سب سے تیزی سے بڑھتے ہوئے دیکھتے ہیں۔ ہر agent run ہر step کے لیے ایک row لکھتا ہے، اور inputs اور outputs مکمل طور پر محفوظ کیے جاتے ہیں۔ اس لیے طویل prompts والا زیادہ باتونی agent روزانہ اس application سے کہیں زیادہ bytes پیدا کرتا ہے جس کی وہ نگرانی کر رہا ہو۔ اگر اسے یونہی چھوڑ دیا جائے تو ClickHouse disk بھر دیتا ہے، اور بھری ہوئی disk ingestion کو سست نہیں کرتی بلکہ روک دیتی ہے۔
یہاں دو الگ چیزیں بڑھتی ہیں، اور ان کے لیے دو الگ اصلاحات درکار ہیں۔
پہلی چیز آپ کا اپنا trace data ہے، اور اس کا حل retention setting ہے۔ web interface میں project settings کھولیں اور دنوں میں data retention period مقرر کریں۔ Langfuse کم از کم 3 دن قبول کرتا ہے۔ اس کے بعد nightly job مقررہ مدت سے پرانے traces، observations، scores اور media assets منتخب کرتی ہے اور انہیں ClickHouse اور blob storage دونوں سے حذف کر دیتی ہے۔ اس job کو bucket پر DeleteObject permission درکار ہوتی ہے، جو default compose file میں موجود MinIO root credentials کے پاس پہلے ہی ہوتی ہے۔ حذف مستقل ہوتا ہے، اس لیے اگر آپ کو طویل مدتی history درکار ہو تو پہلے blob storage export configure کریں۔ Langfuse کی اپنی tables پر TTL clauses خود نہ لکھیں۔ retention job ہی ClickHouse اور bucket کو ہم آہنگ رکھتی ہے، جبکہ manual TTL صرف ایک طرف سے data حذف کرتا ہے۔
مدت کا انتخاب اس data کے مطابق کریں جسے آپ حقیقت میں استعمال کرتے ہیں۔ Cost اور quality review مہینوں پرانے data کے بجائے چند دن پرانے data پر ہوتی ہے۔ چھوٹی team کے لیے 30 دن ایک معقول آغاز ہے، اور اگر آپ صرف کسی خرابی کے وقت trace کھولتے ہیں تو 14 دن کافی ہیں۔
دوسری چیز ClickHouse کی اپنی system log tables ہیں۔ یہ بات لوگوں کو حیران کرتی ہے، کیونکہ retention configure کرنے کے بعد بھی disk بڑھتی رہتی ہے۔ ClickHouse اپنی diagnostics کے لیے trace_log، text_log، opentelemetry_span_log، metric_log اور asynchronous_metric_log لکھتا ہے۔ یہ tables بغیر TTL کے آتی ہیں، اور Langfuse انہیں کبھی نہیں پڑھتا۔ پہلے معلوم کریں کہ disk دراصل کہاں استعمال ہوئی ہے۔
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" کے ساتھ چلائیں۔ اگر system tables فہرست کے اوپر نظر آئیں تو config overlay کے ذریعے انہیں بند کریں، کیونکہ ClickHouse start کے وقت /etc/clickhouse-server/config.d/ میں موجود ہر file کو اپنی main config پر merge کرتا ہے۔
<clickhouse>
<trace_log remove="1"/>
<text_log remove="1"/>
<opentelemetry_span_log remove="1"/>
<asynchronous_metric_log remove="1"/>
<metric_log remove="1"/>
</clickhouse>اسے mount کریں اور ClickHouse restart کریں۔
services:
clickhouse:
volumes:
- ./clickhouse-config.d/system-logs.xml:/etc/clickhouse-server/config.d/system-logs.xml:roاس سے نئی writes رک جائیں گی۔ Disk پر پہلے سے موجود rows برقرار رہیں گی، اس لیے DROP TABLE IF EXISTS system.trace_log کے ذریعے جگہ واضح طور پر خالی کریں، اور حذف کی گئی ہر table کے لیے یہی عمل کریں۔ اگر آپ diagnostics برقرار رکھنا چاہتے ہیں تو remove="1" کے بجائے ہر table پر aggressive TTL لگانا متبادل طریقہ ہے۔ Langfuse کی scaling docs میں اس کا طریقہ درج ہے۔
ایک اور table کے بارے میں جاننا مفید ہے۔ blob_storage_file_log آپ کے bucket میں upload کی گئی event files کو track کرتی ہے۔ اگر آپ bucket پر lifecycle policy بھی set کرتے ہیں تو table کے لیے matching TTL مقرر کریں، تاکہ دونوں میں فرق نہ آئے۔
ALTER TABLE blob_storage_file_log MODIFY TTL created_at + INTERVAL 30 DAY DELETE;data disk پر سادہ df -h alert بھی لگائیں۔ Traces ہموار رفتار سے نہیں بڑھتے۔ جس دن آپ نیا agent ship کرتے ہیں، اسی دن ان میں تیزی سے اضافہ ہو سکتا ہے۔ اس کی پہلی علامت ingestion کا fail ہونا نہیں ہونی چاہیے۔
Postgres اور ClickHouse کا بیک اپ لیں
Langfuse کے بیک اپ کے تین حصے ہیں۔ Postgres میں آپ کے users، organisations، projects اور API keys محفوظ ہوتے ہیں۔ ClickHouse میں traces محفوظ ہوتے ہیں۔ MinIO میں raw events محفوظ ہوتے ہیں۔ صرف Postgres بحال کرنے سے login کام کرے گا، لیکن کوئی history موجود نہیں ہوگی۔ صرف ClickHouse بحال کرنے سے history تو مل جائے گی، لیکن اسے دیکھنے کے لیے کوئی login نہیں کر سکے گا۔
Postgres ایک سادہ pg_dump ہے، اور Langfuse کی backup دستاویزات بھی اسی طریقے کی تجویز کرتی ہیں۔
docker compose exec -T postgres pg_dump -U postgres postgres \
| gzip > langfuse-pg-$(date +%F).sql.gzClickHouse کے لیے زیادہ احتیاط درکار ہے، کیونکہ merges کے دوران live data directory کی نقل ایک consistent backup نہیں ہوتی۔ ایک ہی box پر آسان طریقہ یہ ہے کہ container روکیں اور volume کو archive کریں۔
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 name استعمال کریں جو docker volume ls دکھاتا ہے، نہ کہ وہ نام جو YAML میں لکھا ہے۔ file میں langfuse_clickhouse_data درج ہے، اور Compose اس کے ساتھ project name کا prefix لگاتا ہے۔ اس لیے langfuse نام کی directory میں clone کرنے سے langfuse_langfuse_clickhouse_data بنتا ہے۔ اگر یہ نام غلط ہو تو docker run بغیر کسی error کے نیا خالی volume بنا دیتا ہے، اور آپ کے archive میں کچھ بھی شامل نہیں ہوتا۔
web container ہر incoming event کو worker کے process کرنے سے پہلے bucket میں لکھتا ہے، اس لیے ClickHouse کو مختصر وقت کے لیے روکنے کا زیادہ تر مطلب یہ ہوتا ہے کہ worker بعد میں دوبارہ کوشش کرے گا۔ یہ کام کم استعمال کے وقت کریں اور اسے مختصر رکھیں۔ زیادہ مصروف instance کے لیے ClickHouse کا اپنا BACKUP DATABASE default TO S3(...) statement server روکے بغیر consistent backup لکھتا ہے۔ MinIO تیسرا حصہ ہے، اور mc mirror یا MinIO replication کے ذریعے off-box bucket استعمال کرنے سے اس کا بیک اپ بھی ہو جاتا ہے۔ آپ جو بھی backup بنائیں، اسے server سے باہر منتقل کریں۔ اسی مقصد کے لیے VPS پر encrypted restic backups استعمال ہوتے ہیں۔
Redis کے لیے backup درکار نہیں۔ اس میں queue اور cache ہوتے ہیں، اس لیے اسے کھونے سے صرف وہ events ضائع ہوتے ہیں جو اس وقت process ہونے کے مرحلے میں ہوں؛ پرانے events متاثر نہیں ہوتے۔
Consistency سے متعلق یہ احتیاط حقیقی ہے اور اسے واضح طور پر بیان کرنا ضروری ہے۔ Postgres اور ClickHouse کے dumps مختلف اوقات میں لیے جاتے ہیں، اس لیے restore کے بعد کسی project کی row موجود ہو سکتی ہے لیکن اس کے traces نہ ہوں، یا ایسے traces موجود ہو سکتے ہیں جن کا project اب باقی نہ ہو۔ Langfuse اس صورت حال کو برداشت کر لیتا ہے، لیکن دونوں dumps قریب قریب ایک ہی وقت میں اور کم traffic کے دوران لیں۔ Event bucket اصل safety net ہے، کیونکہ Langfuse ہر incoming event کو process کرنے سے پہلے وہاں محفوظ کرتا ہے۔
کم از کم ایک بار scratch stack میں restore کریں۔ اس طرح غلط volume name کا مسئلہ outage کے دوران نہیں، بلکہ پہلے ہی معلوم ہو جاتا ہے۔
پہلے کیا دیکھیں
پہلے ہفتے میں چار چیزیں لازماً شامل کریں۔
- ہر trace کی لاگت۔ Langfuse model name اور token usage کی بنیاد پر لاگت کا حساب لگاتا ہے، اس لیے traces کو لاگت کے لحاظ سے sort کریں اور سب سے مہنگی trace کو ابتدا سے آخر تک پڑھیں۔ عموماً وجہ ایسا prompt ہوتا ہے جو بڑھ گیا ہو: پورا document context میں paste کیا گیا ہو، یا conversation history کو کوئی trim نہ کرتا ہو۔ جب یہ نظر آنے لگے تو AI agent کی لاگت کو کنٹرول کرنا اندازے کے بجائے engineering task بن جاتا ہے۔
- Input اور output کے لحاظ سے token usage کی تقسیم۔ Input tokens زیادہ اور سستے ہوتے ہیں، output tokens کم اور مہنگے ہوتے ہیں، جبکہ cached input اس سے بھی سستا ہوتا ہے۔ یہی accounting Claude Code کے token usage کا حساب کیسے کیا جاتا ہے میں تفصیل سے بیان کی گئی ہے، اور یہ آپ کے خود لکھے ہوئے کسی بھی agent پر لاگو ہوتی ہے۔
- Latency percentiles۔ Median مسئلہ چھپا دیتا ہے۔ p95 اور p99 پر timeouts ظاہر ہوتے ہیں، اور agent loop کے اندر p95 پر ایک سست tool call iterations کی تعداد کے ساتھ کئی گنا اثر انداز ہوتا ہے۔
- ناکام tool calls۔ Observations کو level
ERRORکے لحاظ سے filter کریں۔ جو tool 5% وقت ناکام ہوتا ہے، وہ aggregate success rate میں نظر نہیں آتا، مگر traces میں واضح دکھائی دیتا ہے، جہاں آپ model کو دوبارہ کوشش کرتے اور پھر اس مسئلے سے بچنے کے لیے tokens خرچ کرتے دیکھ سکتے ہیں۔
Retention window مقرر کریں اور وہ dashboard منتخب کریں جسے آپ deploy کرنے کے دن کے مطابق ہر ہفتے ایک ہی دن check کریں گے۔ ایسا observability tool جسے کوئی نہیں کھولتا، آخرکار disk بھرنے والا database بن جاتا ہے۔
FAQ
self-hosted Langfuse کے لیے کتنی memory درکار ہے؟
4 CPU cores اور 16 GiB memory مختص کریں۔ یہی ایک virtual machine کے لیے Langfuse کی Docker Compose گائیڈ کی تجویز ہے۔ اس کے علاوہ تقریباً 100 GiB storage بھی درکار ہے۔ شائع شدہ component minimums کے مطابق ClickHouse کے لیے 8 GiB، جبکہ web اور worker containers میں سے ہر ایک کے لیے 4 GiB درکار ہے۔ Postgres، Redis اور MinIO کو بھی ان کے علاوہ memory چاہیے۔ 8 GiB پر ایک developer کی instance چل جاتی ہے۔ 2 GiB کافی نہیں ہے: background merges کے دوران kernel ClickHouse کو ختم کر دیتا ہے، اور dmesg میں Out of memory: Killed process دکھائی دیتا ہے۔
data retention مقرر کرنے کے بعد بھی میری ClickHouse disk کیوں بھر رہی ہے؟
Retention setting صرف Langfuse کے اپنے data پر لاگو ہوتی ہے۔ ClickHouse diagnostic tables trace_log، text_log، opentelemetry_span_log، metric_log اور asynchronous_metric_log بھی الگ سے لکھتا ہے، اور ان کے ساتھ کوئی TTL شامل نہیں ہوتا۔ یہ معلوم کرنے کے لیے کہ کون سی table سب سے بڑی ہے، system.parts کو table کے لحاظ سے group کر کے query کریں۔ پھر /etc/clickhouse-server/config.d/ کے تحت موجود file میں remove="1" entry کے ذریعے غیر ضروری tables کو disable کریں، ClickHouse restart کریں، اور پہلے سے موجود tables drop کر کے استعمال شدہ space واپس حاصل کریں۔
Langfuse میں data retention کی کم از کم مدت کیا ہے؟
3 دن۔ Retention ہر project کے لیے project settings میں یا projects API کے ذریعے مقرر کی جاتی ہے۔ ایک nightly job مقررہ مدت سے پرانے traces، observations، scores اور media assets کو ClickHouse اور blob storage دونوں سے delete کرتی ہے۔ Deletion واپس نہیں کی جا سکتی، اس لیے اگر اس مدت سے زیادہ پرانی history درکار ہو تو پہلے blob storage export configure کریں۔
کیا مجھے Postgres اور ClickHouse دونوں کا backup لینا ہوگا؟
ہاں، کیونکہ دونوں میں مختلف data محفوظ ہوتا ہے۔ Postgres میں users، organisations، projects اور API keys ہوتے ہیں، جبکہ ClickHouse میں اصل trace data ہوتا ہے۔ صرف Postgres restore کرنے سے ایسی instance ملے گی جس میں آپ login تو کر سکیں گے، لیکن اس میں کوئی data نہیں ہوگا۔ MinIO bucket کا بھی backup لیں، کیونکہ اس میں وہ raw events محفوظ ہوتے ہیں جو Langfuse وصول ہوتے ہی persist کرتا ہے۔ یہ stack میں source of truth کے سب سے قریب ہوتے ہیں۔
کیا میں موجودہ OpenTelemetry setup کو self-hosted Langfuse سے منسلک کر سکتا ہوں؟
ہاں۔ Langfuse v4 اور اس کے v4 SDKs کی بنیاد OpenTelemetry پر ہے، اور Anthropic اور OpenAI OTel instrumentations براہ راست اس میں export کرتے ہیں۔ Python میں pip install langfuse opentelemetry-instrumentation-anthropic چلائیں، startup پر ایک بار AnthropicInstrumentor().instrument() call کریں، اور LANGFUSE_PUBLIC_KEY، LANGFUSE_SECRET_KEY اور LANGFUSE_BASE_URL کو اپنے host پر set کریں۔ کسی missing dashboard کی تلاش شروع کرنے سے پہلے langfuse.auth_check() سے تصدیق کریں۔