diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 7053360a11..d9223b1c4b 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1226,8 +1226,12 @@ admin/views/index.vue:
abuse: "スパム報告"
queue: "ジョブキュー"
logs: "ログ"
+ db: "データベース"
back-to-misskey: "Misskeyに戻る"
+admin/views/db.vue:
+ tables: "テーブル"
+
admin/views/dashboard.vue:
dashboard: "ダッシュボード"
accounts: "アカウント"
diff --git a/src/client/app/admin/views/db.vue b/src/client/app/admin/views/db.vue
new file mode 100644
index 0000000000..27bb81039e
--- /dev/null
+++ b/src/client/app/admin/views/db.vue
@@ -0,0 +1,39 @@
+
+
+
+ {{ $t('tables') }}
+
+ {{ table }} {{ tables[table].count }} {{ tables[table].size | bytes }}
+
+
+
+
+
+
diff --git a/src/client/app/admin/views/index.vue b/src/client/app/admin/views/index.vue
index 43e47038f3..8a13fe1bf6 100644
--- a/src/client/app/admin/views/index.vue
+++ b/src/client/app/admin/views/index.vue
@@ -22,6 +22,7 @@
{{ $t('instance') }}
{{ $t('queue') }}
{{ $t('logs') }}
+ {{ $t('db') }}
{{ $t('moderators') }}
{{ $t('users') }}
{{ $t('@.drive') }}
@@ -43,6 +44,7 @@
+
@@ -59,19 +61,20 @@
import Vue from 'vue';
import i18n from '../../i18n';
import { version } from '../../config';
-import XDashboard from "./dashboard.vue";
-import XInstance from "./instance.vue";
-import XQueue from "./queue.vue";
-import XLogs from "./logs.vue";
-import XModerators from "./moderators.vue";
-import XEmoji from "./emoji.vue";
-import XAnnouncements from "./announcements.vue";
-import XUsers from "./users.vue";
-import XDrive from "./drive.vue";
-import XAbuse from "./abuse.vue";
-import XFederation from "./federation.vue";
+import XDashboard from './dashboard.vue';
+import XInstance from './instance.vue';
+import XQueue from './queue.vue';
+import XLogs from './logs.vue';
+import XDb from './db.vue';
+import XModerators from './moderators.vue';
+import XEmoji from './emoji.vue';
+import XAnnouncements from './announcements.vue';
+import XUsers from './users.vue';
+import XDrive from './drive.vue';
+import XAbuse from './abuse.vue';
+import XFederation from './federation.vue';
-import { faHeadset, faArrowLeft, faGlobe, faExclamationCircle, faTasks, faStream } from '@fortawesome/free-solid-svg-icons';
+import { faHeadset, faArrowLeft, faGlobe, faExclamationCircle, faTasks, faStream, faDatabase } from '@fortawesome/free-solid-svg-icons';
import { faGrin } from '@fortawesome/free-regular-svg-icons';
// Detect the user agent
@@ -85,6 +88,7 @@ export default Vue.extend({
XInstance,
XQueue,
XLogs,
+ XDb,
XModerators,
XEmoji,
XAnnouncements,
@@ -108,7 +112,8 @@ export default Vue.extend({
faGlobe,
faExclamationCircle,
faTasks,
- faStream
+ faStream,
+ faDatabase,
};
},
methods: {
diff --git a/src/server/api/endpoints/admin/get-table-stats.ts b/src/server/api/endpoints/admin/get-table-stats.ts
new file mode 100644
index 0000000000..1abea18492
--- /dev/null
+++ b/src/server/api/endpoints/admin/get-table-stats.ts
@@ -0,0 +1,37 @@
+import define from '../../define';
+import { getConnection } from 'typeorm';
+
+export const meta = {
+ requireCredential: false,
+
+ desc: {
+ 'en-US': 'Get table stats'
+ },
+
+ tags: ['meta'],
+
+ params: {
+ },
+};
+
+export default define(meta, async () => {
+ const sizes = await
+ getConnection().query(`
+ SELECT relname AS "table", reltuples as "count", pg_total_relation_size(C.oid) AS "size"
+ FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
+ WHERE nspname NOT IN ('pg_catalog', 'information_schema')
+ AND C.relkind <> 'i'
+ AND nspname !~ '^pg_toast';`)
+ .then(recs => {
+ const res = {} as Record;
+ for (const rec of recs) {
+ res[rec.table] = {
+ count: parseInt(rec.count, 10),
+ size: parseInt(rec.size, 10),
+ };
+ }
+ return res;
+ });
+
+ return sizes;
+});