feat: restore Langfuse observability integration (#103)

- Add lib/langfuse.ts with client, trace input/output, telemetry config
- Add instrumentation.ts for OpenTelemetry setup with Langfuse span processor
- Add /api/log-save endpoint for logging diagram saves
- Add /api/log-feedback endpoint for thumbs up/down feedback
- Update chat route with sessionId tracking and telemetry
- Add feedback buttons (thumbs up/down) to chat messages
- Add sessionId tracking throughout the app
- Update env.example with Langfuse configuration
- Add @langfuse/client, @langfuse/otel, @langfuse/tracing, @opentelemetry/sdk-trace-node
This commit is contained in:
Dayuan Jiang
2025-12-05 21:15:02 +09:00
committed by GitHub
parent 4cd78dc561
commit ed29e32ba3
12 changed files with 807 additions and 10 deletions

View File

@@ -63,6 +63,9 @@ export default function ChatPanel({
const [showHistory, setShowHistory] = useState(false);
const [input, setInput] = useState("");
// Generate a unique session ID for Langfuse tracing
const [sessionId, setSessionId] = useState(() => `session-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`);
// Store XML snapshots for each user message (keyed by message index)
const xmlSnapshotsRef = useRef<Map<number, string>>(new Map());
@@ -217,6 +220,7 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
{
body: {
xml: chartXml,
sessionId,
},
}
);
@@ -297,6 +301,7 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
{
body: {
xml: savedXml,
sessionId,
},
}
);
@@ -353,6 +358,7 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
{
body: {
xml: savedXml,
sessionId,
},
}
);
@@ -440,6 +446,7 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
error={error}
setInput={setInput}
setFiles={handleFileChange}
sessionId={sessionId}
onRegenerate={handleRegenerate}
onEditMessage={handleEditMessage}
/>
@@ -455,12 +462,14 @@ Please retry with an adjusted search pattern or use display_diagram if retries a
onClearChat={() => {
setMessages([]);
clearDiagram();
setSessionId(`session-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`);
xmlSnapshotsRef.current.clear();
}}
files={files}
onFileChange={handleFileChange}
showHistory={showHistory}
onToggleHistory={setShowHistory}
sessionId={sessionId}
error={error}
/>
</footer>