# Langfuse

LLM observability and tracing platform for ODS

## Overview

Langfuse is an open-source LLM observability platform that captures traces, evaluations, and prompt versions for every call routed through LiteLLM. It runs at `http://localhost:3006` and is pre-integrated with LiteLLM — when Langfuse is enabled, the compose overlay automatically injects the project credentials into LiteLLM so traces appear without any manual configuration.

Langfuse ships **disabled by default**. Enable it during install with `--langfuse` or at any time with:

```bash
ods enable langfuse
```

## Features

- **Full request tracing**: Captures input, output, latency, token counts, and model for every LLM call
- **Evaluations**: Score traces manually or programmatically to track quality over time
- **Prompt management**: Version and A/B test prompt templates from the UI
- **LiteLLM integration**: Traces appear automatically — no SDK changes required
- **Dashboard integration**: Observability feature managed from the ODS dashboard
- **Isolated storage**: Dedicated PostgreSQL, ClickHouse, Redis, and MinIO services — no shared state with other extensions

## Configuration

Environment variables (set in `.env`, auto-generated by the installer):

| Variable | Default | Description |
|----------|---------|-------------|
| `LANGFUSE_PORT` | `3006` | External port for the Langfuse web UI |
| `LANGFUSE_ENABLED` | `false` | Enables LiteLLM tracing callback when set to `true` |
| `LANGFUSE_INIT_USER_EMAIL` | `admin@ods.local` | Initial admin email address |
| `LANGFUSE_INIT_USER_PASSWORD` | *(generated)* | Initial admin password |
| `LANGFUSE_PROJECT_PUBLIC_KEY` | *(generated)* | Project public key — passed to LiteLLM automatically |
| `LANGFUSE_PROJECT_SECRET_KEY` | *(generated)* | Project secret key — passed to LiteLLM automatically |
| `LANGFUSE_DB_PASSWORD` | *(generated)* | PostgreSQL database password |
| `LANGFUSE_CLICKHOUSE_PASSWORD` | *(generated)* | ClickHouse password |
| `LANGFUSE_REDIS_PASSWORD` | *(generated)* | Redis password |
| `LANGFUSE_MINIO_ACCESS_KEY` | *(generated)* | MinIO access key for event uploads |
| `LANGFUSE_MINIO_SECRET_KEY` | *(generated)* | MinIO secret key for event uploads |
| `LANGFUSE_NEXTAUTH_SECRET` | *(generated)* | Session signing secret |
| `LANGFUSE_SALT` | *(generated)* | Password hashing salt |
| `LANGFUSE_ENCRYPTION_KEY` | *(generated)* | Encryption key for stored credentials |

All secrets are generated by `./install.sh` and stored in `.env`. After changing `LANGFUSE_INIT_USER_EMAIL` or `LANGFUSE_INIT_USER_PASSWORD`, recreate the Langfuse web container to apply the new credentials:

```bash
docker compose up -d --force-recreate langfuse
```

## Data Persistence

| Path (host) | Mounted at (container) | Contents |
|-------------|------------------------|----------|
| `data/langfuse/postgres/` | `/var/lib/postgresql/data` | Trace metadata, projects, and user data |
| `data/langfuse/clickhouse/` | `/var/lib/clickhouse` | Event data and analytics storage |
| `data/langfuse/redis/` | `/data` | Queue and caching |
| `data/langfuse/minio/` | `/data` | Event upload bucket (`langfuse-events`) |

## LiteLLM Integration

When Langfuse is enabled, the `compose.yaml` overlay merges the following into the LiteLLM service:

```yaml
environment:
  LANGFUSE_PUBLIC_KEY: ${LANGFUSE_PROJECT_PUBLIC_KEY}
  LANGFUSE_SECRET_KEY: ${LANGFUSE_PROJECT_SECRET_KEY}
  LANGFUSE_HOST: http://langfuse:3000
  LANGFUSE_TRACING_ENABLED: ${LANGFUSE_ENABLED}
```

No LiteLLM config changes are needed — tracing activates automatically when `LANGFUSE_ENABLED=true` is in `.env`.

## Services

Langfuse runs six containers, all on the isolated `langfuse-internal` network:

| Container | Image | Role |
|-----------|-------|------|
| `ods-langfuse-web` | `langfuse/langfuse:3.159.0` | Web UI and API (port 3006) |
| `ods-langfuse-worker` | `langfuse/langfuse-worker:3.159.0` | Async event processing |
| `ods-langfuse-postgres` | `postgres:17.9-alpine` | Relational store |
| `ods-langfuse-clickhouse` | `clickhouse/clickhouse-server:26.2.4.23` | Analytics store |
| `ods-langfuse-redis` | `redis:7.4.8-alpine` | Job queue |
| `ods-langfuse-minio` | `minio/minio` | Object store for event uploads |

## Files

- `compose.yaml.disabled` — Service definition (renamed to `compose.yaml` when enabled)
- `manifest.yaml` — Service metadata and feature definitions

## Troubleshooting

**Service not starting:**
```bash
docker compose ps langfuse langfuse-worker langfuse-postgres langfuse-clickhouse langfuse-redis langfuse-minio
docker compose logs langfuse
```

All six services must be healthy before the web UI starts. ClickHouse has a 90-second start period — allow extra time on first launch.

**Cannot log in:**
- Verify `LANGFUSE_INIT_USER_EMAIL` and `LANGFUSE_INIT_USER_PASSWORD` are set in `.env`
- Credentials are seeded on first start. To reset, remove `data/langfuse/postgres/` and recreate all Langfuse containers.

**No traces appearing in the UI:**
- Confirm `LANGFUSE_ENABLED=true` in `.env`
- Restart LiteLLM after enabling: `docker compose up -d --force-recreate litellm`
- Check LiteLLM logs for callback errors: `docker compose logs litellm | grep -i langfuse`

**High memory usage:**
- ClickHouse is the largest consumer; default limit is 2 GB. Adjust under `deploy.resources.limits` in the compose file.

## License

Part of ODS — Local AI Infrastructure
