Skip to content

Commit

Permalink
feat: database performance insights (#2361)
Browse files Browse the repository at this point in the history
  • Loading branch information
tanmoysrt authored Dec 23, 2024
1 parent 17fe55a commit ed58508
Show file tree
Hide file tree
Showing 38 changed files with 1,955 additions and 2,223 deletions.
14 changes: 12 additions & 2 deletions dashboard/src2/components/NavigationItems.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import WalletCards from '~icons/lucide/wallet-cards';
import Settings from '~icons/lucide/settings';
import App from '~icons/lucide/layout-grid';
import DatabaseZap from '~icons/lucide/database-zap';
import Activity from '~icons/lucide/activity';
import Logs from '~icons/lucide/scroll-text';
import Globe from '~icons/lucide/globe';
import Notification from '~icons/lucide/inbox';
Expand Down Expand Up @@ -129,9 +130,18 @@ export default {
icon: () => h(Logs),
route: '/log-browser',
isActive: routeName === 'Log Browser'
},
{
name: 'DB Analyzer',
icon: () => h(Activity),
route: '/database-analyzer',
isActive: routeName === 'DB Analyzer',
condition: this.$team.doc?.is_desk_user
}
],
isActive: ['SQL Playground', 'Log Browser'].includes(routeName),
].filter(item => item.condition ?? true),
isActive: ['SQL Playground', 'DB Analyzer', 'Log Browser'].includes(
routeName
),
disabled: enforce2FA
},
{
Expand Down
51 changes: 51 additions & 0 deletions dashboard/src2/components/ToggleContent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<template>
<div class="rounded border text-base">
<div
class="flex cursor-pointer select-none flex-row items-center justify-between gap-2 p-4"
@click="toggleVisibility"
:class="{
'!pb-2': isVisible
}"
>
<div>
<p class="font-medium text-gray-800">
{{ label }}
</p>
<p class="mt-2 text-sm text-gray-700" v-if="subLabel">
{{ subLabel }}
</p>
</div>
<slot name="actions" v-if="isVisible"></slot>
</div>

<div v-if="isVisible" class="text-sm leading-normal">
<slot></slot>
</div>
</div>
</template>

<script>
export default {
name: 'ToggleContent',
props: {
label: {
type: String,
required: true
},
subLabel: {
type: String,
default: ''
}
},
data() {
return {
isVisible: false
};
},
methods: {
toggleVisibility() {
this.isVisible = !this.isVisible;
}
}
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<template>
<Button v-if="isJobRunning" @click="viewJob" variant="ghost" class="w-full"
>View Job</Button
>
<Button
v-else
@click="addIndex"
:loading="this.$resources.addIndex.loading"
loadingText="Adding Index"
iconLeft="plus"
variant="ghost"
class="w-full"
>Add DB Index</Button
>
</template>
<script>
import { toast } from 'vue-sonner';
export default {
props: {
row: { type: Object, required: true },
site: { type: String, required: true }
},
data() {
return {
isJobRunning: false,
jobName: null
};
},
resources: {
addIndex() {
return {
url: 'press.api.client.run_doc_method',
initialData: {},
makeParams: () => {
return {
dt: 'Site',
dn: this.site,
method: 'add_database_index',
args: {
table: this.row['Table'],
column: this.row['Column']
}
};
},
onSuccess: data => {
if (data?.message) {
if (data?.message?.success) {
toast.success(data?.message?.message);
this.isJobRunning = true;
this.jobName = data?.message?.job_name;
} else {
toast.error(data?.message?.message);
}
}
},
auto: false
};
}
},
methods: {
addIndex() {
this.$resources.addIndex.submit();
},
viewJob() {
if (this.jobName) {
window.open(
this.$router.resolve(
`/sites/${this.site}/insights/jobs/${this.jobName}`
).href,
'_blank'
);
}
}
}
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<template>
<p v-if="isKilled">Process Killed</p>
<Button
v-else
@click="killProcess"
:loading="this.$resources.killProcess.loading"
loadingText="Killing"
iconLeft="trash"
variant="ghost"
class="w-full"
>Kill Process</Button
>
</template>
<script>
import { toast } from 'vue-sonner';
export default {
props: {
row: { type: Object, required: true },
site: { type: String, required: true }
},
data() {
return {
isKilled: false
};
},
resources: {
killProcess() {
return {
url: 'press.api.client.run_doc_method',
initialData: {},
makeParams: () => {
return {
dt: 'Site',
dn: this.site,
method: 'kill_database_process',
args: {
id: this.row.ID
}
};
},
onSuccess: data => {
this.isKilled = true;
toast.success('Database Process Killed');
},
auto: false
};
}
},
methods: {
killProcess() {
this.$resources.killProcess.submit();
}
}
};
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
v-if="selectedSchema"
/>
</div>
<div class="mt-3 flex flex-row gap-2" v-if="selectedSchema">
<div
class="mt-3 flex flex-row gap-2"
v-if="selectedSchema && showSQLActions"
>
<Button
iconLeft="play"
class="grow"
Expand Down Expand Up @@ -51,11 +54,29 @@
import { h } from 'vue';
import { FormControl } from 'frappe-ui';
import ObjectList from '../../ObjectList.vue';
import { icon } from '../../../utils/components';
import { toast } from 'vue-sonner';
export default {
name: 'DatabaseTableSchemaDialog',
props: ['site', 'tableSchemas'],
props: {
site: {
type: String,
required: true
},
tableSchemas: {
type: Object,
required: true
},
showSQLActions: {
type: Boolean,
default: false
},
preSelectedSchema: {
type: String,
default: null
}
},
emits: ['runSQLQuery'],
components: {
FormControl,
Expand All @@ -66,18 +87,28 @@ export default {
selectedSchema: null
};
},
mounted() {
this.preSelectSchema();
},
watch: {
preSelectedSchema() {
this.preSelectSchema();
}
},
computed: {
autocompleteOptions() {
return Object.keys(this.tableSchemas).map(x => ({
label: x,
label: `${x} (${this.bytesToMB(
this.tableSchemas[x].size.total_size
)}MB)`,
value: x
}));
},
listOptions() {
if (!this.selectedSchema || !this.selectedSchema.value) return {};
return {
data: () => {
return this.tableSchemas[this.selectedSchema.value] ?? [];
return this.tableSchemas?.[this.selectedSchema.value]?.columns ?? [];
},
hideControls: true,
columns: [
Expand Down Expand Up @@ -124,15 +155,15 @@ export default {
},
align: 'center'
},
{
label: 'Is Indexed',
fieldname: 'indexes',
width: 0.15,
align: 'center',
type: 'Icon',
Icon(value) {
return value.length > 0 ? 'check' : 'x';
type: 'Component',
component({ row }) {
return row.index_info.is_indexed
? icon('check', 'w-4 w-4')
: icon('x', 'w-4 w-4');
}
}
]
Expand Down Expand Up @@ -163,6 +194,18 @@ export default {
'runSQLQuery',
`SELECT * FROM \`${this.selectedSchema.value}\`;`
);
},
bytesToMB(bytes) {
return (bytes / (1024 * 1024)).toFixed(2);
},
preSelectSchema() {
if (!this.preSelectedSchema) return;
if (!this.tableSchemas) return;
if (this.autocompleteOptions.length == 0) return;
this.selectedSchema = {
label: this.preSelectedSchema,
value: this.preSelectedSchema
};
}
}
};
Expand Down
Loading

0 comments on commit ed58508

Please sign in to comment.