1時間単位での集計を追加
This commit is contained in:
		
							parent
							
								
									a62e2b83ff
								
							
						
					
					
						commit
						8fc1e07136
					
				
					 5 changed files with 245 additions and 77 deletions
				
			
		
							
								
								
									
										144
									
								
								cli/migration/8.0.0.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								cli/migration/8.0.0.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,144 @@ | |||
| const { default: Stats } = require('../../built/models/stats'); | ||||
| const { default: User } = require('../../built/models/user'); | ||||
| const { default: Note } = require('../../built/models/note'); | ||||
| const { default: DriveFile } = require('../../built/models/drive-file'); | ||||
| 
 | ||||
| const now = new Date(); | ||||
| const y = now.getFullYear(); | ||||
| const m = now.getMonth(); | ||||
| const d = now.getDate(); | ||||
| const h = now.getHours(); | ||||
| const date = new Date(y, m, d, h); | ||||
| 
 | ||||
| async function main() { | ||||
| 	await Stats.update({}, { | ||||
| 		$set: { | ||||
| 			span: 'day' | ||||
| 		} | ||||
| 	}, { | ||||
| 		multi: true | ||||
| 	}); | ||||
| 
 | ||||
| 	const localUsersCount = await User.count({ | ||||
| 		host: null | ||||
| 	}); | ||||
| 
 | ||||
| 	const remoteUsersCount = await User.count({ | ||||
| 		host: { $ne: null } | ||||
| 	}); | ||||
| 
 | ||||
| 	const localNotesCount = await Note.count({ | ||||
| 		'_user.host': null | ||||
| 	}); | ||||
| 
 | ||||
| 	const remoteNotesCount = await Note.count({ | ||||
| 		'_user.host': { $ne: null } | ||||
| 	}); | ||||
| 
 | ||||
| 	const localDriveFilesCount = await DriveFile.count({ | ||||
| 		'metadata._user.host': null | ||||
| 	}); | ||||
| 
 | ||||
| 	const remoteDriveFilesCount = await DriveFile.count({ | ||||
| 		'metadata._user.host': { $ne: null } | ||||
| 	}); | ||||
| 
 | ||||
| 	const localDriveFilesSize = await DriveFile | ||||
| 		.aggregate([{ | ||||
| 			$match: { | ||||
| 				'metadata._user.host': null, | ||||
| 				'metadata.deletedAt': { $exists: false } | ||||
| 			} | ||||
| 		}, { | ||||
| 			$project: { | ||||
| 				length: true | ||||
| 			} | ||||
| 		}, { | ||||
| 			$group: { | ||||
| 				_id: null, | ||||
| 				usage: { $sum: '$length' } | ||||
| 			} | ||||
| 		}]) | ||||
| 		.then(aggregates => { | ||||
| 			if (aggregates.length > 0) { | ||||
| 				return aggregates[0].usage; | ||||
| 			} | ||||
| 			return 0; | ||||
| 		}); | ||||
| 
 | ||||
| 	const remoteDriveFilesSize = await DriveFile | ||||
| 		.aggregate([{ | ||||
| 			$match: { | ||||
| 				'metadata._user.host': { $ne: null }, | ||||
| 				'metadata.deletedAt': { $exists: false } | ||||
| 			} | ||||
| 		}, { | ||||
| 			$project: { | ||||
| 				length: true | ||||
| 			} | ||||
| 		}, { | ||||
| 			$group: { | ||||
| 				_id: null, | ||||
| 				usage: { $sum: '$length' } | ||||
| 			} | ||||
| 		}]) | ||||
| 		.then(aggregates => { | ||||
| 			if (aggregates.length > 0) { | ||||
| 				return aggregates[0].usage; | ||||
| 			} | ||||
| 			return 0; | ||||
| 		}); | ||||
| 
 | ||||
| 	await Stats.insert({ | ||||
| 		date: date, | ||||
| 		span: 'hour', | ||||
| 		users: { | ||||
| 			local: { | ||||
| 				total: localUsersCount, | ||||
| 				diff: 0 | ||||
| 			}, | ||||
| 			remote: { | ||||
| 				total: remoteUsersCount, | ||||
| 				diff: 0 | ||||
| 			} | ||||
| 		}, | ||||
| 		notes: { | ||||
| 			local: { | ||||
| 				total: localNotesCount, | ||||
| 				diff: 0, | ||||
| 				diffs: { | ||||
| 					normal: 0, | ||||
| 					reply: 0, | ||||
| 					renote: 0 | ||||
| 				} | ||||
| 			}, | ||||
| 			remote: { | ||||
| 				total: remoteNotesCount, | ||||
| 				diff: 0, | ||||
| 				diffs: { | ||||
| 					normal: 0, | ||||
| 					reply: 0, | ||||
| 					renote: 0 | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		drive: { | ||||
| 			local: { | ||||
| 				totalCount: localDriveFilesCount, | ||||
| 				totalSize: localDriveFilesSize, | ||||
| 				diffCount: 0, | ||||
| 				diffSize: 0 | ||||
| 			}, | ||||
| 			remote: { | ||||
| 				totalCount: remoteDriveFilesCount, | ||||
| 				totalSize: remoteDriveFilesSize, | ||||
| 				diffCount: 0, | ||||
| 				diffSize: 0 | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| 	console.log('done'); | ||||
| } | ||||
| 
 | ||||
| main(); | ||||
|  | @ -1,7 +1,7 @@ | |||
| { | ||||
| 	"name": "misskey", | ||||
| 	"author": "syuilo <i@syuilo.com>", | ||||
| 	"version": "7.4.1", | ||||
| 	"version": "8.0.0", | ||||
| 	"clientVersion": "1.0.8790", | ||||
| 	"codename": "nighthike", | ||||
| 	"main": "./built/index.js", | ||||
|  |  | |||
|  | @ -10,6 +10,8 @@ export interface IStats { | |||
| 
 | ||||
| 	date: Date; | ||||
| 
 | ||||
| 	span: 'day' | 'hour'; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * ユーザーに関する統計 | ||||
| 	 */ | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ export default (params: any) => new Promise(async (res, rej) => { | |||
| 	const d = now.getDate(); | ||||
| 
 | ||||
| 	const stats = await Stats.find({ | ||||
| 		span: 'day', | ||||
| 		date: { | ||||
| 			$gt: new Date(y - 1, m, d) | ||||
| 		} | ||||
|  | @ -44,6 +45,7 @@ export default (params: any) => new Promise(async (res, rej) => { | |||
| 			} else { | ||||
| 				chart.unshift({ | ||||
| 					date: day, | ||||
| 					span: 'day', | ||||
| 					users: { | ||||
| 						local: { | ||||
| 							total: 0, | ||||
|  |  | |||
|  | @ -5,89 +5,46 @@ import { IDriveFile } from '../models/drive-file'; | |||
| 
 | ||||
| type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; | ||||
| 
 | ||||
| async function getTodayStats(): Promise<IStats> { | ||||
| async function getCurrentStats(span: 'day' | 'hour'): Promise<IStats> { | ||||
| 	const now = new Date(); | ||||
| 	const y = now.getFullYear(); | ||||
| 	const m = now.getMonth(); | ||||
| 	const d = now.getDate(); | ||||
| 	const today = new Date(y, m, d); | ||||
| 	const h = now.getHours(); | ||||
| 
 | ||||
| 	// 今日の統計
 | ||||
| 	const todayStats = await Stats.findOne({ | ||||
| 		date: today | ||||
| 	const current = | ||||
| 		span == 'day' ? new Date(y, m, d) : | ||||
| 		span == 'hour' ? new Date(y, m, d, h) : | ||||
| 		null; | ||||
| 
 | ||||
| 	// 現在(今日または今のHour)の統計
 | ||||
| 	const currentStats = await Stats.findOne({ | ||||
| 		span: span, | ||||
| 		date: current | ||||
| 	}); | ||||
| 
 | ||||
| 	// 日付が変わってから、初めてのチャート更新なら
 | ||||
| 	if (todayStats == null) { | ||||
| 	if (currentStats) { | ||||
| 		return currentStats; | ||||
| 	} else { | ||||
| 		// 集計期間が変わってから、初めてのチャート更新なら
 | ||||
| 		// 最も最近の統計を持ってくる
 | ||||
| 		// * 例えば集計期間が「日」である場合で考えると、
 | ||||
| 		// * 昨日何もチャートを更新するような出来事がなかった場合は、
 | ||||
| 		//   統計がそもそも作られずドキュメントが存在しないということがあり得るため、
 | ||||
| 		//   「昨日の」と決め打ちせずに「もっとも最近の」とします
 | ||||
| 		const mostRecentStats = await Stats.findOne({}, { | ||||
| 		// * 統計がそもそも作られずドキュメントが存在しないということがあり得るため、
 | ||||
| 		// * 「昨日の」と決め打ちせずに「もっとも最近の」とします
 | ||||
| 		const mostRecentStats = await Stats.findOne({ | ||||
| 			span: span | ||||
| 		}, { | ||||
| 			sort: { | ||||
| 				date: -1 | ||||
| 			} | ||||
| 		}); | ||||
| 
 | ||||
| 		// 統計が存在しなかったら
 | ||||
| 		// * Misskeyインスタンスを建てて初めてのチャート更新時など
 | ||||
| 		if (mostRecentStats == null) { | ||||
| 			// 空の統計を作成
 | ||||
| 		if (mostRecentStats) { | ||||
| 			// 現在の統計を初期挿入
 | ||||
| 			const data: Omit<IStats, '_id'> = { | ||||
| 				date: today, | ||||
| 				users: { | ||||
| 					local: { | ||||
| 						total: 0, | ||||
| 						diff: 0 | ||||
| 					}, | ||||
| 					remote: { | ||||
| 						total: 0, | ||||
| 						diff: 0 | ||||
| 					} | ||||
| 				}, | ||||
| 				notes: { | ||||
| 					local: { | ||||
| 						total: 0, | ||||
| 						diff: 0, | ||||
| 						diffs: { | ||||
| 							normal: 0, | ||||
| 							reply: 0, | ||||
| 							renote: 0 | ||||
| 						} | ||||
| 					}, | ||||
| 					remote: { | ||||
| 						total: 0, | ||||
| 						diff: 0, | ||||
| 						diffs: { | ||||
| 							normal: 0, | ||||
| 							reply: 0, | ||||
| 							renote: 0 | ||||
| 						} | ||||
| 					} | ||||
| 				}, | ||||
| 				drive: { | ||||
| 					local: { | ||||
| 						totalCount: 0, | ||||
| 						totalSize: 0, | ||||
| 						diffCount: 0, | ||||
| 						diffSize: 0 | ||||
| 					}, | ||||
| 					remote: { | ||||
| 						totalCount: 0, | ||||
| 						totalSize: 0, | ||||
| 						diffCount: 0, | ||||
| 						diffSize: 0 | ||||
| 					} | ||||
| 				} | ||||
| 			}; | ||||
| 
 | ||||
| 			const stats = await Stats.insert(data); | ||||
| 
 | ||||
| 			return stats; | ||||
| 		} else { | ||||
| 			// 今日の統計を初期挿入
 | ||||
| 			const data: Omit<IStats, '_id'> = { | ||||
| 				date: today, | ||||
| 				span: span, | ||||
| 				date: current, | ||||
| 				users: { | ||||
| 					local: { | ||||
| 						total: mostRecentStats.users.local.total, | ||||
|  | @ -136,20 +93,83 @@ async function getTodayStats(): Promise<IStats> { | |||
| 
 | ||||
| 			const stats = await Stats.insert(data); | ||||
| 
 | ||||
| 			return stats; | ||||
| 		} else { | ||||
| 			// 統計が存在しなかったら
 | ||||
| 			// * Misskeyインスタンスを建てて初めてのチャート更新時など
 | ||||
| 
 | ||||
| 			// 空の統計を作成
 | ||||
| 			const emptyStat: Omit<IStats, '_id'> = { | ||||
| 				span: span, | ||||
| 				date: current, | ||||
| 				users: { | ||||
| 					local: { | ||||
| 						total: 0, | ||||
| 						diff: 0 | ||||
| 					}, | ||||
| 					remote: { | ||||
| 						total: 0, | ||||
| 						diff: 0 | ||||
| 					} | ||||
| 				}, | ||||
| 				notes: { | ||||
| 					local: { | ||||
| 						total: 0, | ||||
| 						diff: 0, | ||||
| 						diffs: { | ||||
| 							normal: 0, | ||||
| 							reply: 0, | ||||
| 							renote: 0 | ||||
| 						} | ||||
| 					}, | ||||
| 					remote: { | ||||
| 						total: 0, | ||||
| 						diff: 0, | ||||
| 						diffs: { | ||||
| 							normal: 0, | ||||
| 							reply: 0, | ||||
| 							renote: 0 | ||||
| 						} | ||||
| 					} | ||||
| 				}, | ||||
| 				drive: { | ||||
| 					local: { | ||||
| 						totalCount: 0, | ||||
| 						totalSize: 0, | ||||
| 						diffCount: 0, | ||||
| 						diffSize: 0 | ||||
| 					}, | ||||
| 					remote: { | ||||
| 						totalCount: 0, | ||||
| 						totalSize: 0, | ||||
| 						diffCount: 0, | ||||
| 						diffSize: 0 | ||||
| 					} | ||||
| 				} | ||||
| 			}; | ||||
| 
 | ||||
| 			const stats = await Stats.insert(emptyStat); | ||||
| 
 | ||||
| 			return stats; | ||||
| 		} | ||||
| 	} else { | ||||
| 		return todayStats; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| async function update(inc: any) { | ||||
| 	const stats = await getTodayStats(); | ||||
| function update(inc: any) { | ||||
| 	getCurrentStats('day').then(stats => { | ||||
| 		Stats.findOneAndUpdate({ | ||||
| 			_id: stats._id | ||||
| 		}, { | ||||
| 			$inc: inc | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| 	await Stats.findOneAndUpdate({ | ||||
| 		_id: stats._id | ||||
| 	}, { | ||||
| 		$inc: inc | ||||
| 	getCurrentStats('hour').then(stats => { | ||||
| 		Stats.findOneAndUpdate({ | ||||
| 			_id: stats._id | ||||
| 		}, { | ||||
| 			$inc: inc | ||||
| 		}); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue