08 -- Observability: Langfuse
Prerequisite: 01 -- HTTP GatewayYou will need: Running Hangar, Langfuse instance (cloud or self-hosted) Time: 10 minutes Adds: Distributed tracing for tool invocations via Langfuse
The Problem
You know a tool call was slow. You don't know whether the delay was in Hangar (routing, cold start) or in the provider itself. You need end-to-end traces that break down each phase.
The Config
# config.yaml -- Recipe 08: Langfuse Tracing
providers:
my-mcp:
mode: remote
endpoint: "http://localhost:8080"
health_check_interval_s: 10
max_consecutive_failures: 3
observability: # NEW: Langfuse tracing
langfuse: # NEW: Langfuse configuration
enabled: true # NEW: enable Langfuse adapter
public_key: ${LANGFUSE_PUBLIC_KEY} # NEW: from environment
secret_key: ${LANGFUSE_SECRET_KEY} # NEW: from environment
host: "https://cloud.langfuse.com" # NEW: Langfuse hostTry It
Set environment variables:
bashexport LANGFUSE_PUBLIC_KEY="pk-lf-..." export LANGFUSE_SECRET_KEY="sk-lf-..."Start Hangar:
bashmcp-hangar serve --http --port 8000Make a tool call:
bashcurl -X POST http://localhost:8000/api/providers/my-mcp/startOpen Langfuse dashboard and find the trace. You see spans for:
hangar.tool_invocation-- overall callhangar.cold_start-- provider initialization (if cold)hangar.provider_call-- actual provider communication
What Just Happened
The TracedProviderService wraps tool invocations with Langfuse spans via the LangfuseObservabilityAdapter. Each tool call creates a trace with child spans for cold start (if needed) and the actual provider call. Correlation IDs link Hangar traces to provider-side traces.
Key Config Reference
| Key | Type | Default | Description |
|---|---|---|---|
observability.langfuse.enabled | bool | false | Enable Langfuse tracing |
observability.langfuse.public_key | string | -- | Langfuse public key (use env var) |
observability.langfuse.secret_key | string | -- | Langfuse secret key (use env var) |
observability.langfuse.host | string | https://cloud.langfuse.com | Langfuse host URL |
What's Next
You've set up external observability. Now try running providers as local subprocesses instead of remote HTTP.