diff --git a/packages/builder/src/pages/builder/portal/account/systemLogs/index.svelte b/packages/builder/src/pages/builder/portal/account/systemLogs/index.svelte new file mode 100644 index 0000000000..357970aebe --- /dev/null +++ b/packages/builder/src/pages/builder/portal/account/systemLogs/index.svelte @@ -0,0 +1,17 @@ + + + + Download your latest logs to share with the Budibase team +
+ +
+
diff --git a/packages/builder/src/stores/portal/menu.js b/packages/builder/src/stores/portal/menu.js index 40580cd0ec..04151f66d4 100644 --- a/packages/builder/src/stores/portal/menu.js +++ b/packages/builder/src/stores/portal/menu.js @@ -85,6 +85,13 @@ export const menu = derived([admin, auth], ([$admin, $auth]) => { title: "Audit Logs", href: "/builder/portal/account/auditLogs", }) + + if (!$admin.cloud) { + accountSubPages.push({ + title: "System Logs", + href: "/builder/portal/account/systemLogs", + }) + } } if ($admin.cloud && $auth?.user?.accountPortalAccess) { accountSubPages.push({ diff --git a/packages/frontend-core/src/utils/download.js b/packages/frontend-core/src/utils/download.js index 5c00a0023e..89c8572253 100644 --- a/packages/frontend-core/src/utils/download.js +++ b/packages/frontend-core/src/utils/download.js @@ -12,8 +12,17 @@ export function downloadText(filename, text) { URL.revokeObjectURL(url) } -export async function downloadStream(filename, streamResponse) { +export async function downloadStream(streamResponse) { const blob = await streamResponse.blob() + + const contentDisposition = streamResponse.headers.get("Content-Disposition") + + const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec( + contentDisposition + ) + + const filename = matches[1].replace(/['"]/g, "") + const resBlob = new Blob([blob]) const blobUrl = URL.createObjectURL(resBlob) diff --git a/packages/worker/src/api/controllers/system/logs.ts b/packages/worker/src/api/controllers/system/logs.ts index f38a8f57a7..6b3c70f664 100644 --- a/packages/worker/src/api/controllers/system/logs.ts +++ b/packages/worker/src/api/controllers/system/logs.ts @@ -1,8 +1,11 @@ import { UserCtx } from "@budibase/types" -import { logging } from "@budibase/backend-core" +import { context, logging } from "@budibase/backend-core" export async function getLogs(ctx: UserCtx) { const logReadStream = logging.system.getLogReadStream() + const fileName = `${context.getTenantId()}-${Date.now()}.logs` + + ctx.set("content-disposition", `attachment; filename=${fileName}`) ctx.body = logReadStream }