summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-10-21 09:20:11 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-10-21 09:20:11 +0900
commit969b6dbcad813201f15ac25a2e750748a18bad42 (patch)
treed70e40b2b41bc6d3ac89b94b47c96e5ec730ac88 /src
parent:art: (diff)
downloadmisskey-969b6dbcad813201f15ac25a2e750748a18bad42.tar.gz
misskey-969b6dbcad813201f15ac25a2e750748a18bad42.tar.bz2
misskey-969b6dbcad813201f15ac25a2e750748a18bad42.zip
Resolve #2963
Diffstat (limited to 'src')
-rw-r--r--src/client/app/desktop/views/components/charts.vue46
-rw-r--r--src/remote/activitypub/models/person.ts4
-rw-r--r--src/server/api/endpoints/chart.ts33
-rw-r--r--src/server/api/endpoints/charts/drive.ts33
-rw-r--r--src/server/api/endpoints/charts/network.ts33
-rw-r--r--src/server/api/endpoints/charts/notes.ts33
-rw-r--r--src/server/api/endpoints/charts/users.ts33
-rw-r--r--src/server/api/private/signup.ts4
-rw-r--r--src/server/index.ts4
-rw-r--r--src/services/drive/add-file.ts4
-rw-r--r--src/services/drive/delete-file.ts4
-rw-r--r--src/services/note/create.ts4
-rw-r--r--src/services/note/delete.ts4
-rw-r--r--src/services/stats.ts719
14 files changed, 561 insertions, 397 deletions
diff --git a/src/client/app/desktop/views/components/charts.vue b/src/client/app/desktop/views/components/charts.vue
index ada024da2d..8a6d89d3f7 100644
--- a/src/client/app/desktop/views/components/charts.vue
+++ b/src/client/app/desktop/views/components/charts.vue
@@ -112,12 +112,42 @@ export default Vue.extend({
}
},
- created() {
- (this as any).api('chart', {
- limit: 35
- }).then(chart => {
- this.chart = chart;
- });
+ async created() {
+ const limit = 35;
+
+ const [perHour, perDay] = await Promise.all([Promise.all([
+ (this as any).api('charts/users', { limit: limit, span: 'hour' }),
+ (this as any).api('charts/notes', { limit: limit, span: 'hour' }),
+ (this as any).api('charts/drive', { limit: limit, span: 'hour' }),
+ (this as any).api('charts/network', { limit: limit, span: 'hour' })
+ ]), Promise.all([
+ (this as any).api('charts/users', { limit: limit, span: 'day' }),
+ (this as any).api('charts/notes', { limit: limit, span: 'day' }),
+ (this as any).api('charts/drive', { limit: limit, span: 'day' }),
+ (this as any).api('charts/network', { limit: limit, span: 'day' })
+ ])]);
+
+ const chart = {
+ perHour: [],
+ perDay: []
+ };
+
+ for (let i = 0; i < limit; i++) {
+ chart.perHour.push({
+ users: perHour[0][i],
+ notes: perHour[1][i],
+ drive: perHour[2][i],
+ network: perHour[3][i]
+ });
+ chart.perDay.push({
+ users: perDay[0][i],
+ notes: perDay[1][i],
+ drive: perDay[2][i],
+ network: perDay[3][i]
+ });
+ }
+
+ this.chart = chart;
},
methods: {
@@ -586,7 +616,7 @@ export default Vue.extend({
borderWidth: 2,
pointBackgroundColor: '#fff',
lineTension: 0,
- data: data.map(x => ({ t: x.date, y: x.incomingRequests }))
+ data: data.map(x => ({ t: x.date, y: x.incoming }))
}]
}];
},
@@ -594,7 +624,7 @@ export default Vue.extend({
networkTimeChart(): any {
const data = this.stats.slice().reverse().map(x => ({
date: new Date(x.date),
- time: x.network.requests != 0 ? (x.network.totalTime / x.network.requests) : 0,
+ time: x.network.incomingRequests != 0 ? (x.network.totalTime / x.network.incomingRequests) : 0,
}));
return [{
diff --git a/src/remote/activitypub/models/person.ts b/src/remote/activitypub/models/person.ts
index 244b62f470..845b11861e 100644
--- a/src/remote/activitypub/models/person.ts
+++ b/src/remote/activitypub/models/person.ts
@@ -10,7 +10,7 @@ import { isCollectionOrOrderedCollection, isCollection, IPerson } from '../type'
import { IDriveFile } from '../../../models/drive-file';
import Meta from '../../../models/meta';
import htmlToMFM from '../../../mfm/html-to-mfm';
-import { coreChart } from '../../../services/stats';
+import { usersChart } from '../../../services/stats';
import { URL } from 'url';
import { resolveNote } from './note';
@@ -180,7 +180,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<IU
}
}, { upsert: true });
- coreChart.updateUserStats(user, true);
+ usersChart.update(user, true);
//#endregion
//#region アイコンとヘッダー画像をフェッチ
diff --git a/src/server/api/endpoints/chart.ts b/src/server/api/endpoints/chart.ts
deleted file mode 100644
index 54f5d8ad4a..0000000000
--- a/src/server/api/endpoints/chart.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import $ from 'cafy';
-import getParams from '../get-params';
-import { coreChart } from '../../../services/stats';
-
-export const meta = {
- desc: {
- 'ja-JP': 'インスタンスの統計を取得します。'
- },
-
- params: {
- limit: $.num.optional.range(1, 100).note({
- default: 30,
- desc: {
- 'ja-JP': '最大数'
- }
- }),
- }
-};
-
-export default (params: any) => new Promise(async (res, rej) => {
- const [ps, psErr] = getParams(meta, params);
- if (psErr) throw psErr;
-
- const [statsPerDay, statsPerHour] = await Promise.all([
- coreChart.getStats('day', ps.limit),
- coreChart.getStats('hour', ps.limit)
- ]);
-
- res({
- perDay: statsPerDay,
- perHour: statsPerHour
- });
-});
diff --git a/src/server/api/endpoints/charts/drive.ts b/src/server/api/endpoints/charts/drive.ts
new file mode 100644
index 0000000000..0572200d6c
--- /dev/null
+++ b/src/server/api/endpoints/charts/drive.ts
@@ -0,0 +1,33 @@
+import $ from 'cafy';
+import getParams from '../../get-params';
+import { driveChart } from '../../../../services/stats';
+
+export const meta = {
+ desc: {
+ 'ja-JP': 'ドライブの統計を取得します。'
+ },
+
+ params: {
+ span: $.str.or(['day', 'hour']).note({
+ desc: {
+ 'ja-JP': '集計のスパン'
+ }
+ }),
+
+ limit: $.num.optional.range(1, 100).note({
+ default: 30,
+ desc: {
+ 'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
+ }
+ }),
+ }
+};
+
+export default (params: any) => new Promise(async (res, rej) => {
+ const [ps, psErr] = getParams(meta, params);
+ if (psErr) throw psErr;
+
+ const stats = await driveChart.getStats(ps.span as any, ps.limit);
+
+ res(stats);
+});
diff --git a/src/server/api/endpoints/charts/network.ts b/src/server/api/endpoints/charts/network.ts
new file mode 100644
index 0000000000..236674de7c
--- /dev/null
+++ b/src/server/api/endpoints/charts/network.ts
@@ -0,0 +1,33 @@
+import $ from 'cafy';
+import getParams from '../../get-params';
+import { networkChart } from '../../../../services/stats';
+
+export const meta = {
+ desc: {
+ 'ja-JP': 'ネットワークの統計を取得します。'
+ },
+
+ params: {
+ span: $.str.or(['day', 'hour']).note({
+ desc: {
+ 'ja-JP': '集計のスパン'
+ }
+ }),
+
+ limit: $.num.optional.range(1, 100).note({
+ default: 30,
+ desc: {
+ 'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
+ }
+ }),
+ }
+};
+
+export default (params: any) => new Promise(async (res, rej) => {
+ const [ps, psErr] = getParams(meta, params);
+ if (psErr) throw psErr;
+
+ const stats = await networkChart.getStats(ps.span as any, ps.limit);
+
+ res(stats);
+});
diff --git a/src/server/api/endpoints/charts/notes.ts b/src/server/api/endpoints/charts/notes.ts
new file mode 100644
index 0000000000..1efd587519
--- /dev/null
+++ b/src/server/api/endpoints/charts/notes.ts
@@ -0,0 +1,33 @@
+import $ from 'cafy';
+import getParams from '../../get-params';
+import { notesChart } from '../../../../services/stats';
+
+export const meta = {
+ desc: {
+ 'ja-JP': '投稿の統計を取得します。'
+ },
+
+ params: {
+ span: $.str.or(['day', 'hour']).note({
+ desc: {
+ 'ja-JP': '集計のスパン'
+ }
+ }),
+
+ limit: $.num.optional.range(1, 100).note({
+ default: 30,
+ desc: {
+ 'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
+ }
+ }),
+ }
+};
+
+export default (params: any) => new Promise(async (res, rej) => {
+ const [ps, psErr] = getParams(meta, params);
+ if (psErr) throw psErr;
+
+ const stats = await notesChart.getStats(ps.span as any, ps.limit);
+
+ res(stats);
+});
diff --git a/src/server/api/endpoints/charts/users.ts b/src/server/api/endpoints/charts/users.ts
new file mode 100644
index 0000000000..21f5e03523
--- /dev/null
+++ b/src/server/api/endpoints/charts/users.ts
@@ -0,0 +1,33 @@
+import $ from 'cafy';
+import getParams from '../../get-params';
+import { usersChart } from '../../../../services/stats';
+
+export const meta = {
+ desc: {
+ 'ja-JP': 'ユーザーの統計を取得します。'
+ },
+
+ params: {
+ span: $.str.or(['day', 'hour']).note({
+ desc: {
+ 'ja-JP': '集計のスパン'
+ }
+ }),
+
+ limit: $.num.optional.range(1, 100).note({
+ default: 30,
+ desc: {
+ 'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
+ }
+ }),
+ }
+};
+
+export default (params: any) => new Promise(async (res, rej) => {
+ const [ps, psErr] = getParams(meta, params);
+ if (psErr) throw psErr;
+
+ const stats = await usersChart.getStats(ps.span as any, ps.limit);
+
+ res(stats);
+});
diff --git a/src/server/api/private/signup.ts b/src/server/api/private/signup.ts
index 11a599b2b2..99ad9cbccd 100644
--- a/src/server/api/private/signup.ts
+++ b/src/server/api/private/signup.ts
@@ -7,7 +7,7 @@ import generateUserToken from '../common/generate-native-user-token';
import config from '../../../config';
import Meta from '../../../models/meta';
import RegistrationTicket from '../../../models/registration-tickets';
-import { coreChart } from '../../../services/stats';
+import { usersChart } from '../../../services/stats';
if (config.recaptcha) {
recaptcha.init({
@@ -130,7 +130,7 @@ export default async (ctx: Koa.Context) => {
}, { upsert: true });
//#endregion
- coreChart.updateUserStats(account, true);
+ usersChart.update(account, true);
const res = await pack(account, account, {
detail: true,
diff --git a/src/server/index.ts b/src/server/index.ts
index f547668e90..ae989caff5 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -17,7 +17,7 @@ const requestStats = require('request-stats');
import activityPub from './activitypub';
import webFinger from './webfinger';
import config from '../config';
-import { coreChart } from '../services/stats';
+import { networkChart } from '../services/stats';
import apiServer from './api';
// Init app
@@ -104,7 +104,7 @@ export default () => new Promise(resolve => {
const outgoingBytes = queue.reduce((a, b) => a + b.res.bytes, 0);
queue = [];
- coreChart.updateNetworkStats(requests, time, incomingBytes, outgoingBytes);
+ networkChart.update(requests, time, incomingBytes, outgoingBytes);
}, 5000);
//#endregion
});
diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts
index a50f518c2b..e2f48e0d91 100644
--- a/src/services/drive/add-file.ts
+++ b/src/services/drive/add-file.ts
@@ -17,7 +17,7 @@ import { isLocalUser, IUser, IRemoteUser } from '../../models/user';
import delFile from './delete-file';
import config from '../../config';
import { getDriveFileThumbnailBucket } from '../../models/drive-file-thumbnail';
-import { coreChart } from '../stats';
+import { driveChart } from '../stats';
const log = debug('misskey:drive:add-file');
@@ -389,7 +389,7 @@ export default async function(
});
// 統計を更新
- coreChart.updateDriveStats(driveFile, true);
+ driveChart.update(driveFile, true);
return driveFile;
}
diff --git a/src/services/drive/delete-file.ts b/src/services/drive/delete-file.ts
index 1829705bcd..96083a29e1 100644
--- a/src/services/drive/delete-file.ts
+++ b/src/services/drive/delete-file.ts
@@ -2,7 +2,7 @@ import * as Minio from 'minio';
import DriveFile, { DriveFileChunk, IDriveFile } from '../../models/drive-file';
import DriveFileThumbnail, { DriveFileThumbnailChunk } from '../../models/drive-file-thumbnail';
import config from '../../config';
-import { coreChart } from '../stats';
+import { driveChart } from '../stats';
export default async function(file: IDriveFile, isExpired = false) {
if (file.metadata.storage == 'minio') {
@@ -48,5 +48,5 @@ export default async function(file: IDriveFile, isExpired = false) {
//#endregion
// 統計を更新
- coreChart.updateDriveStats(file, false);
+ driveChart.update(file, false);
}
diff --git a/src/services/note/create.ts b/src/services/note/create.ts
index 0f844d4e35..a6ccc6cec0 100644
--- a/src/services/note/create.ts
+++ b/src/services/note/create.ts
@@ -23,7 +23,7 @@ import registerHashtag from '../register-hashtag';
import isQuote from '../../misc/is-quote';
import { TextElementMention } from '../../mfm/parse/elements/mention';
import { TextElementHashtag } from '../../mfm/parse/elements/hashtag';
-import { coreChart } from '../stats';
+import { notesChart } from '../stats';
import { erase, unique } from '../../prelude/array';
import insertNoteUnread from './unread';
@@ -165,7 +165,7 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
}
// 統計を更新
- coreChart.updateNoteStats(note, true);
+ notesChart.update(note, true);
// ハッシュタグ登録
tags.map(tag => registerHashtag(user, tag));
diff --git a/src/services/note/delete.ts b/src/services/note/delete.ts
index a0a86cad25..4041b28d58 100644
--- a/src/services/note/delete.ts
+++ b/src/services/note/delete.ts
@@ -6,7 +6,7 @@ import pack from '../../remote/activitypub/renderer';
import { deliver } from '../../queue';
import Following from '../../models/following';
import renderTombstone from '../../remote/activitypub/renderer/tombstone';
-import { coreChart } from '../stats';
+import { notesChart } from '../stats';
import config from '../../config';
import NoteUnread from '../../models/note-unread';
import read from './read';
@@ -63,5 +63,5 @@ export default async function(user: IUser, note: INote) {
//#endregion
// 統計を更新
- coreChart.updateNoteStats(note, false);
+ notesChart.update(note, false);
}
diff --git a/src/services/stats.ts b/src/services/stats.ts
index 9e471a02e9..0b4106e28c 100644
--- a/src/services/stats.ts
+++ b/src/services/stats.ts
@@ -17,6 +17,11 @@ type ChartDocument<T extends Obj> = {
_id: mongo.ObjectID;
/**
+ * 集計のグループ
+ */
+ group?: any;
+
+ /**
* 集計日時
*/
date: Date;
@@ -40,6 +45,7 @@ abstract class Chart<T> {
constructor(dbCollectionName: string) {
this.collection = db.get<ChartDocument<T>>(dbCollectionName);
this.collection.createIndex({ span: -1, date: -1 }, { unique: true });
+ this.collection.createIndex('group');
}
protected async getCurrentStats(span: Span, group?: Obj): Promise<ChartDocument<T>> {
@@ -55,10 +61,11 @@ abstract class Chart<T> {
null;
// 現在(今日または今のHour)の統計
- const currentStats = await this.collection.findOne(Object.assign({}, {
+ const currentStats = await this.collection.findOne({
+ group: group,
span: span,
date: current
- }, group));
+ });
if (currentStats) {
return currentStats;
@@ -69,9 +76,10 @@ abstract class Chart<T> {
// * 昨日何もチャートを更新するような出来事がなかった場合は、
// * 統計がそもそも作られずドキュメントが存在しないということがあり得るため、
// * 「昨日の」と決め打ちせずに「もっとも最近の」とします
- const mostRecentStats = await this.collection.findOne(Object.assign({}, {
+ const mostRecentStats = await this.collection.findOne({
+ group: group,
span: span
- }, group), {
+ }, {
sort: {
date: -1
}
@@ -81,11 +89,12 @@ abstract class Chart<T> {
// 現在の統計を初期挿入
const data = this.generateEmptyStats(mostRecentStats.data);
- const stats = await this.collection.insert(Object.assign({}, {
+ const stats = await this.collection.insert({
+ group: group,
span: span,
date: current,
data: data
- }, group));
+ });
return stats;
} else {
@@ -95,18 +104,19 @@ abstract class Chart<T> {
// 空の統計を作成
const data = this.generateInitialStats();
- const stats = await this.collection.insert(Object.assign({}, {
+ const stats = await this.collection.insert({
+ group: group,
span: span,
date: current,
data: data
- }, group));
+ });
return stats;
}
}
}
- protected update(inc: Partial<T>, group?: Obj): void {
+ protected inc(inc: Partial<T>, group?: Obj): void {
const query: Obj = {};
const dive = (path: string, x: Obj) => {
@@ -151,12 +161,13 @@ abstract class Chart<T> {
span == 'day' ? new Date(y, m, d - range) :
span == 'hour' ? new Date(y, m, d, h - range) : null;
- const stats = await this.collection.find(Object.assign({
+ const stats = await this.collection.find({
+ group: group,
span: span,
date: {
$gt: gt
}
- }, group), {
+ }, {
sort: {
date: -1
},
@@ -189,377 +200,230 @@ abstract class Chart<T> {
}
}
-type CoreStats = {
- /**
- * ユーザーに関する統計
- */
- users: {
- local: {
- /**
- * 集計期間時点での、全ユーザー数 (ローカル)
- */
- total: number;
-
- /**
- * 増加したユーザー数 (ローカル)
- */
- inc: number;
-
- /**
- * 減少したユーザー数 (ローカル)
- */
- dec: number;
- };
-
- remote: {
- /**
- * 集計期間時点での、全ユーザー数 (リモート)
- */
- total: number;
+//#region Users stats
+/**
+ * ユーザーに関する統計
+ */
+type UsersStats = {
+ local: {
+ /**
+ * 集計期間時点での、全ユーザー数 (ローカル)
+ */
+ total: number;
- /**
- * 増加したユーザー数 (リモート)
- */
- inc: number;
+ /**
+ * 増加したユーザー数 (ローカル)
+ */
+ inc: number;
- /**
- * 減少したユーザー数 (リモート)
- */
- dec: number;
- };
+ /**
+ * 減少したユーザー数 (ローカル)
+ */
+ dec: number;
};
- /**
- * 投稿に関する統計
- */
- notes: {
- local: {
- /**
- * 集計期間時点での、全投稿数 (ローカル)
- */
- total: number;
-
- /**
- * 増加した投稿数 (ローカル)
- */
- inc: number;
+ remote: {
+ /**
+ * 集計期間時点での、全ユーザー数 (リモート)
+ */
+ total: number;
- /**
- * 減少した投稿数 (ローカル)
- */
- dec: number;
+ /**
+ * 増加したユーザー数 (リモート)
+ */
+ inc: number;
- diffs: {
- /**
- * 通常の投稿数の差分 (ローカル)
- */
- normal: number;
+ /**
+ * 減少したユーザー数 (リモート)
+ */
+ dec: number;
+ };
+};
- /**
- * リプライの投稿数の差分 (ローカル)
- */
- reply: number;
+class UsersChart extends Chart<UsersStats> {
+ constructor() {
+ super('usersStats');
+ }
- /**
- * Renoteの投稿数の差分 (ローカル)
- */
- renote: number;
- };
+ protected generateInitialStats(): UsersStats {
+ return {
+ local: {
+ total: 0,
+ inc: 0,
+ dec: 0
+ },
+ remote: {
+ total: 0,
+ inc: 0,
+ dec: 0
+ }
};
+ }
- remote: {
- /**
- * 集計期間時点での、全投稿数 (リモート)
- */
- total: number;
-
- /**
- * 増加した投稿数 (リモート)
- */
- inc: number;
-
- /**
- * 減少した投稿数 (リモート)
- */
- dec: number;
-
- diffs: {
- /**
- * 通常の投稿数の差分 (リモート)
- */
- normal: number;
-
- /**
- * リプライの投稿数の差分 (リモート)
- */
- reply: number;
-
- /**
- * Renoteの投稿数の差分 (リモート)
- */
- renote: number;
- };
+ protected generateEmptyStats(mostRecentStats: UsersStats): UsersStats {
+ return {
+ local: {
+ total: mostRecentStats.local.total,
+ inc: 0,
+ dec: 0
+ },
+ remote: {
+ total: mostRecentStats.remote.total,
+ inc: 0,
+ dec: 0
+ }
};
- };
-
- /**
- * ドライブ(のファイル)に関する統計
- */
- drive: {
- local: {
- /**
- * 集計期間時点での、全ドライブファイル数 (ローカル)
- */
- totalCount: number;
-
- /**
- * 集計期間時点での、全ドライブファイルの合計サイズ (ローカル)
- */
- totalSize: number;
+ }
- /**
- * 増加したドライブファイル数 (ローカル)
- */
- incCount: number;
+ public async update(user: IUser, isAdditional: boolean) {
+ const update: Obj = {};
- /**
- * 増加したドライブ使用量 (ローカル)
- */
- incSize: number;
+ update.total = isAdditional ? 1 : -1;
+ if (isAdditional) {
+ update.inc = 1;
+ } else {
+ update.dec = 1;
+ }
- /**
- * 減少したドライブファイル数 (ローカル)
- */
- decCount: number;
+ await this.inc({
+ [isLocalUser(user) ? 'local' : 'remote']: update
+ });
+ }
+}
- /**
- * 減少したドライブ使用量 (ローカル)
- */
- decSize: number;
- };
+export const usersChart = new UsersChart();
+//#endregion
- remote: {
- /**
- * 集計期間時点での、全ドライブファイル数 (リモート)
- */
- totalCount: number;
+//#region Notes stats
+/**
+ * 投稿に関する統計
+ */
+type NotesStats = {
+ local: {
+ /**
+ * 集計期間時点での、全投稿数 (ローカル)
+ */
+ total: number;
- /**
- * 集計期間時点での、全ドライブファイルの合計サイズ (リモート)
- */
- totalSize: number;
+ /**
+ * 増加した投稿数 (ローカル)
+ */
+ inc: number;
- /**
- * 増加したドライブファイル数 (リモート)
- */
- incCount: number;
+ /**
+ * 減少した投稿数 (ローカル)
+ */
+ dec: number;
+ diffs: {
/**
- * 増加したドライブ使用量 (リモート)
+ * 通常の投稿数の差分 (ローカル)
*/
- incSize: number;
+ normal: number;
/**
- * 減少したドライブファイル数 (リモート)
+ * リプライの投稿数の差分 (ローカル)
*/
- decCount: number;
+ reply: number;
/**
- * 減少したドライブ使用量 (リモート)
+ * Renoteの投稿数の差分 (ローカル)
*/
- decSize: number;
+ renote: number;
};
};
- /**
- * ネットワークに関する統計
- */
- network: {
+ remote: {
/**
- * 受信したリクエスト数
+ * 集計期間時点での、全投稿数 (リモート)
*/
- incomingRequests: number;
+ total: number;
/**
- * 送信したリクエスト数
+ * 増加した投稿数 (リモート)
*/
- outgoingRequests: number;
+ inc: number;
/**
- * 応答時間の合計
- * TIP: (totalTime / incomingRequests) でひとつのリクエストに平均でどれくらいの時間がかかったか知れる
+ * 減少した投稿数 (リモート)
*/
- totalTime: number;
+ dec: number;
- /**
- * 合計受信データ量
- */
- incomingBytes: number;
+ diffs: {
+ /**
+ * 通常の投稿数の差分 (リモート)
+ */
+ normal: number;
- /**
- * 合計送信データ量
- */
- outgoingBytes: number;
+ /**
+ * リプライの投稿数の差分 (リモート)
+ */
+ reply: number;
+
+ /**
+ * Renoteの投稿数の差分 (リモート)
+ */
+ renote: number;
+ };
};
};
-class CoreChart extends Chart<CoreStats> {
+class NotesChart extends Chart<NotesStats> {
constructor() {
- super('coreStats');
+ super('notesStats');
}
- protected generateInitialStats(): CoreStats {
+ protected generateInitialStats(): NotesStats {
return {
- users: {
- local: {
- total: 0,
- inc: 0,
- dec: 0
- },
- remote: {
- total: 0,
- inc: 0,
- dec: 0
+ local: {
+ total: 0,
+ inc: 0,
+ dec: 0,
+ diffs: {
+ normal: 0,
+ reply: 0,
+ renote: 0
}
},
- notes: {
- local: {
- total: 0,
- inc: 0,
- dec: 0,
- diffs: {
- normal: 0,
- reply: 0,
- renote: 0
- }
- },
- remote: {
- total: 0,
- inc: 0,
- dec: 0,
- diffs: {
- normal: 0,
- reply: 0,
- renote: 0
- }
+ remote: {
+ total: 0,
+ inc: 0,
+ dec: 0,
+ diffs: {
+ normal: 0,
+ reply: 0,
+ renote: 0
}
- },
- drive: {
- local: {
- totalCount: 0,
- totalSize: 0,
- incCount: 0,
- incSize: 0,
- decCount: 0,
- decSize: 0
- },
- remote: {
- totalCount: 0,
- totalSize: 0,
- incCount: 0,
- incSize: 0,
- decCount: 0,
- decSize: 0
- }
- },
- network: {
- incomingRequests: 0,
- outgoingRequests: 0,
- totalTime: 0,
- incomingBytes: 0,
- outgoingBytes: 0
}
};
}
- protected generateEmptyStats(mostRecentStats: CoreStats): CoreStats {
+ protected generateEmptyStats(mostRecentStats: NotesStats): NotesStats {
return {
- users: {
- local: {
- total: mostRecentStats.users.local.total,
- inc: 0,
- dec: 0
- },
- remote: {
- total: mostRecentStats.users.remote.total,
- inc: 0,
- dec: 0
- }
- },
- notes: {
- local: {
- total: mostRecentStats.notes.local.total,
- inc: 0,
- dec: 0,
- diffs: {
- normal: 0,
- reply: 0,
- renote: 0
- }
- },
- remote: {
- total: mostRecentStats.notes.remote.total,
- inc: 0,
- dec: 0,
- diffs: {
- normal: 0,
- reply: 0,
- renote: 0
- }
+ local: {
+ total: mostRecentStats.local.total,
+ inc: 0,
+ dec: 0,
+ diffs: {
+ normal: 0,
+ reply: 0,
+ renote: 0
}
},
- drive: {
- local: {
- totalCount: mostRecentStats.drive.local.totalCount,
- totalSize: mostRecentStats.drive.local.totalSize,
- incCount: 0,
- incSize: 0,
- decCount: 0,
- decSize: 0
- },
- remote: {
- totalCount: mostRecentStats.drive.remote.totalCount,
- totalSize: mostRecentStats.drive.remote.totalSize,
- incCount: 0,
- incSize: 0,
- decCount: 0,
- decSize: 0
+ remote: {
+ total: mostRecentStats.remote.total,
+ inc: 0,
+ dec: 0,
+ diffs: {
+ normal: 0,
+ reply: 0,
+ renote: 0
}
- },
- network: {
- incomingRequests: 0,
- outgoingRequests: 0,
- totalTime: 0,
- incomingBytes: 0,
- outgoingBytes: 0
}
};
}
- public async updateUserStats(user: IUser, isAdditional: boolean) {
- const origin = isLocalUser(user) ? 'local' : 'remote';
-
- const update: Obj = {};
-
- update.total = isAdditional ? 1 : -1;
- if (isAdditional) {
- update.inc = 1;
- } else {
- update.dec = 1;
- }
-
- const inc: Obj = {
- users: {}
- };
-
- inc.users[origin] = update;
-
- await this.update(inc);
- }
-
- public async updateNoteStats(note: INote, isAdditional: boolean) {
- const origin = isLocalUser(note._user) ? 'local' : 'remote';
-
+ public async update(note: INote, isAdditional: boolean) {
const update: Obj = {};
update.total = isAdditional ? 1 : -1;
@@ -578,18 +442,133 @@ class CoreChart extends Chart<CoreStats> {
update.diffs.normal = isAdditional ? 1 : -1;
}
- const inc: Obj = {
- notes: {}
- };
+ await this.inc({
+ [isLocalUser(note._user) ? 'local' : 'remote']: update
+ });
+ }
+}
+
+export const notesChart = new NotesChart();
+//#endregion
+
+//#region Drive stats
+/**
+ * ドライブに関する統計
+ */
+type DriveStats = {
+ local: {
+ /**
+ * 集計期間時点での、全ドライブファイル数 (ローカル)
+ */
+ totalCount: number;
+
+ /**
+ * 集計期間時点での、全ドライブファイルの合計サイズ (ローカル)
+ */
+ totalSize: number;
+
+ /**
+ * 増加したドライブファイル数 (ローカル)
+ */
+ incCount: number;
+
+ /**
+ * 増加したドライブ使用量 (ローカル)
+ */
+ incSize: number;
+
+ /**
+ * 減少したドライブファイル数 (ローカル)
+ */
+ decCount: number;
+
+ /**
+ * 減少したドライブ使用量 (ローカル)
+ */
+ decSize: number;
+ };
+
+ remote: {
+ /**
+ * 集計期間時点での、全ドライブファイル数 (リモート)
+ */
+ totalCount: number;
+
+ /**
+ * 集計期間時点での、全ドライブファイルの合計サイズ (リモート)
+ */
+ totalSize: number;
+
+ /**
+ * 増加したドライブファイル数 (リモート)
+ */
+ incCount: number;
+
+ /**
+ * 増加したドライブ使用量 (リモート)
+ */
+ incSize: number;
- inc.notes[origin] = update;
+ /**
+ * 減少したドライブファイル数 (リモート)
+ */
+ decCount: number;
+
+ /**
+ * 減少したドライブ使用量 (リモート)
+ */
+ decSize: number;
+ };
+};
- await this.update(inc);
+class DriveChart extends Chart<DriveStats> {
+ constructor() {
+ super('driveStats');
+ }
+
+ protected generateInitialStats(): DriveStats {
+ return {
+ local: {
+ totalCount: 0,
+ totalSize: 0,
+ incCount: 0,
+ incSize: 0,
+ decCount: 0,
+ decSize: 0
+ },
+ remote: {
+ totalCount: 0,
+ totalSize: 0,
+ incCount: 0,
+ incSize: 0,
+ decCount: 0,
+ decSize: 0
+ }
+ };
}
- public async updateDriveStats(file: IDriveFile, isAdditional: boolean) {
- const origin = isLocalUser(file.metadata._user) ? 'local' : 'remote';
+ protected generateEmptyStats(mostRecentStats: DriveStats): DriveStats {
+ return {
+ local: {
+ totalCount: mostRecentStats.local.totalCount,
+ totalSize: mostRecentStats.local.totalSize,
+ incCount: 0,
+ incSize: 0,
+ decCount: 0,
+ decSize: 0
+ },
+ remote: {
+ totalCount: mostRecentStats.remote.totalCount,
+ totalSize: mostRecentStats.remote.totalSize,
+ incCount: 0,
+ incSize: 0,
+ decCount: 0,
+ decSize: 0
+ }
+ };
+ }
+ public async update(file: IDriveFile, isAdditional: boolean) {
const update: Obj = {};
update.totalCount = isAdditional ? 1 : -1;
@@ -602,27 +581,83 @@ class CoreChart extends Chart<CoreStats> {
update.decSize = file.length;
}
- const inc: Obj = {
- drive: {}
- };
+ await this.inc({
+ [isLocalUser(file.metadata._user) ? 'local' : 'remote']: update
+ });
+ }
+}
+
+export const driveChart = new DriveChart();
+//#endregion
+
+//#region Network stats
+/**
+ * ネットワークに関する統計
+ */
+type NetworkStats = {
+ /**
+ * 受信したリクエスト数
+ */
+ incomingRequests: number;
+
+ /**
+ * 送信したリクエスト数
+ */
+ outgoingRequests: number;
+
+ /**
+ * 応答時間の合計
+ * TIP: (totalTime / incomingRequests) でひとつのリクエストに平均でどれくらいの時間がかかったか知れる
+ */
+ totalTime: number;
+
+ /**
+ * 合計受信データ量
+ */
+ incomingBytes: number;
- inc.drive[origin] = update;
+ /**
+ * 合計送信データ量
+ */
+ outgoingBytes: number;
+};
- await this.update(inc);
+class NetworkChart extends Chart<NetworkStats> {
+ constructor() {
+ super('networkStats');
}
- public async updateNetworkStats(incomingRequests: number, time: number, incomingBytes: number, outgoingBytes: number) {
- const inc: Partial<CoreStats> = {
- network: {
- incomingRequests: incomingRequests,
- totalTime: time,
- incomingBytes: incomingBytes,
- outgoingBytes: outgoingBytes
- }
+ protected generateInitialStats(): NetworkStats {
+ return {
+ incomingRequests: 0,
+ outgoingRequests: 0,
+ totalTime: 0,
+ incomingBytes: 0,
+ outgoingBytes: 0
+ };
+ }
+
+ protected generateEmptyStats(mostRecentStats: NetworkStats): NetworkStats {
+ return {
+ incomingRequests: 0,
+ outgoingRequests: 0,
+ totalTime: 0,
+ incomingBytes: 0,
+ outgoingBytes: 0
+ };
+ }
+
+ public async update(incomingRequests: number, time: number, incomingBytes: number, outgoingBytes: number) {
+ const inc: Partial<NetworkStats> = {
+ incomingRequests: incomingRequests,
+ totalTime: time,
+ incomingBytes: incomingBytes,
+ outgoingBytes: outgoingBytes
};
- await this.update(inc);
+ await this.inc(inc);
}
}
-export const coreChart = new CoreChart();
+export const networkChart = new NetworkChart();
+//#endregion