Skip to content

Commit 6100b2d

Browse files
committed
updated clickhouse config for logs
fixed admin access to logs feature added alpha badge to logs
1 parent 9d9bdc3 commit 6100b2d

File tree

8 files changed

+64
-24
lines changed

8 files changed

+64
-24
lines changed

apps/webapp/app/components/logs/LogsTable.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { ArrowPathIcon } from "@heroicons/react/20/solid";
2-
import { Link } from "@remix-run/react";
32
import { formatDurationNanoseconds } from "@trigger.dev/core/v3";
43
import { type ReactNode, useEffect, useRef, useState } from "react";
54
import { cn } from "~/utils/cn";
@@ -104,13 +103,11 @@ function highlightText(text: string, searchTerm: string | undefined): ReactNode
104103
export function LogsTable({
105104
logs,
106105
hasFilters,
107-
filters,
108106
searchTerm,
109107
isLoading = false,
110108
isLoadingMore = false,
111109
hasMore = false,
112110
onLoadMore,
113-
variant = "dimmed",
114111
selectedLogId,
115112
onLogSelect,
116113
}: LogsTableProps) {

apps/webapp/app/components/navigation/SideMenu.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -269,13 +269,16 @@ export function SideMenu({
269269
to={v3DeploymentsPath(organization, project, environment)}
270270
data-action="deployments"
271271
/>
272-
<SideMenuItem
273-
name="Logs"
274-
icon={LogsIcon}
275-
activeIconColor="text-logs"
276-
to={v3LogsPath(organization, project, environment)}
277-
data-action="logs"
278-
/>
272+
{(isAdmin || user.isImpersonating) && (
273+
<SideMenuItem
274+
name="Logs"
275+
icon={LogsIcon}
276+
activeIconColor="text-logs"
277+
to={v3LogsPath(organization, project, environment)}
278+
data-action="logs"
279+
badge={<AlphaBadge />}
280+
/>
281+
)}
279282
<SideMenuItem
280283
name="Test"
281284
icon={BeakerIcon}

apps/webapp/app/env.server.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,6 +1175,18 @@ const EnvironmentSchema = z
11751175
CLICKHOUSE_LOG_LEVEL: z.enum(["log", "error", "warn", "info", "debug"]).default("info"),
11761176
CLICKHOUSE_COMPRESSION_REQUEST: z.string().default("1"),
11771177

1178+
// Logs List Query Settings (for paginated log views)
1179+
CLICKHOUSE_LOGS_LIST_MAX_MEMORY_USAGE: z.coerce.number().int().default(2_000_000_000),
1180+
CLICKHOUSE_LOGS_LIST_MAX_BYTES_BEFORE_EXTERNAL_SORT: z.coerce.number().int().default(1_000_000_000),
1181+
CLICKHOUSE_LOGS_LIST_MAX_THREADS: z.coerce.number().int().default(4),
1182+
CLICKHOUSE_LOGS_LIST_MAX_ROWS_TO_READ: z.coerce.number().int().optional(),
1183+
CLICKHOUSE_LOGS_LIST_MAX_EXECUTION_TIME: z.coerce.number().int().optional(),
1184+
1185+
// Logs Detail Query Settings (for single log views)
1186+
CLICKHOUSE_LOGS_DETAIL_MAX_MEMORY_USAGE: z.coerce.number().int().default(500_000_000),
1187+
CLICKHOUSE_LOGS_DETAIL_MAX_THREADS: z.coerce.number().int().default(2),
1188+
CLICKHOUSE_LOGS_DETAIL_MAX_EXECUTION_TIME: z.coerce.number().int().optional(),
1189+
11781190
EVENTS_CLICKHOUSE_URL: z
11791191
.string()
11801192
.optional()

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type LoaderFunctionArgs } from "@remix-run/server-runtime";
1+
import { type LoaderFunctionArgs , redirect} from "@remix-run/server-runtime";
22
import { type MetaFunction, useFetcher, useNavigation, useLocation } from "@remix-run/react";
33
import {
44
TypedAwait,
@@ -62,6 +62,10 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
6262
const userId = user.id;
6363
const isAdmin = user.admin || user.isImpersonating;
6464

65+
if (!isAdmin) {
66+
throw redirect("/");
67+
}
68+
6569
const { projectParam, organizationSlug, envParam } = EnvironmentParamSchema.parse(params);
6670

6771
const project = await findProjectBySlug(organizationSlug, projectParam, userId);

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { type LoaderFunctionArgs } from "@remix-run/server-runtime";
22
import { json } from "@remix-run/node";
3-
import { requireUserId } from "~/services/session.server";
3+
import { requireUser, requireUserId } from "~/services/session.server";
44
import { EnvironmentParamSchema } from "~/utils/pathBuilder";
55
import { findProjectBySlug } from "~/models/project.server";
66
import { findEnvironmentBySlug } from "~/models/runtimeEnvironment.server";
77
import { getRunFiltersFromRequest } from "~/presenters/RunFilters.server";
88
import { LogsListPresenter, type LogLevel } from "~/presenters/v3/LogsListPresenter.server";
99
import { $replica } from "~/db.server";
1010
import { clickhouseClient } from "~/services/clickhouseInstance.server";
11-
import { getUserById } from "~/models/user.server";
1211

1312
// Valid log levels for filtering
1413
const validLevels: LogLevel[] = ["TRACE", "DEBUG", "INFO", "WARN", "ERROR", "CANCELLED"];
@@ -33,9 +32,8 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
3332
throw new Response("Environment not found", { status: 404 });
3433
}
3534

36-
const user = await requireUserId(request);
37-
const userRecord = await getUserById(user);
38-
const isAdmin = userRecord?.admin || userRecord?.isImpersonating;
35+
const user = await requireUser(request);
36+
const isAdmin = user?.admin || user?.isImpersonating;
3937

4038
const filters = await getRunFiltersFromRequest(request);
4139

apps/webapp/app/services/clickhouseInstance.server.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,28 @@ function initializeClickhouseClient() {
1212

1313
console.log(`🗃️ Clickhouse service enabled to host ${url.host}`);
1414

15+
// Build logs query settings from environment variables
16+
const logsQuerySettings = {
17+
list: {
18+
max_memory_usage: env.CLICKHOUSE_LOGS_LIST_MAX_MEMORY_USAGE.toString(),
19+
max_bytes_before_external_sort: env.CLICKHOUSE_LOGS_LIST_MAX_BYTES_BEFORE_EXTERNAL_SORT.toString(),
20+
max_threads: env.CLICKHOUSE_LOGS_LIST_MAX_THREADS,
21+
...(env.CLICKHOUSE_LOGS_LIST_MAX_ROWS_TO_READ && {
22+
max_rows_to_read: env.CLICKHOUSE_LOGS_LIST_MAX_ROWS_TO_READ.toString(),
23+
}),
24+
...(env.CLICKHOUSE_LOGS_LIST_MAX_EXECUTION_TIME && {
25+
max_execution_time: env.CLICKHOUSE_LOGS_LIST_MAX_EXECUTION_TIME,
26+
}),
27+
},
28+
detail: {
29+
max_memory_usage: env.CLICKHOUSE_LOGS_DETAIL_MAX_MEMORY_USAGE.toString(),
30+
max_threads: env.CLICKHOUSE_LOGS_DETAIL_MAX_THREADS,
31+
...(env.CLICKHOUSE_LOGS_DETAIL_MAX_EXECUTION_TIME && {
32+
max_execution_time: env.CLICKHOUSE_LOGS_DETAIL_MAX_EXECUTION_TIME,
33+
}),
34+
},
35+
};
36+
1537
const clickhouse = new ClickHouse({
1638
url: url.toString(),
1739
name: "clickhouse-instance",
@@ -24,6 +46,7 @@ function initializeClickhouseClient() {
2446
request: true,
2547
},
2648
maxOpenConnections: env.CLICKHOUSE_MAX_OPEN_CONNECTIONS,
49+
logsQuerySettings,
2750
});
2851

2952
return clickhouse;

internal-packages/clickhouse/src/index.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ export {
4646
} from "./client/tsql.js";
4747
export type { OutputColumnMetadata } from "@internal/tsql";
4848

49+
export type LogsQuerySettings = {
50+
list?: ClickHouseSettings;
51+
detail?: ClickHouseSettings;
52+
};
53+
4954
export type ClickhouseCommonConfig = {
5055
keepAlive?: {
5156
enabled?: boolean;
@@ -60,6 +65,7 @@ export type ClickhouseCommonConfig = {
6065
response?: boolean;
6166
};
6267
maxOpenConnections?: number;
68+
logsQuerySettings?: LogsQuerySettings;
6369
};
6470

6571
export type ClickHouseConfig =
@@ -83,9 +89,11 @@ export class ClickHouse {
8389
public readonly writer: ClickhouseWriter;
8490
private readonly logger: Logger;
8591
private _splitClients: boolean;
92+
private readonly logsQuerySettings?: LogsQuerySettings;
8693

8794
constructor(config: ClickHouseConfig) {
8895
this.logger = config.logger ?? new Logger("ClickHouse", config.logLevel ?? "debug");
96+
this.logsQuerySettings = config.logsQuerySettings;
8997

9098
if (config.url) {
9199
const url = new URL(config.url);
@@ -197,8 +205,8 @@ export class ClickHouse {
197205
traceSummaryQueryBuilder: getTraceSummaryQueryBuilderV2(this.reader),
198206
traceDetailedSummaryQueryBuilder: getTraceDetailedSummaryQueryBuilderV2(this.reader),
199207
spanDetailsQueryBuilder: getSpanDetailsQueryBuilderV2(this.reader),
200-
logsListQueryBuilder: getLogsListQueryBuilder(this.reader),
201-
logDetailQueryBuilder: getLogDetailQueryBuilder(this.reader),
208+
logsListQueryBuilder: getLogsListQueryBuilder(this.reader, this.logsQuerySettings?.list),
209+
logDetailQueryBuilder: getLogDetailQueryBuilder(this.reader, this.logsQuerySettings?.detail),
202210
};
203211
}
204212
}

internal-packages/clickhouse/src/taskEvents.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -276,12 +276,7 @@ export function getLogsListQueryBuilder(ch: ClickhouseReader, settings?: ClickHo
276276
"metadata",
277277
"attributes"
278278
],
279-
settings: {
280-
max_memory_usage: "2000000000", // 2GB per query limit
281-
max_bytes_before_external_sort: "1000000000", // 1GB before spill to disk
282-
max_threads: 4, // Limit parallelism to reduce memory
283-
...settings,
284-
},
279+
settings,
285280
});
286281
}
287282

0 commit comments

Comments
 (0)