3
import { prisma } from "@/src/server/db";
4
import { makeAPICall, pruneDatabase } from "@/src/__tests__/test-utils";
5
import { v4 as uuidv4 } from "uuid";
7
describe("/api/public/spans API Endpoint", () => {
8
beforeEach(async () => await pruneDatabase());
9
afterEach(async () => await pruneDatabase());
11
it("should create span after trace", async () => {
12
await pruneDatabase();
14
const traceId = uuidv4();
16
await makeAPICall("POST", "/api/public/traces", {
20
projectId: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a",
21
metadata: { key: "value" },
26
const dbTrace = await prisma.trace.findMany({
32
expect(dbTrace.length).toBeGreaterThan(0);
33
expect(dbTrace[0]?.id).toBe(traceId);
35
const spanId = uuidv4();
36
const createSpan = await makeAPICall("POST", "/api/public/spans", {
40
startTime: "2021-01-01T00:00:00.000Z",
41
endTime: "2021-01-01T00:00:00.000Z",
42
input: { input: "value" },
43
metadata: { meta: "value" },
47
expect(createSpan.status).toBe(200);
48
const dbSpan = await prisma.observation.findUnique({
54
expect(dbSpan?.id).toBe(spanId);
55
expect(dbSpan?.traceId).toBe(traceId);
56
expect(dbSpan?.name).toBe("span-name");
57
expect(dbSpan?.startTime).toEqual(new Date("2021-01-01T00:00:00.000Z"));
58
expect(dbSpan?.endTime).toEqual(new Date("2021-01-01T00:00:00.000Z"));
59
expect(dbSpan?.input).toEqual({ input: "value" });
60
expect(dbSpan?.metadata).toEqual({ meta: "value" });
61
expect(dbSpan?.version).toBe("2.0.0");
64
it("should create span before trace", async () => {
65
await pruneDatabase();
67
const traceId = uuidv4();
68
const spanId = uuidv4();
70
const createSpan = await makeAPICall("POST", "/api/public/spans", {
74
startTime: "2021-01-01T00:00:00.000Z",
75
endTime: "2021-01-01T00:00:00.000Z",
76
input: { input: "value" },
77
metadata: { meta: "value" },
81
expect(createSpan.status).toBe(200);
82
const dbSpan = await prisma.observation.findUnique({
88
expect(dbSpan?.id).toBe(spanId);
89
expect(dbSpan?.traceId).toBe(traceId);
90
expect(dbSpan?.name).toBe("span-name");
91
expect(dbSpan?.startTime).toEqual(new Date("2021-01-01T00:00:00.000Z"));
92
expect(dbSpan?.endTime).toEqual(new Date("2021-01-01T00:00:00.000Z"));
93
expect(dbSpan?.input).toEqual({ input: "value" });
94
expect(dbSpan?.metadata).toEqual({ meta: "value" });
95
expect(dbSpan?.version).toBe("2.0.0");
97
await makeAPICall("POST", "/api/public/traces", {
101
projectId: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a",
102
metadata: { key: "value" },
107
const dbTrace = await prisma.trace.findMany({
113
expect(dbTrace.length).toBeGreaterThan(0);
114
expect(dbTrace[0]?.id).toBe(traceId);
117
it("should create span after trace ignoring externalId", async () => {
118
const traceId = uuidv4();
119
const spanId = uuidv4();
121
const response = await makeAPICall("POST", "/api/public/traces", {
122
externalId: uuidv4(),
126
projectId: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a",
128
expect(response.status).toBe(200);
129
const createSpan = await makeAPICall("POST", "/api/public/spans", {
132
projectId: "7a88fb47-b4e2-43b8-a06c-a5ce950dc53a",
134
externalTraceIdType: "EXTERNAL",
136
expect(createSpan.status).toBe(200);
138
const dbSpan = await prisma.observation.findFirstOrThrow({
143
expect(dbSpan.id).toBe(spanId);
144
expect(dbSpan.traceId).toBe(traceId);
147
it("should create trace when creating span without existing trace", async () => {
148
const spanName = uuidv4();
150
const spanId = uuidv4();
151
const createSpan = await makeAPICall("POST", "/api/public/spans", {
154
startTime: "2021-01-01T00:00:00.000Z",
155
endTime: "2021-01-01T00:00:00.000Z",
156
input: { input: "value" },
157
metadata: { meta: "value" },
161
const dbTrace = await prisma.trace.findMany({
167
expect(dbTrace.length).toBe(1);
168
expect(dbTrace[0]?.name).toBe(spanName);
170
expect(createSpan.status).toBe(200);
171
const dbSpan = await prisma.observation.findUnique({
177
expect(dbSpan?.id).toBe(spanId);
178
expect(dbSpan?.traceId).toBe(dbTrace[0]?.id);
179
expect(dbSpan?.name).toBe(spanName);
180
expect(dbSpan?.startTime).toEqual(new Date("2021-01-01T00:00:00.000Z"));
181
expect(dbSpan?.endTime).toEqual(new Date("2021-01-01T00:00:00.000Z"));
182
expect(dbSpan?.input).toEqual({ input: "value" });
183
expect(dbSpan?.metadata).toEqual({ meta: "value" });
184
expect(dbSpan?.version).toBe("2.0.0");
187
it("should create trace when creating span without existing trace with externalId", async () => {
188
const spanName = uuidv4();
190
const spanId = uuidv4();
191
const traceId = uuidv4();
192
const createSpan = await makeAPICall("POST", "/api/public/spans", {
194
traceIdType: "EXTERNAL",
197
startTime: "2021-01-01T00:00:00.000Z",
198
endTime: "2021-01-01T00:00:00.000Z",
199
input: { input: "value" },
200
metadata: { meta: "value" },
204
expect(createSpan.status).toBe(200);
206
const dbSpan = await prisma.observation.findMany({
211
expect(dbSpan.length).toBe(1);
212
expect(dbSpan[0]?.name).toBe(spanName);
213
expect(dbSpan[0]?.id).toBe(spanId);
214
expect(dbSpan[0]?.traceId).toBe(traceId);
216
const dbTraces = await prisma.trace.findMany();
217
expect(dbTraces.length).toBe(0);
220
it("should create trace when creating span without existing trace without traceId", async () => {
221
const generationName = uuidv4();
223
const spanId = uuidv4();
224
const createSpan = await makeAPICall("POST", "/api/public/spans", {
226
name: generationName,
227
startTime: "2021-01-01T00:00:00.000Z",
228
endTime: "2021-01-01T00:00:00.000Z",
229
input: { key: "value" },
230
metadata: { key: "value" },
234
const dbSpan = await prisma.observation.findFirstOrThrow({
236
name: generationName,
240
const dbTrace = await prisma.trace.findMany({
246
expect(dbTrace.length).toBe(1);
247
expect(dbTrace[0]?.name).toBe(generationName);
249
expect(createSpan.status).toBe(200);
251
expect(dbSpan.id).toBe(spanId);
252
expect(dbSpan.traceId).toBe(dbTrace[0]?.id);
253
expect(dbSpan.name).toBe(generationName);
254
expect(dbSpan.startTime).toEqual(new Date("2021-01-01T00:00:00.000Z"));
255
expect(dbSpan.endTime).toEqual(new Date("2021-01-01T00:00:00.000Z"));
256
expect(dbSpan.input).toEqual({ key: "value" });
257
expect(dbSpan.metadata).toEqual({ key: "value" });
258
expect(dbSpan.version).toBe("2.0.0");
261
it("should update span", async () => {
262
const spanName = uuidv4();
264
const spanId = uuidv4();
265
const createSpan = await makeAPICall("POST", "/api/public/spans", {
268
startTime: "2021-01-01T00:00:00.000Z",
269
endTime: "2021-01-01T00:00:00.000Z",
270
input: { input: "value" },
271
metadata: { meta: "value" },
275
expect(createSpan.status).toBe(200);
277
const updatedSpan = await makeAPICall("PATCH", "/api/public/spans", {
279
output: { key: "this is a great gpt output" },
281
expect(updatedSpan.status).toBe(200);
283
const dbSpan = await prisma.observation.findUnique({
289
expect(dbSpan?.id).toBe(spanId);
290
expect(dbSpan?.name).toBe(spanName);
291
expect(dbSpan?.startTime).toEqual(new Date("2021-01-01T00:00:00.000Z"));
292
expect(dbSpan?.endTime).toEqual(new Date("2021-01-:00:00.000Z"));
293
expect(dbSpan?.input).toEqual({ input: "value" });
294
expect(dbSpan?.output).toEqual({ key: "this is a great gpt output" });
295
expect(dbSpan?.metadata).toEqual({ meta: "value" });
296
expect(dbSpan?.version).toBe("2.0.0");
299
it("should not upsert span if span does not exist", async () => {
300
const spanId = uuidv4();
302
const updatedSpan = await makeAPICall("PATCH", "/api/public/spans", {
304
output: { key: "this is a great gpt output" },
306
expect(updatedSpan.status).toBe(404);
308
const dbSpan = await prisma.observation.findUnique({
314
expect(dbSpan).toBeNull();