mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
* o11y: mirror and sanitize breadcrumbs Mirror Sentry breadcrumbs as the basis for our own support logging. Also adds more sanitization to breadcrumbs. * feat(support form): toggle for attaching dashboard logs Add a toggle to the support form when the category is "Dashboard bug", to attach recent dashboard logs. Users can preview the attached logs and opt out. * feat(support links): dedicated support link component Add a new component for support links, which: - Uses the serializer for support link params to ensure serialization/deserialization pairs correctly - Snapshots breadcrumbs so the attached log on the support form will be cut off at the support link click (otherwise we will get support form actions cluttering up the log) * tests(support form): extend timeout on flaky test * Minor clean up * fix(support form): allow url to specifically indicate no specified project * minor nits * Fix tests * Fix tests --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
78 lines
2.3 KiB
TypeScript
78 lines
2.3 KiB
TypeScript
import * as Sentry from '@sentry/nextjs'
|
|
|
|
import { SupportCategories } from '@supabase/shared-types/out/constants'
|
|
import type {
|
|
GenerateAttachmentURLsData,
|
|
GenerateAttachmentURLsVariables,
|
|
} from 'data/support/generate-attachment-urls-mutation'
|
|
import { getMirroredBreadcrumbs, getOwnershipOfBreadcrumbSnapshot } from 'lib/breadcrumbs'
|
|
import { uuidv4 } from 'lib/helpers'
|
|
import { sanitizeArrayOfObjects } from 'lib/sanitize'
|
|
import { createSupportStorageClient } from './support-storage-client'
|
|
import type { ExtendedSupportCategories } from './Support.constants'
|
|
|
|
export type DashboardBreadcrumb = Sentry.Breadcrumb
|
|
|
|
export const DASHBOARD_LOG_BUCKET = 'dashboard-logs'
|
|
|
|
export const DASHBOARD_LOG_CATEGORIES: ExtendedSupportCategories[] = [
|
|
SupportCategories.DASHBOARD_BUG,
|
|
]
|
|
|
|
export const getSanitizedBreadcrumbs = (): unknown[] => {
|
|
const breadcrumbs = getOwnershipOfBreadcrumbSnapshot() ?? getMirroredBreadcrumbs()
|
|
return sanitizeArrayOfObjects(breadcrumbs)
|
|
}
|
|
|
|
export const uploadDashboardLog = async ({
|
|
userId,
|
|
uploadDashboardLogFn,
|
|
}: {
|
|
userId: string | undefined
|
|
uploadDashboardLogFn: (
|
|
vars: GenerateAttachmentURLsVariables
|
|
) => Promise<GenerateAttachmentURLsData>
|
|
}): Promise<string[]> => {
|
|
if (!userId) {
|
|
console.error(
|
|
'[SupportForm > uploadDashboardLog] Cannot upload dashboard log: user ID is undefined'
|
|
)
|
|
return []
|
|
}
|
|
|
|
const sanitized = getSanitizedBreadcrumbs()
|
|
if (sanitized.length === 0) return []
|
|
|
|
try {
|
|
const supportStorageClient = createSupportStorageClient()
|
|
const objectKey = `${userId}/${uuidv4()}.json`
|
|
const body = new Blob([JSON.stringify(sanitized, null, 2)], {
|
|
type: 'application/json',
|
|
})
|
|
|
|
const { error: uploadError } = await supportStorageClient.storage
|
|
.from(DASHBOARD_LOG_BUCKET)
|
|
.upload(objectKey, body, {
|
|
cacheControl: '3600',
|
|
contentType: 'application/json',
|
|
upsert: false,
|
|
})
|
|
|
|
if (uploadError) {
|
|
console.error(
|
|
'[SupportForm > uploadDashboardLog] Failed to upload dashboard log to support storage bucket',
|
|
uploadError
|
|
)
|
|
return []
|
|
}
|
|
|
|
return uploadDashboardLogFn({
|
|
bucket: DASHBOARD_LOG_BUCKET,
|
|
filenames: [objectKey],
|
|
})
|
|
} catch (error) {
|
|
console.error('[SupportForm] Unexpected error uploading dashboard log', error)
|
|
return []
|
|
}
|
|
}
|