1 import { mapSeries } from 'bluebird'
2 import { CONFIG } from '@server/initializers/config'
3 import { ActorFollowModel } from '@server/models/actor/actor-follow'
4 import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy'
5 import { UserModel } from '@server/models/user/user'
6 import { VideoModel } from '@server/models/video/video'
7 import { VideoChannelModel } from '@server/models/video/video-channel'
8 import { VideoCommentModel } from '@server/models/video/video-comment'
9 import { VideoFileModel } from '@server/models/video/video-file'
10 import { VideoPlaylistModel } from '@server/models/video/video-playlist'
11 import { ActivityType, ServerStats, VideoRedundancyStrategyWithManual } from '@shared/models'
15 private static instance: StatsManager
17 private readonly instanceStartDate = new Date()
19 private inboxMessages = {
24 errorsPerType: this.buildAPPerType(),
25 successesPerType: this.buildAPPerType()
28 private constructor () {}
30 updateInboxWaiting (inboxMessagesWaiting: number) {
31 this.inboxMessages.waiting = inboxMessagesWaiting
34 addInboxProcessedSuccess (type: ActivityType) {
35 this.inboxMessages.processed++
36 this.inboxMessages.successes++
37 this.inboxMessages.successesPerType[type]++
40 addInboxProcessedError (type: ActivityType) {
41 this.inboxMessages.processed++
42 this.inboxMessages.errors++
43 this.inboxMessages.errorsPerType[type]++
47 const { totalLocalVideos, totalLocalVideoViews, totalVideos } = await VideoModel.getStats()
48 const { totalLocalVideoComments, totalVideoComments } = await VideoCommentModel.getStats()
49 const { totalUsers, totalDailyActiveUsers, totalWeeklyActiveUsers, totalMonthlyActiveUsers } = await UserModel.getStats()
50 const { totalInstanceFollowers, totalInstanceFollowing } = await ActorFollowModel.getStats()
51 const { totalLocalVideoFilesSize } = await VideoFileModel.getStats()
53 totalLocalVideoChannels,
54 totalLocalDailyActiveVideoChannels,
55 totalLocalWeeklyActiveVideoChannels,
56 totalLocalMonthlyActiveVideoChannels
57 } = await VideoChannelModel.getStats()
58 const { totalLocalPlaylists } = await VideoPlaylistModel.getStats()
60 const videosRedundancyStats = await this.buildRedundancyStats()
62 const data: ServerStats = {
64 totalDailyActiveUsers,
65 totalWeeklyActiveUsers,
66 totalMonthlyActiveUsers,
70 totalLocalVideoComments,
71 totalLocalVideoFilesSize,
76 totalLocalVideoChannels,
77 totalLocalDailyActiveVideoChannels,
78 totalLocalWeeklyActiveVideoChannels,
79 totalLocalMonthlyActiveVideoChannels,
83 totalInstanceFollowers,
84 totalInstanceFollowing,
86 videosRedundancy: videosRedundancyStats,
88 ...this.buildAPStats()
94 private buildActivityPubMessagesProcessedPerSecond () {
95 const now = new Date()
96 const startedSeconds = (now.getTime() - this.instanceStartDate.getTime()) / 1000
98 return this.inboxMessages.processed / startedSeconds
101 private buildRedundancyStats () {
102 const strategies = CONFIG.REDUNDANCY.VIDEOS.STRATEGIES
104 strategy: r.strategy as VideoRedundancyStrategyWithManual,
108 strategies.push({ strategy: 'manual', size: null })
110 return mapSeries(strategies, r => {
111 return VideoRedundancyModel.getStats(r.strategy)
112 .then(stats => Object.assign(stats, { strategy: r.strategy, totalSize: r.size }))
116 private buildAPPerType () {
133 private buildAPStats () {
135 totalActivityPubMessagesProcessed: this.inboxMessages.processed,
137 totalActivityPubMessagesSuccesses: this.inboxMessages.successes,
139 // Dirty, but simpler and with type checking
140 totalActivityPubCreateMessagesSuccesses: this.inboxMessages.successesPerType.Create,
141 totalActivityPubUpdateMessagesSuccesses: this.inboxMessages.successesPerType.Update,
142 totalActivityPubDeleteMessagesSuccesses: this.inboxMessages.successesPerType.Delete,
143 totalActivityPubFollowMessagesSuccesses: this.inboxMessages.successesPerType.Follow,
144 totalActivityPubAcceptMessagesSuccesses: this.inboxMessages.successesPerType.Accept,
145 totalActivityPubRejectMessagesSuccesses: this.inboxMessages.successesPerType.Reject,
146 totalActivityPubAnnounceMessagesSuccesses: this.inboxMessages.successesPerType.Announce,
147 totalActivityPubUndoMessagesSuccesses: this.inboxMessages.successesPerType.Undo,
148 totalActivityPubLikeMessagesSuccesses: this.inboxMessages.successesPerType.Like,
149 totalActivityPubDislikeMessagesSuccesses: this.inboxMessages.successesPerType.Dislike,
150 totalActivityPubFlagMessagesSuccesses: this.inboxMessages.successesPerType.Flag,
151 totalActivityPubViewMessagesSuccesses: this.inboxMessages.successesPerType.View,
153 totalActivityPubCreateMessagesErrors: this.inboxMessages.errorsPerType.Create,
154 totalActivityPubUpdateMessagesErrors: this.inboxMessages.errorsPerType.Update,
155 totalActivityPubDeleteMessagesErrors: this.inboxMessages.errorsPerType.Delete,
156 totalActivityPubFollowMessagesErrors: this.inboxMessages.errorsPerType.Follow,
157 totalActivityPubAcceptMessagesErrors: this.inboxMessages.errorsPerType.Accept,
158 totalActivityPubRejectMessagesErrors: this.inboxMessages.errorsPerType.Reject,
159 totalActivityPubAnnounceMessagesErrors: this.inboxMessages.errorsPerType.Announce,
160 totalActivityPubUndoMessagesErrors: this.inboxMessages.errorsPerType.Undo,
161 totalActivityPubLikeMessagesErrors: this.inboxMessages.errorsPerType.Like,
162 totalActivityPubDislikeMessagesErrors: this.inboxMessages.errorsPerType.Dislike,
163 totalActivityPubFlagMessagesErrors: this.inboxMessages.errorsPerType.Flag,
164 totalActivityPubViewMessagesErrors: this.inboxMessages.errorsPerType.View,
166 totalActivityPubMessagesErrors: this.inboxMessages.errors,
168 activityPubMessagesProcessedPerSecond: this.buildActivityPubMessagesProcessedPerSecond(),
169 totalActivityPubMessagesWaiting: this.inboxMessages.waiting
173 static get Instance () {
174 return this.instance || (this.instance = new this())
178 // ---------------------------------------------------------------------------