Skip to content

Commit c8686b5

Browse files
mpcgridsamejr
andauthored
feat: tri-6738 Create aggregated logs page (#2862)
Closes #<issue> ## ✅ Checklist - [x] I have followed every step in the [contributing guide](https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md) - [x] The PR title follows the convention. - [x] I ran and tested the code works --- ## Testing - Verified log detail view displays correctly with message, metadata, and attributes - Tested search highlighting functionality in log messages (escapes special regex characters) - Confirmed tabs (Details/Run) switch properly with keyboard shortcuts (d/r) - Verified run information loads via async fetcher in Run tab - Tested close button and Escape key for dismissing the panel - Verified log details display correct information: level badges, kind badges, timestamps, trace IDs, span IDs - Confirmed links to parent spans and run pages work correctly - Tested with various log levels (ERROR, WARN, INFO, DEBUG, TRACE) and kinds (SPAN, SPAN_EVENT, LOG_*) - Verified admin-only fields display correctly when user has admin access - Tested data loading states and error states (log not found, run not found) --- ## Changelog Created new Logs page. The information shown is gathered from the spans from each run. The feature supports all run filters with two new filters for level and logs text search. --- ## Screenshots <img width="2059" height="1196" alt="Logs page preview" src="https://github.com/user-attachments/assets/70b667b4-98cc-4728-855a-2766dd5c1aa5" /> 💯 --------- Co-authored-by: James Ritchie <[email protected]>
1 parent dfb46d8 commit c8686b5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+3585
-40
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
export function LogsIcon({ className }: { className?: string }) {
2+
return (
3+
<svg className={className} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
4+
<circle cx="4" cy="10" r="1" fill="currentColor" />
5+
<circle cx="4" cy="5" r="1" fill="currentColor" />
6+
<circle cx="4" cy="14" r="1" fill="currentColor" />
7+
<circle cx="4" cy="19" r="1" fill="currentColor" />
8+
<path
9+
d="M7 9.75L10 9.75"
10+
stroke="currentColor"
11+
strokeWidth="2"
12+
strokeLinecap="round"
13+
strokeLinejoin="round"
14+
/>
15+
<path
16+
d="M7 5L10 5"
17+
stroke="currentColor"
18+
strokeWidth="2"
19+
strokeLinecap="round"
20+
strokeLinejoin="round"
21+
/>
22+
<path
23+
d="M7 14.25H10"
24+
stroke="currentColor"
25+
strokeWidth="2"
26+
strokeLinecap="round"
27+
strokeLinejoin="round"
28+
/>
29+
<path
30+
d="M7 19H10"
31+
stroke="currentColor"
32+
strokeWidth="2"
33+
strokeLinecap="round"
34+
strokeLinejoin="round"
35+
/>
36+
<path
37+
d="M13 5H20"
38+
stroke="currentColor"
39+
strokeWidth="2"
40+
strokeLinecap="round"
41+
strokeLinejoin="round"
42+
/>
43+
<path
44+
d="M13 9.75H20"
45+
stroke="currentColor"
46+
strokeWidth="2"
47+
strokeLinecap="round"
48+
strokeLinejoin="round"
49+
/>
50+
<path
51+
d="M13 14.25H20"
52+
stroke="currentColor"
53+
strokeWidth="2"
54+
strokeLinecap="round"
55+
strokeLinejoin="round"
56+
/>
57+
<path
58+
d="M13 19H20"
59+
stroke="currentColor"
60+
strokeWidth="2"
61+
strokeLinecap="round"
62+
strokeLinejoin="round"
63+
/>
64+
</svg>
65+
);
66+
}

apps/webapp/app/components/code/CodeBlock.tsx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Highlight, Prism } from "prism-react-renderer";
55
import { forwardRef, ReactNode, useCallback, useEffect, useState } from "react";
66
import { TextWrapIcon } from "~/assets/icons/TextWrapIcon";
77
import { cn } from "~/utils/cn";
8+
import { highlightSearchText } from "~/utils/logUtils";
89
import { Button } from "../primitives/Buttons";
910
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../primitives/Dialog";
1011
import { Paragraph } from "../primitives/Paragraph";
@@ -64,6 +65,9 @@ type CodeBlockProps = {
6465

6566
/** Whether to show the open in modal button */
6667
showOpenInModal?: boolean;
68+
69+
/** Search term to highlight in the code */
70+
searchTerm?: string;
6771
};
6872

6973
const dimAmount = 0.5;
@@ -202,6 +206,7 @@ export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
202206
showChrome = false,
203207
fileName,
204208
rowTitle,
209+
searchTerm,
205210
...props
206211
}: CodeBlockProps,
207212
ref
@@ -238,7 +243,7 @@ export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
238243
[code]
239244
);
240245

241-
code = code.trim();
246+
code = code?.trim() ?? "";
242247
const lineCount = code.split("\n").length;
243248
const maxLineWidth = lineCount.toString().length;
244249
let maxHeight: string | undefined = undefined;
@@ -340,6 +345,7 @@ export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
340345
className="px-2 py-3"
341346
preClassName="text-xs"
342347
isWrapped={isWrapped}
348+
searchTerm={searchTerm}
343349
/>
344350
) : (
345351
<div
@@ -360,7 +366,7 @@ export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
360366
)}
361367
dir="ltr"
362368
>
363-
{code}
369+
{highlightSearchText(code, searchTerm)}
364370
</pre>
365371
</div>
366372
)}
@@ -402,7 +408,7 @@ export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
402408
className="overflow-auto px-3 py-3 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600"
403409
>
404410
<pre className="relative mr-2 p-2 font-mono text-base leading-relaxed" dir="ltr">
405-
{code}
411+
{highlightSearchText(code, searchTerm)}
406412
</pre>
407413
</div>
408414
)}
@@ -451,6 +457,7 @@ type HighlightCodeProps = {
451457
className?: string;
452458
preClassName?: string;
453459
isWrapped: boolean;
460+
searchTerm?: string;
454461
};
455462

456463
function HighlightCode({
@@ -463,6 +470,7 @@ function HighlightCode({
463470
className,
464471
preClassName,
465472
isWrapped,
473+
searchTerm,
466474
}: HighlightCodeProps) {
467475
const [isLoaded, setIsLoaded] = useState(false);
468476

@@ -556,6 +564,10 @@ function HighlightCode({
556564
<div className="flex-1">
557565
{line.map((token, key) => {
558566
const tokenProps = getTokenProps({ token, key });
567+
568+
// Highlight search term matches in token
569+
const content = highlightSearchText(token.content, searchTerm);
570+
559571
return (
560572
<span
561573
key={key}
@@ -564,7 +576,9 @@ function HighlightCode({
564576
color: tokenProps?.style?.color as string,
565577
...tokenProps.style,
566578
}}
567-
/>
579+
>
580+
{content}
581+
</span>
568582
);
569583
})}
570584
</div>

0 commit comments

Comments
 (0)