Skip to content

Commit 6af6a9e

Browse files
committed
Show ignore reasons
1 parent e91c887 commit 6af6a9e

File tree

2 files changed

+125
-2
lines changed

2 files changed

+125
-2
lines changed

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

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,14 @@ export type ErrorGroupState = {
6666
resolvedAt: Date | null;
6767
resolvedInVersion: string | null;
6868
resolvedBy: string | null;
69+
ignoredAt: Date | null;
6970
ignoredUntil: Date | null;
7071
ignoredReason: string | null;
7172
ignoredByUserId: string | null;
73+
ignoredByUserDisplayName: string | null;
7274
ignoredUntilOccurrenceRate: number | null;
7375
ignoredUntilTotalOccurrences: number | null;
76+
ignoredAtOccurrenceCount: number | null;
7477
};
7578

7679
export type ErrorGroupSummary = {
@@ -151,11 +154,14 @@ export class ErrorGroupPresenter extends BasePresenter {
151154
resolvedAt: null,
152155
resolvedInVersion: null,
153156
resolvedBy: null,
157+
ignoredAt: null,
154158
ignoredUntil: null,
155159
ignoredReason: null,
156160
ignoredByUserId: null,
161+
ignoredByUserDisplayName: null,
157162
ignoredUntilOccurrenceRate: null,
158163
ignoredUntilTotalOccurrences: null,
164+
ignoredAtOccurrenceCount: null,
159165
};
160166
}
161167

@@ -329,15 +335,47 @@ export class ErrorGroupPresenter extends BasePresenter {
329335
resolvedAt: true,
330336
resolvedInVersion: true,
331337
resolvedBy: true,
338+
ignoredAt: true,
332339
ignoredUntil: true,
333340
ignoredReason: true,
334341
ignoredByUserId: true,
335342
ignoredUntilOccurrenceRate: true,
336343
ignoredUntilTotalOccurrences: true,
344+
ignoredAtOccurrenceCount: true,
337345
},
338346
});
339347

340-
return row;
348+
if (!row) {
349+
return null;
350+
}
351+
352+
let ignoredByUserDisplayName: string | null = null;
353+
if (row.ignoredByUserId) {
354+
const user = await this.replica.user.findUnique({
355+
where: { id: row.ignoredByUserId },
356+
select: { displayName: true, name: true, email: true },
357+
});
358+
if (user) {
359+
ignoredByUserDisplayName = user.displayName ?? user.name ?? user.email;
360+
}
361+
}
362+
363+
return {
364+
status: row.status,
365+
resolvedAt: row.resolvedAt,
366+
resolvedInVersion: row.resolvedInVersion,
367+
resolvedBy: row.resolvedBy,
368+
ignoredAt: row.ignoredAt,
369+
ignoredUntil: row.ignoredUntil,
370+
ignoredReason: row.ignoredReason,
371+
ignoredByUserId: row.ignoredByUserId,
372+
ignoredByUserDisplayName,
373+
ignoredUntilOccurrenceRate: row.ignoredUntilOccurrenceRate,
374+
ignoredUntilTotalOccurrences: row.ignoredUntilTotalOccurrences,
375+
ignoredAtOccurrenceCount: row.ignoredAtOccurrenceCount
376+
? Number(row.ignoredAtOccurrenceCount)
377+
: null,
378+
};
341379
}
342380

343381
private async getRunList(

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

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { Spinner } from "~/components/primitives/Spinner";
3232
import { Paragraph } from "~/components/primitives/Paragraph";
3333
import { Callout } from "~/components/primitives/Callout";
3434
import { Header1, Header2, Header3 } from "~/components/primitives/Headers";
35-
import { formatDistanceToNow } from "date-fns";
35+
import { formatDistanceToNow, isPast } from "date-fns";
3636
import { formatNumberCompact } from "~/utils/numberFormatter";
3737
import * as Property from "~/components/primitives/PropertyTable";
3838
import { TaskRunsTable } from "~/components/runs/v3/TaskRunsTable";
@@ -463,6 +463,8 @@ function ErrorGroupDetail({
463463
)}
464464
</Property.Table>
465465
</div>
466+
467+
<IgnoredDetails state={errorGroup.state} totalOccurrences={errorGroup.count} />
466468
</div>
467469

468470
{/* Activity chart */}
@@ -563,6 +565,89 @@ function StatusBadge({ status }: { status: ErrorGroupState["status"] }) {
563565
);
564566
}
565567

568+
function IgnoredDetails({
569+
state,
570+
totalOccurrences,
571+
}: {
572+
state: ErrorGroupState;
573+
totalOccurrences: number;
574+
}) {
575+
if (state.status !== "IGNORED") {
576+
return null;
577+
}
578+
579+
const hasConditions =
580+
state.ignoredUntil || state.ignoredUntilOccurrenceRate || state.ignoredUntilTotalOccurrences;
581+
582+
const ignoredForever = !hasConditions;
583+
584+
const occurrencesSinceIgnore =
585+
state.ignoredUntilTotalOccurrences && state.ignoredAtOccurrenceCount !== null
586+
? totalOccurrences - state.ignoredAtOccurrenceCount
587+
: null;
588+
589+
return (
590+
<div className="flex flex-col gap-1.5 rounded border border-text-dimmed/20 bg-text-dimmed/5 px-3 py-2.5 text-sm">
591+
<div className="flex items-center gap-2">
592+
<span className="font-medium text-text-bright">
593+
{ignoredForever ? "Ignored permanently" : "Ignored with conditions"}
594+
</span>
595+
{state.ignoredByUserDisplayName && (
596+
<span className="text-text-dimmed">by {state.ignoredByUserDisplayName}</span>
597+
)}
598+
{state.ignoredAt && (
599+
<span className="text-text-dimmed">
600+
<RelativeDateTime date={state.ignoredAt} />
601+
</span>
602+
)}
603+
</div>
604+
605+
{state.ignoredReason && (
606+
<div className="text-text-dimmed">
607+
Reason: <span className="text-text-bright">{state.ignoredReason}</span>
608+
</div>
609+
)}
610+
611+
{hasConditions && (
612+
<div className="flex flex-col gap-0.5 text-xs text-text-dimmed">
613+
<span className="font-medium text-text-bright/80">Will unignore when:</span>
614+
<ul className="list-inside list-disc space-y-0.5 pl-1">
615+
{state.ignoredUntil && (
616+
<li>
617+
Time expires:{" "}
618+
<span className="text-text-bright">
619+
<DateTime date={state.ignoredUntil} />
620+
</span>
621+
{isPast(state.ignoredUntil) && <span className="ml-1 text-warning">(expired)</span>}
622+
</li>
623+
)}
624+
{state.ignoredUntilOccurrenceRate !== null && state.ignoredUntilOccurrenceRate > 0 && (
625+
<li>
626+
Occurrence rate exceeds{" "}
627+
<span className="text-text-bright">{state.ignoredUntilOccurrenceRate}/min</span>
628+
</li>
629+
)}
630+
{state.ignoredUntilTotalOccurrences !== null &&
631+
state.ignoredUntilTotalOccurrences > 0 && (
632+
<li>
633+
Total occurrences exceed{" "}
634+
<span className="text-text-bright">
635+
{state.ignoredUntilTotalOccurrences.toLocaleString()}
636+
</span>
637+
{occurrencesSinceIgnore !== null && (
638+
<span className="ml-1 text-text-dimmed">
639+
({occurrencesSinceIgnore.toLocaleString()} since ignored)
640+
</span>
641+
)}
642+
</li>
643+
)}
644+
</ul>
645+
</div>
646+
)}
647+
</div>
648+
);
649+
}
650+
566651
function ErrorGroupActionButtons({
567652
state,
568653
taskIdentifier,

0 commit comments

Comments
 (0)