Skip to content

Commit f197c58

Browse files
committed
implemented both detailed trace view and events/download logs in clickhouse
1 parent f9dba60 commit f197c58

File tree

7 files changed

+96
-4
lines changed

7 files changed

+96
-4
lines changed

apps/webapp/app/presenters/v3/ApiRetrieveRunPresenter.server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export class ApiRetrieveRunPresenter {
7575
},
7676
select: {
7777
...commonRunSelect,
78+
traceId: true,
7879
payload: true,
7980
payloadType: true,
8081
output: true,

apps/webapp/app/routes/api.v1.runs.$runId.events.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { json } from "@remix-run/server-runtime";
22
import { z } from "zod";
33
import { getTaskEventStoreTableForRun } from "~/v3/taskEventStore.server";
44
import { createLoaderApiRoute } from "~/services/routeBuilders/apiBuilder.server";
5-
import { eventRepository } from "~/v3/eventRepository/eventRepository.server";
65
import { ApiRetrieveRunPresenter } from "~/presenters/v3/ApiRetrieveRunPresenter.server";
6+
import { resolveEventRepositoryForStore } from "~/v3/eventRepository/index.server";
77

88
const ParamsSchema = z.object({
99
runId: z.string(), // This is the run friendly ID
@@ -31,9 +31,12 @@ export const loader = createLoaderApiRoute(
3131
},
3232
},
3333
async ({ resource: run, authentication }) => {
34+
const eventRepository = resolveEventRepositoryForStore(run.taskEventStore);
35+
3436
const runEvents = await eventRepository.getRunEvents(
3537
getTaskEventStoreTableForRun(run),
3638
authentication.environment.id,
39+
run.traceId,
3740
run.friendlyId,
3841
run.createdAt,
3942
run.completedAt ?? undefined

apps/webapp/app/routes/api.v1.runs.$runId.trace.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { BatchId } from "@trigger.dev/core/v3/isomorphic";
33
import { z } from "zod";
44
import { $replica } from "~/db.server";
55
import { createLoaderApiRoute } from "~/services/routeBuilders/apiBuilder.server";
6-
import { eventRepository } from "~/v3/eventRepository/eventRepository.server";
6+
import { resolveEventRepositoryForStore } from "~/v3/eventRepository/index.server";
77
import { getTaskEventStoreTableForRun } from "~/v3/taskEventStore.server";
88

99
const ParamsSchema = z.object({
@@ -36,6 +36,8 @@ export const loader = createLoaderApiRoute(
3636
},
3737
},
3838
async ({ resource: run, authentication }) => {
39+
const eventRepository = resolveEventRepositoryForStore(run.taskEventStore);
40+
3941
const traceSummary = await eventRepository.getTraceDetailedSummary(
4042
getTaskEventStoreTableForRun(run),
4143
authentication.environment.id,

apps/webapp/app/routes/resources.runs.$runParam.logs.download.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import { LoaderFunctionArgs } from "@remix-run/server-runtime";
22
import { prisma } from "~/db.server";
33
import { requireUser } from "~/services/session.server";
44
import { v3RunParamsSchema } from "~/utils/pathBuilder";
5-
import { eventRepository } from "~/v3/eventRepository/eventRepository.server";
65
import type { RunPreparedEvent } from "~/v3/eventRepository/eventRepository.types";
76
import { createGzip } from "zlib";
87
import { Readable } from "stream";
98
import { formatDurationMilliseconds } from "@trigger.dev/core/v3/utils/durations";
109
import { getTaskEventStoreTableForRun } from "~/v3/taskEventStore.server";
1110
import { TaskEventKind } from "@trigger.dev/database";
11+
import { resolveEventRepositoryForStore } from "~/v3/eventRepository/index.server";
1212

1313
export async function loader({ params, request }: LoaderFunctionArgs) {
1414
const user = await requireUser(request);
@@ -33,9 +33,12 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
3333
return new Response("Not found", { status: 404 });
3434
}
3535

36+
const eventRepository = resolveEventRepositoryForStore(run.taskEventStore);
37+
3638
const runEvents = await eventRepository.getRunEvents(
3739
getTaskEventStoreTableForRun(run),
3840
run.runtimeEnvironmentId,
41+
run.traceId,
3942
run.friendlyId,
4043
run.createdAt,
4144
run.completedAt ?? undefined

apps/webapp/app/v3/eventRepository/clickhouseEventRepository.server.ts

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1512,11 +1512,92 @@ export class ClickhouseEventRepository implements IEventRepository {
15121512
async getRunEvents(
15131513
storeTable: TaskEventStoreTable,
15141514
environmentId: string,
1515+
traceId: string,
15151516
runId: string,
15161517
startCreatedAt: Date,
15171518
endCreatedAt?: Date
15181519
): Promise<RunPreparedEvent[]> {
1519-
throw new Error("ClickhouseEventRepository.getRunEvents not implemented");
1520+
const startCreatedAtWithBuffer = new Date(startCreatedAt.getTime() - 1000);
1521+
1522+
const queryBuilder = this._clickhouse.taskEvents.traceSummaryQueryBuilder();
1523+
1524+
queryBuilder.where("environment_id = {environmentId: String}", { environmentId });
1525+
queryBuilder.where("trace_id = {traceId: String}", { traceId });
1526+
queryBuilder.where("run_id = {runId: String}", { runId });
1527+
queryBuilder.where("start_time >= {startCreatedAt: String}", {
1528+
startCreatedAt: convertDateToNanoseconds(startCreatedAtWithBuffer).toString(),
1529+
});
1530+
1531+
if (endCreatedAt) {
1532+
queryBuilder.where("start_time <= {endCreatedAt: String}", {
1533+
endCreatedAt: convertDateToNanoseconds(endCreatedAt).toString(),
1534+
});
1535+
}
1536+
1537+
queryBuilder.where("kind != {kind: String}", { kind: "DEBUG_EVENT" });
1538+
queryBuilder.orderBy("start_time ASC");
1539+
1540+
if (this._config.maximumTraceSummaryViewCount) {
1541+
queryBuilder.limit(this._config.maximumTraceSummaryViewCount);
1542+
}
1543+
1544+
const [queryError, records] = await queryBuilder.execute();
1545+
1546+
if (queryError) {
1547+
throw queryError;
1548+
}
1549+
1550+
if (!records) {
1551+
return [];
1552+
}
1553+
1554+
const recordsGroupedBySpanId = records.reduce((acc, record) => {
1555+
acc[record.span_id] = [...(acc[record.span_id] ?? []), record];
1556+
return acc;
1557+
}, {} as Record<string, TaskEventSummaryV1Result[]>);
1558+
1559+
const spanSummaries = new Map<string, SpanSummary>();
1560+
1561+
for (const [spanId, spanRecords] of Object.entries(recordsGroupedBySpanId)) {
1562+
const spanSummary = this.#mergeRecordsIntoSpanSummary(spanId, spanRecords);
1563+
1564+
if (!spanSummary) {
1565+
continue;
1566+
}
1567+
1568+
spanSummaries.set(spanId, spanSummary);
1569+
}
1570+
1571+
const spans = Array.from(spanSummaries.values());
1572+
1573+
const overridesBySpanId: Record<string, SpanOverride> = {};
1574+
1575+
const finalSpans = spans.map((span) => {
1576+
return this.#applyAncestorOverrides(span, spanSummaries, overridesBySpanId);
1577+
});
1578+
1579+
const runPreparedEvents = finalSpans.map((span) => this.#spanSummaryToRunPreparedEvent(span));
1580+
1581+
return runPreparedEvents;
1582+
}
1583+
1584+
#spanSummaryToRunPreparedEvent(span: SpanSummary): RunPreparedEvent {
1585+
return {
1586+
spanId: span.id,
1587+
parentId: span.parentId ?? null,
1588+
runId: span.runId,
1589+
message: span.data.message,
1590+
style: span.data.style,
1591+
events: span.data.events,
1592+
startTime: convertDateToNanoseconds(span.data.startTime),
1593+
duration: span.data.duration,
1594+
isError: span.data.isError,
1595+
isPartial: span.data.isPartial,
1596+
isCancelled: span.data.isCancelled,
1597+
kind: "UNSPECIFIED",
1598+
attemptNumber: span.data.attemptNumber ?? null,
1599+
level: span.data.level,
1600+
};
15201601
}
15211602
}
15221603

apps/webapp/app/v3/eventRepository/eventRepository.server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,7 @@ export class EventRepository implements IEventRepository {
681681
public async getRunEvents(
682682
storeTable: TaskEventStoreTable,
683683
environmentId: string,
684+
traceId: string,
684685
runId: string,
685686
startCreatedAt: Date,
686687
endCreatedAt?: Date

apps/webapp/app/v3/eventRepository/eventRepository.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ export interface IEventRepository {
373373
getRunEvents(
374374
storeTable: TaskEventStoreTable,
375375
environmentId: string,
376+
traceId: string,
376377
runId: string,
377378
startCreatedAt: Date,
378379
endCreatedAt?: Date

0 commit comments

Comments
 (0)