Skip to content

Commit

Permalink
feat(ceremony): ingest errors
Browse files Browse the repository at this point in the history
  • Loading branch information
Swepool committed Oct 2, 2024
1 parent 42698e1 commit 3756af9
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 4 deletions.
9 changes: 9 additions & 0 deletions ceremony/src/hooks.client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { generateUserErrorMessage, sendSvelteErrorLog } from "$lib/utils/error"
import type { HandleClientError } from "@sveltejs/kit"

export const handleError = (async ({ error, event, message, status }) => {
const errorId = await sendSvelteErrorLog({ error, event, message, status }, "client")
return {
message: generateUserErrorMessage(errorId)
}
}) satisfies HandleClientError
1 change: 1 addition & 0 deletions ceremony/src/lib/constants/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const AXIOM_KEY = "xaat-c2ba1f52-0af4-4814-81d1-996c285912c8"
3 changes: 2 additions & 1 deletion ceremony/src/lib/utils/axiom.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Axiom } from "@axiomhq/js"
import { AXIOM_KEY } from "$lib/constants"

export const axiom = new Axiom({
token: import.meta.env.VITE_AXIOM_KEY,
token: AXIOM_KEY,
orgId: "union-qaca",
onError: err => {
console.error("AXIOM ERROR:", err)
Expand Down
102 changes: 102 additions & 0 deletions ceremony/src/lib/utils/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { browser } from "$app/environment"
import { axiom } from "$lib/utils/axiom.ts"

const browserErrorSessionId = browser ? crypto.randomUUID() : undefined

export const generateUserErrorMessage = (errorId: string) => {
return `An unexpected error occurred, please try again! Error ID: "${errorId}"`
}

export const sendSvelteErrorLog = async (svelteError: SvelteError, type: "client") => {
return await sendErrorLog({ svelte: svelteError }, type)
}

export const sendWindowErrorLog = async (event: Event) => {
const origin = event.target instanceof Window ? event.target.origin : undefined
const location = event.target instanceof Window ? event.target.location.href : undefined
const message = event instanceof ErrorEvent ? event.message : undefined
const stack = event instanceof ErrorEvent ? event.error?.stack : undefined
const windowEventError = {
origin,
location,
message,
stack,
type: event.type,
sessionId: browserErrorSessionId
}
return await sendErrorLog({ window: windowEventError }, "window")
}

export const sendWindowRejectionLog = async (event: PromiseRejectionEvent) => {
const origin = event.target instanceof Window ? event.target.origin : undefined
const location = event.target instanceof Window ? event.target.location.href : undefined
const windowEventError = {
origin,
location,
message: event.reason?.message,
stack: event.reason?.stack,
type: event.type,
sessionId: browserErrorSessionId
}
return await sendErrorLog({ window: windowEventError }, "window")
}

const sendErrorLog = async (detail: ErrorDetail, type: "client" | "window") => {
const errorId = crypto.randomUUID()
const jsonBody = JSON.stringify(
{
errorId,
type,
detail
},
errorJsonReplacer
)

axiom.ingest("errors", [
{
errorId,
type,
detail
},
errorJsonReplacer
])

return errorId
}

const errorJsonReplacer = (key: string, value: unknown) => {
try {
if (key === "error" && !!value && typeof value === "object") {
const sanitizedError: { [k: string]: unknown } = {}
const errorValue = value as Record<string, unknown>
for (const propertyName of Object.getOwnPropertyNames(errorValue)) {
sanitizedError[propertyName] = errorValue[propertyName]
}
return sanitizedError
}
} catch (e) {
console.error("Failed to sanitize error", e)
}
return value
}

type SvelteError = {
error: unknown
event: unknown
message: string
status: number
}

type WindowEventError = {
origin: string | undefined
location: string | undefined
message: unknown | undefined
stack: unknown | undefined
type: string
sessionId: string | undefined
}

type ErrorDetail = {
svelte?: SvelteError
window?: WindowEventError
}
25 changes: 22 additions & 3 deletions ceremony/src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ import { checkAuth } from "$lib/state/session.svelte.ts"
import Terminal from "$lib/components/Terminal/index.svelte"
import { start } from "$lib/client"
import Timer from "$lib/components/Terminal/Timer.svelte"
import "../styles/tailwind.css"
import { onMount } from "svelte"
import { axiom } from "$lib/utils/axiom.ts"
import {
generateUserErrorMessage,
sendWindowErrorLog,
sendWindowRejectionLog
} from "$lib/utils/error.ts"
import "../styles/tailwind.css"
let { children } = $props()
Expand Down Expand Up @@ -53,14 +58,28 @@ $effect(() => {
let showBootSequence = $state(localStorage?.getItem("ceremony:show-boot-sequence") !== "false")
let bootSequenceVideoElement = $state<HTMLVideoElement | null>(null)
onMount(() => bootSequenceVideoElement?.play())
onMount(() => {
bootSequenceVideoElement?.play()
})
const hideBootSequenceVideo = () => {
showBootSequence = false
localStorage?.setItem("ceremony:show-boot-sequence", "false")
}
const handleRejection = async (e: PromiseRejectionEvent) => {
const errorId = await sendWindowRejectionLog(e)
console.error(generateUserErrorMessage(errorId))
}
const handleError = async (e: Event) => {
const errorId = await sendWindowErrorLog(e)
console.error(generateUserErrorMessage(errorId))
}
</script>

<svelte:window on:error={handleError} on:unhandledrejection={handleRejection} />

{#if showBootSequence}
<video
muted
Expand Down
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"caseSensitive": false,
"dictionaries": ["en_US", "companies", "softwareTerms", "go", "union"],
"ignorePaths": [
"ceremony/src/lib/constants/*",
"**/*.splinecode",
"**/*.graphql",
"light-clients/ethereum-light-client/src/test/**",
Expand Down

0 comments on commit 3756af9

Please sign in to comment.