Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(engine+ui): Improve error messages [1/N] #353

Merged
merged 5 commits into from
Aug 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { ImperativePanelHandle } from "react-resizable-panels"

import { useWorkflowExecutions } from "@/lib/hooks"
import { cn } from "@/lib/utils"
import { Badge } from "@/components/ui/badge"
import {
ResizableHandle,
ResizablePanel,
Expand All @@ -20,6 +19,8 @@ import { AlertNotification } from "@/components/notifications"

import "react18-json-view/src/style.css"

import { History, ListVideoIcon } from "lucide-react"

import { WorkflowExecutionEventDetailView } from "@/components/executions/event-details"
import { WorkflowExecutionEventHistory } from "@/components/executions/event-history"
import { WorkflowExecutionNav } from "@/components/executions/nav"
Expand Down Expand Up @@ -113,7 +114,10 @@ function WorkflowExecutionsViewLayout({
className={cn("flex h-full flex-col p-2", isCollapsed && "min-w-14")}
>
<ScrollArea className="overflow-auto">
<SectionHead text="Workflow Executions" />
<SectionHead
text="Workflow Runs"
icon={<ListVideoIcon className="mr-2 size-4" strokeWidth={2} />}
/>
<WorkflowExecutionNav
executions={workflowExecutions}
executionId={executionId}
Expand All @@ -131,7 +135,10 @@ function WorkflowExecutionsViewLayout({
className={cn("flex h-full flex-col p-2", isCollapsed && "min-w-14")}
>
<ScrollArea className="overflow-auto">
<SectionHead text="Event History" />
<SectionHead
text="Event History"
icon={<History className="mr-2 size-4" strokeWidth={2} />}
/>
{executionId ? (
<WorkflowExecutionEventHistory
executionId={executionId}
Expand Down Expand Up @@ -162,10 +169,11 @@ function WorkflowExecutionsViewLayout({
)
}

function SectionHead({ text }: { text: string }) {
function SectionHead({ icon, text }: { icon: React.ReactNode; text: string }) {
return (
<span className="flex w-full justify-start px-2 py-1 text-center text-xs font-normal text-muted-foreground/80">
<Badge variant="secondary">{text}</Badge>
</span>
<div className="flex w-full justify-start p-2 text-center text-xs font-semibold">
{icon}
<span>{text}</span>
</div>
)
}
2 changes: 1 addition & 1 deletion frontend/src/app/workspaces/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default function WorkspaceLayout({
<div className="no-scrollbar flex h-screen max-h-screen flex-col overflow-hidden">
{/* DynamicNavbar needs a WorkflowProvider and a WorkspaceProvider */}
<DynamicNavbar />
<div className="flex-grow overflow-auto">{children}</div>
<div className="grow overflow-auto">{children}</div>
</div>
</WorkflowProvider>
</WorkspaceProvider>
Expand Down
111 changes: 71 additions & 40 deletions frontend/src/components/executions/event-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
import { cn } from "@/lib/utils"
import { Badge } from "@/components/ui/badge"
import { Label } from "@/components/ui/label"
import { Switch } from "@/components/ui/switch"
import { GenericWorkflowIcon, getIcon } from "@/components/icons"

/**
Expand Down Expand Up @@ -70,16 +71,11 @@ export function WorkflowExecutionEventDetailView({
</AccordionTrigger>
<AccordionContent>
<div className="my-4 flex flex-col space-y-8 px-4">
<div className="rounded-md border p-4 shadow-md">
<JsonView
collapsed
displaySize
enableClipboard
src={event.failure}
className="text-sm"
theme="atom"
/>
</div>
<CodeBlock title="Message">{event.failure.message}</CodeBlock>
<CodeBlock title="Stack Trace">
{event.failure.stack_trace}
</CodeBlock>
<JsonViewWithControls src={event.failure} />
</div>
</AccordionContent>
</AccordionItem>
Expand All @@ -94,16 +90,9 @@ export function WorkflowExecutionEventDetailView({
</AccordionTrigger>
<AccordionContent>
<div className="my-4 flex flex-col space-y-8 px-4">
<div className="rounded-md border p-4 shadow-md">
<JsonView
collapsed
displaySize
enableClipboard
src={(event.result as Record<string, unknown>) ?? {}}
className="text-sm"
theme="atom"
/>
</div>
<JsonViewWithControls
src={(event.result as Record<string, unknown>) ?? {}}
/>
</div>
</AccordionContent>
</AccordionItem>
Expand All @@ -118,16 +107,7 @@ export function WorkflowExecutionEventDetailView({
</AccordionTrigger>
<AccordionContent>
<div className="my-4 flex flex-col space-y-8 px-4">
<div className="rounded-md border p-4 shadow-md">
<JsonView
collapsed
displaySize
enableClipboard
src={event?.event_group?.action_input}
className="text-sm"
theme="atom"
/>
</div>
<JsonViewWithControls src={event?.event_group?.action_input} />
</div>
</AccordionContent>
</AccordionItem>
Expand All @@ -143,16 +123,7 @@ export function WorkflowExecutionEventDetailView({
</AccordionTrigger>
<AccordionContent>
<div className="my-4 flex flex-col space-y-8 px-4">
<div className="rounded-md border p-4 shadow-md">
<JsonView
collapsed
displaySize
enableClipboard
src={event.event_group.action_input}
className="text-sm"
theme="atom"
/>
</div>
<JsonViewWithControls src={event.event_group.action_input} />
</div>
</AccordionContent>
</AccordionItem>
Expand Down Expand Up @@ -375,3 +346,63 @@ function isDSLRunArgs(actionInput: unknown): actionInput is DSLRunArgs {
(actionInput as DSLRunArgs).wf_id !== undefined
)
}

function CodeBlock({
title,
children,
}: {
title?: string
children: React.ReactNode
}) {
return (
<div className="space-y-2">
{title && (
<span className="text-xs font-semibold text-foreground/50">
{title}
</span>
)}
<pre className="flex flex-col rounded-md border bg-muted-foreground/5 p-4 font-mono text-foreground/70">
{children}
</pre>
</div>
)
}

function JsonViewWithControls({
src,
title = "JSON",
}: {
src: unknown
title?: string
}): JSX.Element {
const [isExpanded, setIsExpanded] = React.useState(false)
return (
<div className="space-y-2">
<div className="flex w-full items-center gap-4">
<span className="text-xs font-semibold text-foreground/50">
{title}
</span>
<div className="flex items-center gap-2">
<Switch
checked={isExpanded}
onCheckedChange={setIsExpanded}
className="data-[state=checked]:bg-muted-foreground"
/>
<p className="text-xs text-foreground/70">
{isExpanded ? "Collapse" : "Expand"}
</p>
</div>
</div>
<div className="rounded-md border bg-muted-foreground/5 p-4">
<JsonView
collapsed={!isExpanded}
displaySize
enableClipboard
src={src}
className="text-sm"
theme="atom"
/>
</div>
</div>
)
}
4 changes: 3 additions & 1 deletion tracecat/dsl/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,9 @@ async def run_udf(input: UDFActionInput) -> Any:
except TracecatException as e:
err_type = e.__class__.__name__
msg = str(e)
act_logger.error(f"{err_type} occurred: {msg}", error=e, detail=e.detail)
act_logger.error(
"Application exception occurred", error=msg, detail=e.detail
)
raise ApplicationError(
msg, e.detail, non_retryable=True, type=err_type
) from e
Expand Down
4 changes: 3 additions & 1 deletion tracecat/types/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
through FastAPI exception handlers, which match the exception type.
"""

from typing import Any


class TracecatException(Exception):
"""Tracecat generic user-facing exception"""

def __init__(self, *args, detail=None, **kwargs):
def __init__(self, *args, detail: Any | None = None, **kwargs):
super().__init__(*args, **kwargs)
self.detail = detail

Expand Down
Loading