diagnostics panel

This commit is contained in:
Martin McKeaveney 2023-06-10 16:16:52 +01:00
parent 746afaf573
commit 7e45773d02
7 changed files with 128 additions and 100 deletions

View File

@ -1,81 +0,0 @@
<script>
import {
Layout,
Heading,
Body,
Divider,
Icon,
Input,
TextArea,
} from "@budibase/bbui"
import { CopyInput } from "@budibase/bbui"
import { auth, admin } from "stores/portal"
import { redirect } from "@roxi/routify"
import { processStringSync } from "@budibase/string-templates"
import { API } from "api"
import { onMount } from "svelte"
const BROWSER_MAP = {
edge: "Microsoft Edge",
"edg/": "Chromium Based Edge",
opr: "Opera",
chrome: "Chrome",
trident: "Internet Explorer",
firefox: "Firefox",
safari: "Safari",
}
let diagnosticInfo = ""
// Make sure page can't be visited directly in cloud
$: {
if ($admin.cloud) {
$redirect("../../portal")
}
}
async function fetchDiagnostics() {
const diagnostics = await API.fetchDiagnostics()
return {
browser: {
language: navigator.language || navigator.userLanguage,
userAgent: navigator.userAgent,
platform: navigator.platform,
vendor: navigator.vendor,
},
server: diagnostics,
}
}
onMount(async () => {
const info = await fetchDiagnostics()
diagnosticInfo = info
})
</script>
{#if $auth.isAdmin}
<Layout noPadding>
<Layout gap="XS" noPadding>
<Heading size="M">Diagnostics</Heading>
<Body size="M">
<pre>
{JSON.stringify(diagnosticInfo, null, 2)}
</pre>
<!-- <CopyInput value={JSON.stringify(diagnosticInfo, null, 2)} /> -->
</Body>
</Layout>
<Divider />
<div>
<!-- <Button secondary on:click={refresh}>Refresh</Button> -->
</div>
</Layout>
{/if}
<style>
pre {
overflow-x: auto;
white-space: pre;
word-wrap: break-word;
font-size: 15px;
}
</style>

View File

@ -0,0 +1,86 @@
<script>
import {
Layout,
Heading,
Body,
Helpers,
Button,
Divider,
notifications,
Icon,
Input,
TextArea,
} from "@budibase/bbui"
import { auth, admin } from "stores/portal"
import { redirect } from "@roxi/routify"
import { API } from "api"
import { onMount } from "svelte"
let diagnosticInfo = ""
// Make sure page can't be visited directly in cloud
$: {
if ($admin.cloud) {
$redirect("../../portal")
}
}
async function fetchSystemDebugInfo() {
const diagnostics = await API.fetchSystemDebugInfo()
diagnosticInfo = {
browser: {
language: navigator.language || navigator.userLanguage,
userAgent: navigator.userAgent,
platform: navigator.platform,
vendor: navigator.vendor,
},
server: diagnostics,
}
}
const copyToClipboard = async () => {
await Helpers.copyToClipboard(JSON.stringify(diagnosticInfo, undefined, 2))
notifications.success("Copied")
}
onMount(async () => {
await fetchSystemDebugInfo()
})
</script>
{#if $auth.isAdmin && diagnosticInfo}
<Layout noPadding>
<Layout gap="XS">
<Heading size="M">Diagnostics</Heading>
Please include this diagnostic information in support requests and github issues
by clicking the button on the top right to copy to clipboard.
<Divider />
<Body size="M">
<section>
<div on:click={copyToClipboard} class="copy-icon">
<Icon name="Copy" size="M" />
</div>
<TextArea
height="45vh"
disabled
value={JSON.stringify(diagnosticInfo, undefined, 2)}
/>
</section>
</Body>
</Layout>
</Layout>
{/if}
<style>
section {
position: relative;
}
.copy-icon {
z-index: 1;
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
}
</style>

View File

@ -58,6 +58,10 @@ export const menu = derived([admin, auth], ([$admin, $auth]) => {
title: "Environment",
href: "/builder/portal/settings/environment",
},
{
title: "Diagnostics",
href: "/builder/portal/settings/diagnostics",
},
]
if (!$admin.cloud) {
settingsSubPages.push({
@ -85,14 +89,6 @@ export const menu = derived([admin, auth], ([$admin, $auth]) => {
title: "Audit Logs",
href: "/builder/portal/account/auditLogs",
})
accountSubPages.push({
title: "Diagnostics",
href: "/builder/portal/account/diagnostics",
})
accountSubPages.push({
title: "Logs",
href: "/builder/portal/account/debugLogs",
})
}
if ($admin.cloud && $auth?.user?.accountPortalAccess) {
accountSubPages.push({

View File

@ -124,11 +124,11 @@ export const buildAppEndpoints = API => ({
},
/**
* Gets application diagnostics.
* Gets budibase platform debug information.
*/
fetchDiagnostics: async () => {
fetchSystemDebugInfo: async () => {
return await API.get({
url: `/api/dev/diagnostics`,
url: `/api/dev/debug`,
})
},

View File

@ -1,5 +1,7 @@
import fetch from "node-fetch"
import env from "../../environment"
import os from "os"
import process from "process"
import { checkSlashesInUrl } from "../../utilities"
import { request } from "../../utilities/workerRequests"
import { clearLock as redisClearLock } from "../../utilities/redis"
@ -7,6 +9,7 @@ import { DocumentType } from "../../db/utils"
import { context, env as envCore } from "@budibase/backend-core"
import { events, db as dbCore, cache } from "@budibase/backend-core"
async function redirect(ctx: any, method: string, path: string = "global") {
const { devPath } = ctx.params
const queryString = ctx.originalUrl.split("?")[1] || ""
@ -128,9 +131,9 @@ export async function getBudibaseVersion(ctx: any) {
await events.installation.versionChecked(version)
}
export async function troubleshootingInfo(ctx: any) {
const os = require("os")
const process = require("process")
export async function systemDebugInfo(ctx: any) {
const { days, hours, minutes } = secondsToHMS(os.uptime())
const totalMemory = convertBytes(os.totalmem())
ctx.body = {
budibaseVersion: envCore.VERSION,
@ -140,8 +143,32 @@ export async function troubleshootingInfo(ctx: any) {
cpuArch: process.arch,
cpuCores: os.cpus().length,
cpuInfo: os.cpus()[0].model,
totalMemory: os.totalmem(),
freeMemory: os.freemem(),
uptime: os.uptime(),
totalMemory: `${totalMemory.gb}GB`,
uptime: `${days} day(s), ${hours} hour(s), ${minutes} minute(s)`,
}
}
function secondsToHMS(seconds: number) {
const MINUTE_IN_SECONDS = 60
const HOUR_IN_SECONDS = 3600
const DAY_IN_SECONDS = HOUR_IN_SECONDS * 24
const minutes = Math.floor((seconds / MINUTE_IN_SECONDS) % 60);
const hours = Math.floor((seconds / HOUR_IN_SECONDS) % 24);
const days = Math.floor(seconds / DAY_IN_SECONDS)
return {
days,
hours,
minutes,
seconds
}
}
function convertBytes(bytes: number) {
const kb = bytes / 1024;
const mb = kb / 1024;
const gb = mb / 1024;
return { gb, mb, kb }
}

View File

@ -25,9 +25,9 @@ router
controller.getBudibaseVersion
)
.get(
"/api/dev/diagnostics",
"/api/dev/debug",
authorized(permissions.BUILDER),
controller.troubleshootingInfo
controller.systemDebugInfo
)
.delete(
"/api/dev/:appId/lock",