shared: auto-emit Langfuse trace+span per HTTP request — closes OPEN #2

Adds langfuseMiddleware in internal/shared so every daemon's
shared.Run gets free production-traffic trace visibility when
LANGFUSE_URL + LANGFUSE_PUBLIC_KEY + LANGFUSE_SECRET_KEY are set.
Same env names + file shape as the multi_coord_stress driver, so
operators ship one /etc/lakehouse/langfuse.env across the deploy.

Wiring is auth-gated: middleware runs INSIDE the RequireAuth group,
so 401s from credential-stuffing don't pollute traces. /health is
exempt so LB probes don't either. Missing env vars → nil client →
middleware is a passthrough no-op (fail-open per ADR-005 5.1).

Bundled deploy:
- langfuse.env.example template (mode 0640, root:lakehouse)
- 11 systemd units gain `EnvironmentFile=-/etc/lakehouse/langfuse.env`
  (leading - so missing file = OK)
- REPLICATION.md bootstrap section documents setup

Tests (4): nil passthrough, /health bypass, real-request emission,
status-writer wrapping. All green.

STATE_OF_PLAY OPEN list: 5 rows → 4 rows.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
root
2026-04-30 19:55:42 -05:00
co-authored by Claude Opus 4.7
parent 5a3364f539
commit 68d9e554b0
17 changed files with 311 additions and 5 deletions
+16
View File
@@ -75,6 +75,18 @@ func Run(serviceName, addr string, register RegisterRoutes, auth AuthConfig) err
Level: slog.LevelInfo,
}))
// Optional Langfuse client from LANGFUSE_URL + LANGFUSE_PUBLIC_KEY
// + LANGFUSE_SECRET_KEY env vars. Per OPEN item #2: every daemon
// gets free production-traffic trace visibility when those env
// vars are set. Missing any of the three → nil client → middleware
// becomes a passthrough.
lf := loadLangfuseFromEnv()
if lf != nil {
// Make sure pending events flush on graceful shutdown so the
// last few requests' traces don't get lost.
defer func() { _ = lf.Close() }()
}
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
@@ -95,8 +107,12 @@ func Run(serviceName, addr string, register RegisterRoutes, auth AuthConfig) err
// Registered routes live inside an auth-gated group so
// RequireAuth applies uniformly without per-handler wiring.
// Empty auth → middleware is a no-op (group is transparent).
// Langfuse middleware sits AFTER auth so we don't trace 401s
// from credential-stuffing attempts (avoids polluting traces
// with non-real-traffic).
r.Group(func(authed chi.Router) {
authed.Use(RequireAuth(auth))
authed.Use(langfuseMiddleware(serviceName, lf))
register(authed)
})
}