summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-11-03 11:38:00 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-11-03 11:38:00 +0900
commitaadd5b95b811dbd9d0fce9e622613a148e4ad7da (patch)
treee656a7e348fe9c5a6a79c005eb5925d006f1440c /src
parentImprove stats API (diff)
downloadsharkey-aadd5b95b811dbd9d0fce9e622613a148e4ad7da.tar.gz
sharkey-aadd5b95b811dbd9d0fce9e622613a148e4ad7da.tar.bz2
sharkey-aadd5b95b811dbd9d0fce9e622613a148e4ad7da.zip
Improve admin dashboard
Diffstat (limited to 'src')
-rw-r--r--src/client/app/admin/views/ap-log.vue113
-rw-r--r--src/client/app/admin/views/dashboard.vue23
-rw-r--r--src/client/app/common/views/filters/bytes.ts1
-rw-r--r--src/client/app/common/views/filters/number.ts1
-rw-r--r--src/queue/processors/http/process-inbox.ts10
-rw-r--r--src/remote/activitypub/request.ts10
-rw-r--r--src/server/api/stream/channels/ap-log.ts24
-rw-r--r--src/server/api/stream/channels/index.ts2
-rw-r--r--src/stream.ts5
9 files changed, 181 insertions, 8 deletions
diff --git a/src/client/app/admin/views/ap-log.vue b/src/client/app/admin/views/ap-log.vue
new file mode 100644
index 0000000000..a26627a90f
--- /dev/null
+++ b/src/client/app/admin/views/ap-log.vue
@@ -0,0 +1,113 @@
+<template>
+<div class="hyhctythnmwihguaaapnbrbszsjqxpio">
+ <table>
+ <thead>
+ <tr>
+ <th>%fa:exchange-alt% In/Out</th>
+ <th>%fa:server% Host</th>
+ <th>%fa:bolt% Activity</th>
+ <th>%fa:user% Actor</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr v-for="log in logs" :key="log.id">
+ <td :class="log.direction">{{ log.direction == 'in' ? '<' : '>' }} {{ log.direction }}</td>
+ <td>{{ log.host }}</td>
+ <td>{{ log.activity }}</td>
+ <td>@{{ log.actor }}</td>
+ </tr>
+ </tbody>
+ </table>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+
+export default Vue.extend({
+ data() {
+ return {
+ logs: [],
+ connection: null
+ };
+ },
+
+ mounted() {
+ this.connection = (this as any).os.stream.useSharedConnection('apLog');
+ this.connection.on('stats', this.onLog);
+ this.connection.on('statsLog', this.onLogs);
+ this.connection.send('requestLog', {
+ id: Math.random().toString().substr(2, 8),
+ length: 50
+ });
+
+ setInterval(() => {
+ this.onLog({
+ direction: ['in', 'out'][Math.floor(Math.random() * 2)],
+ activity: 'Create',
+ host: 'misskey.ai',
+ actor: 'foobar'
+ });
+ }, 1000);
+ },
+
+ beforeDestroy() {
+ this.connection.dispose();
+ },
+
+ methods: {
+ onLog(log) {
+ log.id = Math.random();
+ this.logs.unshift(log);
+ if (this.logs.length > 50) this.logs.pop();
+ },
+
+ onLogs(logs) {
+ logs.reverse().forEach(log => this.onLog(log));
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+.hyhctythnmwihguaaapnbrbszsjqxpio
+ display block
+ padding 16px
+ height 250px
+ overflow auto
+ box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
+ background var(--face)
+ border-radius 8px
+
+ > table
+ width 100%
+ max-width 100%
+ overflow auto
+ border-spacing 0
+ border-collapse collapse
+ color #555
+
+ thead
+ font-weight bold
+ border-bottom solid 2px #eee
+
+ tr
+ th
+ text-align left
+
+ tbody
+ tr
+ &:nth-child(odd)
+ background #fbfbfb
+
+ th, td
+ padding 8px 16px
+ min-width 128px
+
+ td.in
+ color #d26755
+
+ td.out
+ color #55bb83
+
+</style>
diff --git a/src/client/app/admin/views/dashboard.vue b/src/client/app/admin/views/dashboard.vue
index 95000d4bad..04a4de8746 100644
--- a/src/client/app/admin/views/dashboard.vue
+++ b/src/client/app/admin/views/dashboard.vue
@@ -7,6 +7,7 @@
<p><b>Node</b><span>{{ meta.node }}</span></p>
<p>藍ちゃかわいい</p>
</header>
+
<div v-if="stats" class="stats">
<div>
<div>
@@ -34,22 +35,22 @@
</div>
<div>
<div>
- <div>%fa:user%</div>
+ <div>%fa:database%</div>
<div>
- <span>%i18n:@accounts%</span>
- <b>{{ stats.usersCount | number }}</b>
+ <span>%i18n:@drive%</span>
+ <b>{{ stats.driveUsageLocal | bytes }}</b>
</div>
</div>
<div>
- <span>%fa:globe% %i18n:@federated%</span>
+ <span>%fa:home% %i18n:@this-instance%</span>
</div>
</div>
<div>
<div>
- <div>%fa:pencil-alt%</div>
+ <div>%fa:hdd R%</div>
<div>
- <span>%i18n:@notes%</span>
- <b>{{ stats.notesCount | number }}</b>
+ <span>%i18n:@instances%</span>
+ <b>{{ stats.instances | number }}</b>
</div>
</div>
<div>
@@ -65,6 +66,10 @@
<div class="cpu-memory">
<x-cpu-memory :connection="connection"/>
</div>
+
+ <div class="ap">
+ <x-ap-log/>
+ </div>
</div>
</template>
@@ -72,11 +77,13 @@
import Vue from "vue";
import XCpuMemory from "./cpu-memory.vue";
import XCharts from "./charts.vue";
+import XApLog from "./ap-log.vue";
export default Vue.extend({
components: {
XCpuMemory,
- XCharts
+ XCharts,
+ XApLog
},
data() {
return {
diff --git a/src/client/app/common/views/filters/bytes.ts b/src/client/app/common/views/filters/bytes.ts
index f7a1b2690f..5b5d966cfd 100644
--- a/src/client/app/common/views/filters/bytes.ts
+++ b/src/client/app/common/views/filters/bytes.ts
@@ -1,6 +1,7 @@
import Vue from 'vue';
Vue.filter('bytes', (v, digits = 0) => {
+ if (v == null) return '?';
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
if (v == 0) return '0';
const isMinus = v < 0;
diff --git a/src/client/app/common/views/filters/number.ts b/src/client/app/common/views/filters/number.ts
index d9f48229dd..08f9fea805 100644
--- a/src/client/app/common/views/filters/number.ts
+++ b/src/client/app/common/views/filters/number.ts
@@ -1,5 +1,6 @@
import Vue from 'vue';
Vue.filter('number', (n) => {
+ if (n == null) return 'N/A';
return n.toLocaleString();
});
diff --git a/src/queue/processors/http/process-inbox.ts b/src/queue/processors/http/process-inbox.ts
index 8e6b3769de..87f0fbfb8d 100644
--- a/src/queue/processors/http/process-inbox.ts
+++ b/src/queue/processors/http/process-inbox.ts
@@ -8,6 +8,7 @@ import perform from '../../../remote/activitypub/perform';
import { resolvePerson, updatePerson } from '../../../remote/activitypub/models/person';
import { toUnicode } from 'punycode';
import { URL } from 'url';
+import { publishApLogStream } from '../../../stream';
const log = debug('misskey:queue:inbox');
@@ -61,6 +62,15 @@ export default async (job: bq.Job, done: any): Promise<void> => {
}) as IRemoteUser;
}
+ //#region Log
+ publishApLogStream({
+ direction: 'in',
+ activity: activity.type,
+ host: user.host,
+ actor: user.username
+ });
+ //#endregion
+
// Update activityの場合は、ここで署名検証/更新処理まで実施して終了
if (activity.type === 'Update') {
if (activity.object && activity.object.type === 'Person') {
diff --git a/src/remote/activitypub/request.ts b/src/remote/activitypub/request.ts
index 177b6f458e..68c53e0c6c 100644
--- a/src/remote/activitypub/request.ts
+++ b/src/remote/activitypub/request.ts
@@ -6,6 +6,7 @@ const crypto = require('crypto');
import config from '../../config';
import { ILocalUser } from '../../models/user';
+import { publishApLogStream } from '../../stream';
const log = debug('misskey:activitypub:deliver');
@@ -64,4 +65,13 @@ export default (user: ILocalUser, url: string, object: any) => new Promise((reso
});
req.end(data);
+
+ //#region Log
+ publishApLogStream({
+ direction: 'out',
+ activity: object.type,
+ host: null,
+ actor: user.username
+ });
+ //#endregion
});
diff --git a/src/server/api/stream/channels/ap-log.ts b/src/server/api/stream/channels/ap-log.ts
new file mode 100644
index 0000000000..dfa1cc702d
--- /dev/null
+++ b/src/server/api/stream/channels/ap-log.ts
@@ -0,0 +1,24 @@
+import autobind from 'autobind-decorator';
+import Channel from '../channel';
+
+export default class extends Channel {
+ public readonly chName = 'apLog';
+ public static shouldShare = true;
+
+ @autobind
+ public async init(params: any) {
+ // Subscribe events
+ this.subscriber.on('apLog', this.onLog);
+ }
+
+ @autobind
+ private async onLog(log: any) {
+ this.send('log', log);
+ }
+
+ @autobind
+ public dispose() {
+ // Unsubscribe events
+ this.subscriber.off('apLog', this.onLog);
+ }
+}
diff --git a/src/server/api/stream/channels/index.ts b/src/server/api/stream/channels/index.ts
index 7e71590d00..7248579abd 100644
--- a/src/server/api/stream/channels/index.ts
+++ b/src/server/api/stream/channels/index.ts
@@ -10,6 +10,7 @@ import messaging from './messaging';
import messagingIndex from './messaging-index';
import drive from './drive';
import hashtag from './hashtag';
+import apLog from './ap-log';
import gamesReversi from './games/reversi';
import gamesReversiGame from './games/reversi-game';
@@ -26,6 +27,7 @@ export default {
messagingIndex,
drive,
hashtag,
+ apLog,
gamesReversi,
gamesReversiGame
};
diff --git a/src/stream.ts b/src/stream.ts
index b222a45ca9..543421726a 100644
--- a/src/stream.ts
+++ b/src/stream.ts
@@ -100,6 +100,10 @@ class Publisher {
public publishHashtagStream = (note: any): void => {
this.publish('hashtag', null, note);
}
+
+ public publishApLogStream = (log: any): void => {
+ this.publish('apLog', null, log);
+ }
}
const publisher = new Publisher();
@@ -119,3 +123,4 @@ export const publishLocalTimelineStream = publisher.publishLocalTimelineStream;
export const publishHybridTimelineStream = publisher.publishHybridTimelineStream;
export const publishGlobalTimelineStream = publisher.publishGlobalTimelineStream;
export const publishHashtagStream = publisher.publishHashtagStream;
+export const publishApLogStream = publisher.publishApLogStream;