1 import { CONFIG } from '@server/initializers/config'
2 import { UserModel } from '@server/models/account/user'
3 import { ActorFollowModel } from '@server/models/activitypub/actor-follow'
4 import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy'
5 import { VideoModel } from '@server/models/video/video'
6 import { VideoChannelModel } from '@server/models/video/video-channel'
7 import { VideoCommentModel } from '@server/models/video/video-comment'
8 import { VideoFileModel } from '@server/models/video/video-file'
9 import { VideoPlaylistModel } from '@server/models/video/video-playlist'
10 import { ActivityType, ServerStats, VideoRedundancyStrategyWithManual } from '@shared/models'
14 private static instance: StatsManager
16 private readonly instanceStartDate = new Date()
18 private inboxMessages = {
23 errorsPerType: this.buildAPPerType(),
24 successesPerType: this.buildAPPerType()
27 private constructor () {}
29 updateInboxWaiting (inboxMessagesWaiting: number) {
30 this.inboxMessages.waiting = inboxMessagesWaiting
33 addInboxProcessedSuccess (type: ActivityType) {
34 this.inboxMessages.processed++
35 this.inboxMessages.successes++
36 this.inboxMessages.successesPerType[type]++
39 addInboxProcessedError (type: ActivityType) {
40 this.inboxMessages.processed++
41 this.inboxMessages.errors++
42 this.inboxMessages.errorsPerType[type]++
46 const { totalLocalVideos, totalLocalVideoViews, totalVideos } = await VideoModel.getStats()
47 const { totalLocalVideoComments, totalVideoComments } = await VideoCommentModel.getStats()
48 const { totalUsers, totalDailyActiveUsers, totalWeeklyActiveUsers, totalMonthlyActiveUsers } = await UserModel.getStats()
49 const { totalInstanceFollowers, totalInstanceFollowing } = await ActorFollowModel.getStats()
50 const { totalLocalVideoFilesSize } = await VideoFileModel.getStats()
52 totalLocalVideoChannels,
53 totalLocalDailyActiveVideoChannels,
54 totalLocalWeeklyActiveVideoChannels,
55 totalLocalMonthlyActiveVideoChannels
56 } = await VideoChannelModel.getStats()
57 const { totalLocalPlaylists } = await VideoPlaylistModel.getStats()
59 const videosRedundancyStats = await this.buildRedundancyStats()
61 const data: ServerStats = {
63 totalDailyActiveUsers,
64 totalWeeklyActiveUsers,
65 totalMonthlyActiveUsers,
69 totalLocalVideoComments,
70 totalLocalVideoFilesSize,
75 totalLocalVideoChannels,
76 totalLocalDailyActiveVideoChannels,
77 totalLocalWeeklyActiveVideoChannels,
78 totalLocalMonthlyActiveVideoChannels,
82 totalInstanceFollowers,
83 totalInstanceFollowing,
85 videosRedundancy: videosRedundancyStats,
87 ...this.buildAPStats()
93 private buildActivityPubMessagesProcessedPerSecond () {
94 const now = new Date()
95 const startedSeconds = (now.getTime() - this.instanceStartDate.getTime()) / 1000
97 return this.inboxMessages.processed / startedSeconds
100 private buildRedundancyStats () {
101 const strategies = CONFIG.REDUNDANCY.VIDEOS.STRATEGIES
103 strategy: r.strategy as VideoRedundancyStrategyWithManual,
107 strategies.push({ strategy: 'manual', size: null })
110 strategies.map(r => {
111 return VideoRedundancyModel.getStats(r.strategy)
112 .then(stats => Object.assign(stats, { strategy: r.strategy, totalSize: r.size }))
117 private buildAPPerType () {
134 private buildAPStats () {
136 totalActivityPubMessagesProcessed: this.inboxMessages.processed,
138 totalActivityPubMessagesSuccesses: this.inboxMessages.successes,
140 // Dirty, but simpler and with type checking
141 totalActivityPubCreateMessagesSuccesses: this.inboxMessages.successesPerType.Create,
142 totalActivityPubUpdateMessagesSuccesses: this.inboxMessages.successesPerType.Update,
143 totalActivityPubDeleteMessagesSuccesses: this.inboxMessages.successesPerType.Delete,
144 totalActivityPubFollowMessagesSuccesses: this.inboxMessages.successesPerType.Follow,
145 totalActivityPubAcceptMessagesSuccesses: this.inboxMessages.successesPerType.Accept,
146 totalActivityPubRejectMessagesSuccesses: this.inboxMessages.successesPerType.Reject,
147 totalActivityPubAnnounceMessagesSuccesses: this.inboxMessages.successesPerType.Announce,
148 totalActivityPubUndoMessagesSuccesses: this.inboxMessages.successesPerType.Undo,
149 totalActivityPubLikeMessagesSuccesses: this.inboxMessages.successesPerType.Like,
150 totalActivityPubDislikeMessagesSuccesses: this.inboxMessages.successesPerType.Dislike,
151 totalActivityPubFlagMessagesSuccesses: this.inboxMessages.successesPerType.Flag,
152 totalActivityPubViewMessagesSuccesses: this.inboxMessages.successesPerType.View,
154 totalActivityPubCreateMessagesErrors: this.inboxMessages.errorsPerType.Create,
155 totalActivityPubUpdateMessagesErrors: this.inboxMessages.errorsPerType.Update,
156 totalActivityPubDeleteMessagesErrors: this.inboxMessages.errorsPerType.Delete,
157 totalActivityPubFollowMessagesErrors: this.inboxMessages.errorsPerType.Follow,
158 totalActivityPubAcceptMessagesErrors: this.inboxMessages.errorsPerType.Accept,
159 totalActivityPubRejectMessagesErrors: this.inboxMessages.errorsPerType.Reject,
160 totalActivityPubAnnounceMessagesErrors: this.inboxMessages.errorsPerType.Announce,
161 totalActivityPubUndoMessagesErrors: this.inboxMessages.errorsPerType.Undo,
162 totalActivityPubLikeMessagesErrors: this.inboxMessages.errorsPerType.Like,
163 totalActivityPubDislikeMessagesErrors: this.inboxMessages.errorsPerType.Dislike,
164 totalActivityPubFlagMessagesErrors: this.inboxMessages.errorsPerType.Flag,
165 totalActivityPubViewMessagesErrors: this.inboxMessages.errorsPerType.View,
167 totalActivityPubMessagesErrors: this.inboxMessages.errors,
169 activityPubMessagesProcessedPerSecond: this.buildActivityPubMessagesProcessedPerSecond(),
170 totalActivityPubMessagesWaiting: this.inboxMessages.waiting
174 static get Instance () {
175 return this.instance || (this.instance = new this())
179 // ---------------------------------------------------------------------------