diff --git a/skyvern-frontend/src/App.tsx b/skyvern-frontend/src/App.tsx index ea11570c..f193f16b 100644 --- a/skyvern-frontend/src/App.tsx +++ b/skyvern-frontend/src/App.tsx @@ -5,30 +5,37 @@ import { QueryClientProvider } from "@tanstack/react-query"; import { queryClient } from "./api/QueryClient"; import { PostHogProvider } from "posthog-js/react"; +import { LoggingContext, loggingStub } from "@/store/LoggingContext"; import { UserContext } from "@/store/UserContext"; const postHogOptions = { api_host: "https://app.posthog.com", }; +const getLogging = () => { + return loggingStub; +}; + const getUser = () => { return null; }; function App() { return ( - - - - - - - - - + + + + + + + + + + + ); } diff --git a/skyvern-frontend/src/hooks/useLogging.ts b/skyvern-frontend/src/hooks/useLogging.ts new file mode 100644 index 00000000..7ddaaebd --- /dev/null +++ b/skyvern-frontend/src/hooks/useLogging.ts @@ -0,0 +1,9 @@ +import { LoggingContext } from "@/store/LoggingContext"; +import { useContext } from "react"; + +function useLogging() { + const getLogging = useContext(LoggingContext); + return getLogging(); +} + +export { useLogging }; diff --git a/skyvern-frontend/src/routes/workflows/debugger/DebuggerRun.tsx b/skyvern-frontend/src/routes/workflows/debugger/DebuggerRun.tsx index 97821c45..bc090a0c 100644 --- a/skyvern-frontend/src/routes/workflows/debugger/DebuggerRun.tsx +++ b/skyvern-frontend/src/routes/workflows/debugger/DebuggerRun.tsx @@ -6,13 +6,13 @@ function DebuggerRun() { const workflowFailureReason = workflowRun?.failure_reason ? (
-
Workflow Failure Reason
+
Run Failure Reason
{workflowRun.failure_reason}
) : null; diff --git a/skyvern-frontend/src/routes/workflows/editor/nodes/components/NodeHeader.tsx b/skyvern-frontend/src/routes/workflows/editor/nodes/components/NodeHeader.tsx index cdbb228f..3dd03ca5 100644 --- a/skyvern-frontend/src/routes/workflows/editor/nodes/components/NodeHeader.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/nodes/components/NodeHeader.tsx @@ -8,6 +8,7 @@ import { getClient } from "@/api/AxiosClient"; import { ProxyLocation } from "@/api/types"; import { Timer } from "@/components/Timer"; import { toast } from "@/components/ui/use-toast"; +import { useLogging } from "@/hooks/useLogging"; import { useCredentialGetter } from "@/hooks/useCredentialGetter"; import { useNodeLabelChangeHandler } from "@/routes/workflows/hooks/useLabelChangeHandler"; @@ -131,6 +132,7 @@ function NodeHeader({ totpUrl, type, }: Props) { + const log = useLogging(); const { blockLabel: urlBlockLabel, workflowPermanentId, @@ -214,7 +216,7 @@ function NodeHeader({ await saveWorkflow.mutateAsync(); if (!workflowPermanentId) { - console.error("There is no workflowPermanentId"); + log.error("Run block: there is no workflowPermanentId"); toast({ variant: "destructive", title: "Failed to start workflow block run", @@ -224,7 +226,7 @@ function NodeHeader({ } if (!debugSession) { - console.error("There is no debug session, yet"); + log.error("Run block: there is no debug session, yet"); toast({ variant: "destructive", title: "Failed to start workflow block run", @@ -263,6 +265,12 @@ function NodeHeader({ }); if (!body) { + log.error("Run block: could not construct run payload", { + workflowPermanentId, + blockLabel, + debugSessionId: debugSession.debug_session_id, + browserSessionId: debugSession.browser_session_id, + }); toast({ variant: "destructive", title: "Failed to start workflow block run", @@ -271,6 +279,13 @@ function NodeHeader({ return; } + log.info("Run block: sending run payload", { + workflowPermanentId, + blockLabel, + debugSessionId: debugSession.debug_session_id, + browserSessionId: debugSession.browser_session_id, + }); + return await client.post( "/run/workflows/blocks", body, @@ -278,7 +293,12 @@ function NodeHeader({ }, onSuccess: (response) => { if (!response) { - console.error("No response"); + log.error("Run block: no response", { + workflowPermanentId, + blockLabel, + debugSessionId: debugSession?.debug_session_id, + browserSessionId: debugSession?.browser_session_id, + }); toast({ variant: "destructive", title: "Failed to start workflow block run", @@ -287,6 +307,14 @@ function NodeHeader({ return; } + log.info("Run block: run started", { + workflowPermanentId, + blockLabel, + debugSessionId: debugSession?.debug_session_id, + browserSessionId: debugSession?.browser_session_id, + runId: response.data.run_id, + }); + toast({ variant: "success", title: "Workflow block run started", @@ -299,6 +327,13 @@ function NodeHeader({ }, onError: (error: AxiosError) => { const detail = (error.response?.data as { detail?: string })?.detail; + log.error("Run block: error", { + workflowPermanentId, + blockLabel, + debugSessionId: debugSession?.debug_session_id, + browserSessionId: debugSession?.browser_session_id, + error, + }); toast({ variant: "destructive", title: "Failed to start workflow block run", @@ -310,7 +345,10 @@ function NodeHeader({ const cancelBlock = useMutation({ mutationFn: async () => { if (!debugSession) { - console.error("Missing debug session"); + log.error("Cancel block: missing debug session", { + workflowPermanentId, + blockLabel, + }); toast({ variant: "destructive", title: "Failed to cancel workflow block run", @@ -326,6 +364,12 @@ function NodeHeader({ .then((response) => response.data); }, onSuccess: () => { + log.info("Cancel block: canceled", { + workflowPermanentId, + blockLabel, + debugSessionId: debugSession?.debug_session_id, + browserSessionId: debugSession?.browser_session_id, + }); toast({ variant: "success", title: "Workflow Canceled", @@ -333,6 +377,13 @@ function NodeHeader({ }); }, onError: (error) => { + log.error("Cancel block: error", { + workflowPermanentId, + blockLabel, + debugSessionId: debugSession?.debug_session_id, + browserSessionId: debugSession?.browser_session_id, + error, + }); toast({ variant: "destructive", title: "Error", diff --git a/skyvern-frontend/src/store/LoggingContext.ts b/skyvern-frontend/src/store/LoggingContext.ts new file mode 100644 index 00000000..5ca26187 --- /dev/null +++ b/skyvern-frontend/src/store/LoggingContext.ts @@ -0,0 +1,26 @@ +import { createContext } from "react"; + +type LogFn = (message: string, data?: Record) => void; + +interface Logging { + info: LogFn; + warn: LogFn; + error: LogFn; +} + +// make this a stub of LogFn that does nothing + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const noop: LogFn = (..._: Parameters) => {}; + +const stub: Logging = { + info: noop, + warn: noop, + error: noop, +}; + +type GetLogging = () => Logging; + +const LoggingContext = createContext(() => stub); + +export { LoggingContext, stub as loggingStub };