Skip to content

Commit 6be1dbd

Browse files
committed
removed time presets
debug level only for admins removed AI helper
1 parent 1dbfdce commit 6be1dbd

7 files changed

Lines changed: 175 additions & 197 deletions

File tree

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

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { FilterMenuProvider, appliedSummary } from "~/components/runs/v3/SharedF
1616
import type { LogLevel } from "~/presenters/v3/LogsListPresenter.server";
1717
import { cn } from "~/utils/cn";
1818

19-
const logLevels: { level: LogLevel; label: string; color: string }[] = [
19+
const allLogLevels: { level: LogLevel; label: string; color: string }[] = [
2020
{ level: "ERROR", label: "Error", color: "text-error" },
2121
{ level: "WARN", label: "Warning", color: "text-warning" },
2222
{ level: "INFO", label: "Info", color: "text-blue-400" },
@@ -25,6 +25,13 @@ const logLevels: { level: LogLevel; label: string; color: string }[] = [
2525
{ level: "TRACE", label: "Trace", color: "text-charcoal-500" },
2626
];
2727

28+
function getAvailableLevels(showDebug: boolean): typeof allLogLevels {
29+
if (showDebug) {
30+
return allLogLevels;
31+
}
32+
return allLogLevels.filter((level) => level.level !== "DEBUG");
33+
}
34+
2835
function getLevelBadgeColor(level: LogLevel): string {
2936
switch (level) {
3037
case "ERROR":
@@ -45,13 +52,13 @@ function getLevelBadgeColor(level: LogLevel): string {
4552

4653
const shortcut = { key: "l" };
4754

48-
export function LogsLevelFilter() {
55+
export function LogsLevelFilter({ showDebug = false }: { showDebug?: boolean }) {
4956
const { values } = useSearchParams();
5057
const selectedLevels = values("levels");
5158
const hasLevels = selectedLevels.length > 0 && selectedLevels.some((v) => v !== "");
5259

5360
if (hasLevels) {
54-
return <AppliedLevelFilter />;
61+
return <AppliedLevelFilter showDebug={showDebug} />;
5562
}
5663

5764
return (
@@ -70,6 +77,7 @@ export function LogsLevelFilter() {
7077
}
7178
searchValue={search}
7279
clearSearchValue={() => setSearch("")}
80+
showDebug={showDebug}
7381
/>
7482
)}
7583
</FilterMenuProvider>
@@ -81,11 +89,13 @@ function LevelDropdown({
8189
clearSearchValue,
8290
searchValue,
8391
onClose,
92+
showDebug = false,
8493
}: {
8594
trigger: ReactNode;
8695
clearSearchValue: () => void;
8796
searchValue: string;
8897
onClose?: () => void;
98+
showDebug?: boolean;
8999
}) {
90100
const { values, replace } = useSearchParams();
91101

@@ -94,11 +104,12 @@ function LevelDropdown({
94104
replace({ levels: values, cursor: undefined, direction: undefined });
95105
};
96106

107+
const availableLevels = getAvailableLevels(showDebug);
97108
const filtered = useMemo(() => {
98-
return logLevels.filter((item) =>
109+
return availableLevels.filter((item) =>
99110
item.label.toLowerCase().includes(searchValue.toLowerCase())
100111
);
101-
}, [searchValue]);
112+
}, [searchValue, availableLevels]);
102113

103114
return (
104115
<SelectProvider value={values("levels")} setValue={handleChange} virtualFocus={true}>
@@ -137,7 +148,7 @@ function LevelDropdown({
137148
);
138149
}
139150

140-
function AppliedLevelFilter() {
151+
function AppliedLevelFilter({ showDebug = false }: { showDebug?: boolean }) {
141152
const { values, del } = useSearchParams();
142153
const levels = values("levels");
143154

@@ -162,6 +173,7 @@ function AppliedLevelFilter() {
162173
}
163174
searchValue={search}
164175
clearSearchValue={() => setSearch("")}
176+
showDebug={showDebug}
165177
/>
166178
)}
167179
</FilterMenuProvider>

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

Lines changed: 38 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
import { MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/20/solid";
22
import { useNavigate } from "@remix-run/react";
33
import { useCallback, useEffect, useRef, useState } from "react";
4-
import { AISparkleIcon } from "~/assets/icons/AISparkleIcon";
54
import { Input } from "~/components/primitives/Input";
65
import { ShortcutKey } from "~/components/primitives/ShortcutKey";
76
import { cn } from "~/utils/cn";
87
import { useOptimisticLocation } from "~/hooks/useOptimisticLocation";
9-
import { AIFilterInput } from "~/components/runs/v3/AIFilterInput";
10-
11-
type SearchMode = "ai" | "text";
128

139
export function LogsSearchInput() {
1410
const location = useOptimisticLocation();
@@ -19,7 +15,6 @@ export function LogsSearchInput() {
1915
const searchParams = new URLSearchParams(location.search);
2016
const initialSearch = searchParams.get("search") ?? "";
2117

22-
const [mode, setMode] = useState<SearchMode>("text");
2318
const [text, setText] = useState(initialSearch);
2419
const [isFocused, setIsFocused] = useState(false);
2520

@@ -54,81 +49,47 @@ export function LogsSearchInput() {
5449
navigate(`${location.pathname}?${params.toString()}`, { replace: true });
5550
}, [location.pathname, location.search, navigate]);
5651

57-
const toggleMode = useCallback(() => {
58-
// Clear text search when switching modes
59-
if (mode === "text" && text.trim()) {
60-
handleClear();
61-
}
62-
setMode((prev) => (prev === "ai" ? "text" : "ai"));
63-
}, [mode, text, handleClear]);
64-
6552
return (
6653
<div className="flex items-center gap-1">
67-
{/* Mode toggle button */}
68-
<button
69-
type="button"
70-
onClick={toggleMode}
71-
className={cn(
72-
"flex size-6 items-center justify-center rounded border transition-colors",
73-
mode === "ai"
74-
? "border-indigo-500/50 bg-indigo-500/10 text-indigo-400 hover:bg-indigo-500/20"
75-
: "border-charcoal-700 bg-charcoal-750 text-text-dimmed hover:bg-charcoal-700 hover:text-text-bright"
76-
)}
77-
title={mode === "ai" ? "Switch to text search" : "Switch to AI search"}
78-
>
79-
{mode === "ai" ? (
80-
<AISparkleIcon className="size-3.5" />
81-
) : (
82-
<MagnifyingGlassIcon className="size-3.5" />
83-
)}
84-
</button>
85-
86-
{/* Show AI or text search based on mode */}
87-
{mode === "ai" ? (
88-
<AIFilterInput />
89-
) : (
90-
<div className="flex items-center gap-1">
91-
<div className="relative h-6 min-w-52">
92-
<Input
93-
type="text"
94-
ref={inputRef}
95-
variant="secondary-small"
96-
placeholder="Search messages…"
97-
value={text}
98-
onChange={(e) => setText(e.target.value)}
99-
fullWidth
100-
className={cn(isFocused && "placeholder:text-text-dimmed/70")}
101-
onKeyDown={(e) => {
102-
if (e.key === "Enter") {
103-
e.preventDefault();
104-
handleSubmit();
105-
}
106-
if (e.key === "Escape") {
107-
e.currentTarget.blur();
108-
}
109-
}}
110-
onFocus={() => setIsFocused(true)}
111-
onBlur={() => setIsFocused(false)}
112-
icon={<MagnifyingGlassIcon className="size-4" />}
113-
accessory={
114-
text.length > 0 ? (
115-
<ShortcutKey shortcut={{ key: "enter" }} variant="small" />
116-
) : undefined
117-
}
118-
/>
119-
</div>
54+
<div className="relative h-6 min-w-52">
55+
<Input
56+
type="text"
57+
ref={inputRef}
58+
variant="secondary-small"
59+
placeholder="Search logs…"
60+
value={text}
61+
onChange={(e) => setText(e.target.value)}
62+
fullWidth
63+
className={cn(isFocused && "placeholder:text-text-dimmed/70")}
64+
onKeyDown={(e) => {
65+
if (e.key === "Enter") {
66+
e.preventDefault();
67+
handleSubmit();
68+
}
69+
if (e.key === "Escape") {
70+
e.currentTarget.blur();
71+
}
72+
}}
73+
onFocus={() => setIsFocused(true)}
74+
onBlur={() => setIsFocused(false)}
75+
icon={<MagnifyingGlassIcon className="size-4" />}
76+
accessory={
77+
text.length > 0 ? (
78+
<ShortcutKey shortcut={{ key: "enter" }} variant="small" />
79+
) : undefined
80+
}
81+
/>
82+
</div>
12083

121-
{text.length > 0 && (
122-
<button
123-
type="button"
124-
onClick={handleClear}
125-
className="flex size-6 items-center justify-center rounded text-text-dimmed hover:bg-charcoal-700 hover:text-text-bright"
126-
title="Clear search"
127-
>
128-
<XMarkIcon className="size-4" />
129-
</button>
130-
)}
131-
</div>
84+
{text.length > 0 && (
85+
<button
86+
type="button"
87+
onClick={handleClear}
88+
className="flex size-6 items-center justify-center rounded text-text-dimmed hover:bg-charcoal-700 hover:text-text-bright"
89+
title="Clear search"
90+
>
91+
<XMarkIcon className="size-4" />
92+
</button>
13293
)}
13394
</div>
13495
);

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

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { v3RunSpanPath } from "~/utils/pathBuilder";
1212
import { DateTime } from "../primitives/DateTime";
1313
import { Paragraph } from "../primitives/Paragraph";
1414
import { Spinner } from "../primitives/Spinner";
15-
import { SimpleTooltip } from "../primitives/Tooltip";
15+
import { TruncatedCopyableValue } from "../primitives/TruncatedCopyableValue";
1616
import {
1717
Table,
1818
TableBlankRow,
@@ -209,21 +209,10 @@ export function LogsTable({
209209
>
210210
<DateTime date={log.startTime} />
211211
</TableCell>
212-
<TableCell>
213-
<SimpleTooltip
214-
content="Jump to run"
215-
disableHoverableContent
216-
button={
217-
<Link
218-
to={runPath}
219-
className="flex items-center gap-1 text-blue-500 hover:text-blue-400"
220-
>
221-
{log.runId.slice(0, 12)}
222-
</Link>
223-
}
224-
/>
212+
<TableCell className="min-w-24">
213+
<TruncatedCopyableValue value={log.runId} />
225214
</TableCell>
226-
<TableCell onClick={handleRowClick} hasAction>
215+
<TableCell className="min-w-32" onClick={handleRowClick} hasAction>
227216
<span className="font-mono text-xs">{log.taskIdentifier}</span>
228217
</TableCell>
229218
<TableCell onClick={handleRowClick} hasAction>

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

Lines changed: 0 additions & 55 deletions
This file was deleted.

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

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export type LogsListOptions = {
4242
levels?: LogLevel[];
4343
// search
4444
search?: string;
45+
includeDebugLogs?: boolean;
4546
// pagination
4647
direction?: Direction;
4748
cursor?: string;
@@ -155,6 +156,7 @@ export class LogsListPresenter {
155156
direction = "forward",
156157
cursor,
157158
pageSize = DEFAULT_PAGE_SIZE,
159+
includeDebugLogs = true,
158160
}: LogsListOptions
159161
) {
160162
// Get time values from raw values (including default period)
@@ -381,11 +383,16 @@ export class LogsListPresenter {
381383
queryBuilder.where("run_id IN {runIds: Array(String)}", { runIds });
382384
}
383385

384-
// Case-insensitive contains message search using ilike
386+
// Case-insensitive search in message and status fields
385387
if (search && search.trim() !== "") {
386-
queryBuilder.where("message ilike {searchPattern: String}", {
387-
searchPattern: `%${search.trim()}%`,
388-
});
388+
const searchTerm = search.trim();
389+
queryBuilder.where(
390+
"(message ilike {searchPattern: String} OR status = {statusTerm: String})",
391+
{
392+
searchPattern: `%${searchTerm}%`,
393+
statusTerm: searchTerm.toUpperCase(),
394+
}
395+
);
389396
}
390397

391398
// Level filter (map display levels to ClickHouse kinds)
@@ -394,6 +401,22 @@ export class LogsListPresenter {
394401
queryBuilder.where("kind IN {kinds: Array(String)}", { kinds });
395402
}
396403

404+
// Exclude DEBUG logs if not included
405+
if (includeDebugLogs === false) {
406+
queryBuilder.where("kind NOT IN {debugKinds: Array(String)}", {
407+
debugKinds: ["DEBUG_EVENT", "LOG_DEBUG"],
408+
});
409+
}
410+
411+
// Exclude TRACE logs with PARTIAL status
412+
// const traceKinds = ["SPAN", "ANCESTOR_OVERRIDE", "SPAN_EVENT"];
413+
// queryBuilder.where(
414+
// "NOT (kind IN {traceKinds: Array(String)} AND status = 'PARTIAL')",
415+
// { traceKinds }
416+
// );
417+
queryBuilder.where("NOT (kind = 'SPAN' AND status = 'PARTIAL')");
418+
419+
397420
// Cursor pagination
398421
const decodedCursor = cursor ? decodeCursor(cursor) : null;
399422
if (decodedCursor) {

0 commit comments

Comments
 (0)