feat: Python SDK real implementation + API ingestion routes
- SDK: client with BatchTransport, trace decorator/context manager, log_decision, thread-local context stack, nested trace→span support - API: POST /api/traces (batch ingest), GET /api/traces (paginated list), GET /api/traces/[id] (full trace with relations), GET /api/health - Tests: 8 unit tests for SDK (all passing) - Transport: thread-safe buffer with background flush thread
This commit is contained in:
46
apps/web/src/app/api/traces/[id]/route.ts
Normal file
46
apps/web/src/app/api/traces/[id]/route.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
// GET /api/traces/[id] — Get single trace with all relations
|
||||
export async function GET(
|
||||
_request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const { id } = await params;
|
||||
|
||||
if (!id || typeof id !== "string") {
|
||||
return NextResponse.json({ error: "Invalid trace ID" }, { status: 400 });
|
||||
}
|
||||
|
||||
const trace = await prisma.trace.findUnique({
|
||||
where: { id },
|
||||
include: {
|
||||
decisionPoints: {
|
||||
orderBy: {
|
||||
timestamp: "asc",
|
||||
},
|
||||
},
|
||||
spans: {
|
||||
orderBy: {
|
||||
startedAt: "asc",
|
||||
},
|
||||
},
|
||||
events: {
|
||||
orderBy: {
|
||||
timestamp: "asc",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!trace) {
|
||||
return NextResponse.json({ error: "Trace not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
return NextResponse.json({ trace }, { status: 200 });
|
||||
} catch (error) {
|
||||
console.error("Error retrieving trace:", error);
|
||||
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user