Skip to content

Commit

Permalink
feat(renterd): generate debug report zip
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfreska committed Oct 11, 2024
1 parent 3d2a152 commit fe8a8a3
Show file tree
Hide file tree
Showing 9 changed files with 408 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/large-games-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'renterd': minor
---

There is now an option to generate a metadata report for debugging purposes. It can be accessed from the cmd+k menu.
6 changes: 6 additions & 0 deletions .changeset/swift-otters-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@siafoundation/renterd-react': minor
'@siafoundation/renterd-types': minor
---

The alerts API limit and skip params are now optional.
9 changes: 9 additions & 0 deletions apps/renterd/components/CmdRoot/AppCmdGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,15 @@ export function AppCmdGroup({ currentPage, parentPage }: Props) {
>
Set theme to light
</CommandItemSearch>
<CommandItemSearch
currentPage={currentPage}
commandPage={commandPage}
onSelect={() => {
openDialog('debug')
}}
>
Generate a debug report
</CommandItemSearch>
<CommandItemSearch
currentPage={currentPage}
commandPage={commandPage}
Expand Down
3 changes: 3 additions & 0 deletions apps/renterd/contexts/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { FilesBucketPolicyDialog } from '../dialogs/FilesBucketPolicyDialog'
import { FilesBucketCreateDialog } from '../dialogs/FilesBucketCreateDialog'
import { FileRenameDialog } from '../dialogs/FileRenameDialog'
import { KeysCreateDialog } from '../components/Keys/KeysCreateDialog'
import { DebugDialog } from '../dialogs/DebugDialog'

export type DialogType =
| 'cmdk'
Expand All @@ -46,6 +47,7 @@ export type DialogType =
| 'filesSearch'
| 'fileRename'
| 'keysCreate'
| 'debug'
| 'confirm'

type ConfirmProps = {
Expand Down Expand Up @@ -212,6 +214,7 @@ export function Dialogs() {
open={dialog === 'keysCreate'}
onOpenChange={onOpenChange}
/>
<DebugDialog open={dialog === 'debug'} onOpenChange={onOpenChange} />
<ConfirmDialog
open={dialog === 'confirm'}
params={confirm}
Expand Down
221 changes: 221 additions & 0 deletions apps/renterd/dialogs/DebugDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
import {
Dialog,
ConfigFields,
useOnInvalid,
FormSubmitButton,
useDialogFormHelpers,
FieldSwitch,
Label,
} from '@siafoundation/design-system'
import {
useAlerts,
useAutopilotConfig,
useContracts,
useSettingsGouging,
useSettingsPinned,
useSettingsUpload,
} from '@siafoundation/renterd-react'
import { useCallback, useMemo } from 'react'
import { useForm } from 'react-hook-form'
import JSZip from 'jszip'
import { saveAs } from 'file-saver'
import { useApp } from '../contexts/app'

function getDefaultValues() {
return {
contracts: true,
alerts: true,
autopilot: true,
gouging: true,
upload: true,
pinned: true,
}
}

type Values = ReturnType<typeof getDefaultValues>

function getFields(): ConfigFields<Values, never> {
return {
contracts: {
type: 'boolean',
title: 'Contracts',
validation: {},
},
alerts: {
type: 'boolean',
title: 'Alerts',
validation: {},
},
autopilot: {
type: 'boolean',
title: 'Autopilot',
validation: {},
},
gouging: {
type: 'boolean',
title: 'Gouging',
validation: {},
},
upload: {
type: 'boolean',
title: 'Upload',
validation: {},
},
pinned: {
type: 'boolean',
title: 'Pinned',
validation: {},
},
}
}

type Props = {
trigger?: React.ReactNode
open: boolean
onOpenChange: (val: boolean) => void
}

export function DebugDialog({ trigger, open, onOpenChange }: Props) {
const { isAutopilotEnabled } = useApp()
const defaultValues = useMemo(() => getDefaultValues(), [])

const contracts = useContracts()
const alerts = useAlerts({
params: {
limit: 1000,
},
})
const autopilot = useAutopilotConfig({
disabled: !isAutopilotEnabled,
})
const gouging = useSettingsGouging()
const upload = useSettingsUpload()
const pinned = useSettingsPinned()

const form = useForm({
mode: 'all',
defaultValues,
})

const { handleOpenChange } = useDialogFormHelpers({
form,
onOpenChange,
defaultValues,
initKey: [name],
})

const onValid = useCallback(
async (values: Values) => {
const zip = new JSZip()

// Add all the data to the zip file as JSON files.
if (values.alerts) {
zip.file('alerts.json', JSON.stringify(alerts.data, null, 2))
}
if (values.contracts) {
zip.file('contracts.json', JSON.stringify(contracts.data, null, 2))
}
if (isAutopilotEnabled && values.autopilot) {
zip.file('autopilot.json', JSON.stringify(autopilot.data, null, 2))
}
if (values.gouging) {
zip.file('gouging.json', JSON.stringify(gouging.data, null, 2))
}
if (values.upload) {
zip.file('upload.json', JSON.stringify(upload.data, null, 2))
}
if (values.pinned) {
zip.file('pinned.json', JSON.stringify(pinned.data, null, 2))
}

// Generate the zip file.
const blob = await zip.generateAsync({ type: 'blob' })

// Trigger download.
saveAs(blob, 'renterd-debug.zip')
},
[
isAutopilotEnabled,
contracts.data,
alerts.data,
autopilot.data,
gouging.data,
upload.data,
pinned.data,
]
)

const fields = useMemo(() => getFields(), [])

const onInvalid = useOnInvalid(fields)

return (
<Dialog
title="Generate a debug report"
description="Select which metadata files to include in the generated report."
trigger={trigger}
open={open}
onOpenChange={handleOpenChange}
contentVariants={{
className: 'w-[400px]',
}}
onSubmit={form.handleSubmit(onValid, onInvalid)}
>
<div className="flex flex-col gap-6 pt-4">
<div className="flex flex-col gap-2">
<Label size="14" color="subtle">
General
</Label>
<div className="flex gap-4">
<FieldSwitch
size="small"
form={form}
fields={fields}
name="contracts"
/>
<FieldSwitch
size="small"
form={form}
fields={fields}
name="alerts"
/>
</div>
</div>
<div className="flex flex-col gap-2">
<Label size="14" color="subtle">
Configuration
</Label>
<div className="flex gap-4">
{isAutopilotEnabled && (
<FieldSwitch
size="small"
form={form}
fields={fields}
name="autopilot"
/>
)}
<FieldSwitch
size="small"
form={form}
fields={fields}
name="gouging"
/>
<FieldSwitch
size="small"
form={form}
fields={fields}
name="upload"
/>
<FieldSwitch
size="small"
form={form}
fields={fields}
name="pinned"
/>
</div>
</div>
<FormSubmitButton form={form}>Generate</FormSubmitButton>
</div>
</Dialog>
)
}
2 changes: 1 addition & 1 deletion libs/renterd-react/src/bus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ export function useSettingsUploadUpdate(
}

// params are required because omitting them returns a deprecated response structure
export function useAlerts(args: HookArgsSwr<AlertsParams, AlertsResponse>) {
export function useAlerts(args?: HookArgsSwr<AlertsParams, AlertsResponse>) {
return useGetSwr({ ...args, route: busAlertsRoute })
}

Expand Down
4 changes: 2 additions & 2 deletions libs/renterd-types/src/bus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,8 +474,8 @@ export type Alert = {
}

export type AlertsParams = {
limit: number
offset: number
limit?: number
offset?: number
severity?: AlertSeverity
}
export type AlertsPayload = void
Expand Down
Loading

0 comments on commit fe8a8a3

Please sign in to comment.