Init commit
This commit is contained in:
237
server/core/lib/stat-manager.ts
Normal file
237
server/core/lib/stat-manager.ts
Normal file
@@ -0,0 +1,237 @@
|
||||
import Bluebird from 'bluebird'
|
||||
import { CONFIG } from '@server/initializers/config.js'
|
||||
import { ActorFollowModel } from '@server/models/actor/actor-follow.js'
|
||||
import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy.js'
|
||||
import { UserModel } from '@server/models/user/user.js'
|
||||
import { VideoModel } from '@server/models/video/video.js'
|
||||
import { VideoChannelModel } from '@server/models/video/video-channel.js'
|
||||
import { VideoCommentModel } from '@server/models/video/video-comment.js'
|
||||
import { VideoFileModel } from '@server/models/video/video-file.js'
|
||||
import { VideoPlaylistModel } from '@server/models/video/video-playlist.js'
|
||||
import { ActivityType, ServerStats, VideoRedundancyStrategyWithManual } from '@peertube/peertube-models'
|
||||
import { UserRegistrationModel } from '@server/models/user/user-registration.js'
|
||||
import { AbuseModel } from '@server/models/abuse/abuse.js'
|
||||
import { pick } from '@peertube/peertube-core-utils'
|
||||
|
||||
class StatsManager {
|
||||
|
||||
private static instance: StatsManager
|
||||
|
||||
private readonly instanceStartDate = new Date()
|
||||
|
||||
private readonly inboxMessages = {
|
||||
processed: 0,
|
||||
errors: 0,
|
||||
successes: 0,
|
||||
waiting: 0,
|
||||
errorsPerType: this.buildAPPerType(),
|
||||
successesPerType: this.buildAPPerType()
|
||||
}
|
||||
|
||||
private constructor () {}
|
||||
|
||||
updateInboxWaiting (inboxMessagesWaiting: number) {
|
||||
this.inboxMessages.waiting = inboxMessagesWaiting
|
||||
}
|
||||
|
||||
addInboxProcessedSuccess (type: ActivityType) {
|
||||
this.inboxMessages.processed++
|
||||
this.inboxMessages.successes++
|
||||
this.inboxMessages.successesPerType[type]++
|
||||
}
|
||||
|
||||
addInboxProcessedError (type: ActivityType) {
|
||||
this.inboxMessages.processed++
|
||||
this.inboxMessages.errors++
|
||||
this.inboxMessages.errorsPerType[type]++
|
||||
}
|
||||
|
||||
async getStats () {
|
||||
const { totalLocalVideos, totalLocalVideoViews, totalVideos } = await VideoModel.getStats()
|
||||
const { totalLocalVideoComments, totalVideoComments } = await VideoCommentModel.getStats()
|
||||
const {
|
||||
totalUsers,
|
||||
totalDailyActiveUsers,
|
||||
totalWeeklyActiveUsers,
|
||||
totalMonthlyActiveUsers,
|
||||
totalAdmins,
|
||||
totalModerators
|
||||
} = await UserModel.getStats()
|
||||
const { totalInstanceFollowers, totalInstanceFollowing } = await ActorFollowModel.getStats()
|
||||
const { totalLocalVideoFilesSize } = await VideoFileModel.getStats()
|
||||
const {
|
||||
totalLocalVideoChannels,
|
||||
totalLocalDailyActiveVideoChannels,
|
||||
totalLocalWeeklyActiveVideoChannels,
|
||||
totalLocalMonthlyActiveVideoChannels
|
||||
} = await VideoChannelModel.getStats()
|
||||
const { totalLocalPlaylists } = await VideoPlaylistModel.getStats()
|
||||
|
||||
const videosRedundancyStats = await this.buildRedundancyStats()
|
||||
|
||||
const data: ServerStats = {
|
||||
totalUsers,
|
||||
totalDailyActiveUsers,
|
||||
totalWeeklyActiveUsers,
|
||||
totalMonthlyActiveUsers,
|
||||
|
||||
totalModerators: CONFIG.STATS.TOTAL_MODERATORS.ENABLED
|
||||
? totalModerators
|
||||
: null,
|
||||
|
||||
totalAdmins: CONFIG.STATS.TOTAL_ADMINS.ENABLED
|
||||
? totalAdmins
|
||||
: null,
|
||||
|
||||
totalLocalVideos,
|
||||
totalLocalVideoViews,
|
||||
totalLocalVideoComments,
|
||||
totalLocalVideoFilesSize,
|
||||
|
||||
totalVideos,
|
||||
totalVideoComments,
|
||||
|
||||
totalLocalVideoChannels,
|
||||
totalLocalDailyActiveVideoChannels,
|
||||
totalLocalWeeklyActiveVideoChannels,
|
||||
totalLocalMonthlyActiveVideoChannels,
|
||||
|
||||
totalLocalPlaylists,
|
||||
|
||||
totalInstanceFollowers,
|
||||
totalInstanceFollowing,
|
||||
|
||||
videosRedundancy: videosRedundancyStats,
|
||||
|
||||
...await this.buildAbuseStats(),
|
||||
...await this.buildRegistrationRequestsStats(),
|
||||
|
||||
...this.buildAPStats()
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
private buildActivityPubMessagesProcessedPerSecond () {
|
||||
const now = new Date()
|
||||
const startedSeconds = (now.getTime() - this.instanceStartDate.getTime()) / 1000
|
||||
|
||||
return this.inboxMessages.processed / startedSeconds
|
||||
}
|
||||
|
||||
private buildRedundancyStats () {
|
||||
const strategies = CONFIG.REDUNDANCY.VIDEOS.STRATEGIES
|
||||
.map(r => ({
|
||||
strategy: r.strategy as VideoRedundancyStrategyWithManual,
|
||||
size: r.size
|
||||
}))
|
||||
|
||||
strategies.push({ strategy: 'manual', size: null })
|
||||
|
||||
return Bluebird.mapSeries(strategies, r => {
|
||||
return VideoRedundancyModel.getStats(r.strategy)
|
||||
.then(stats => Object.assign(stats, { strategy: r.strategy, totalSize: r.size }))
|
||||
})
|
||||
}
|
||||
|
||||
private buildAPPerType () {
|
||||
return {
|
||||
Create: 0,
|
||||
Update: 0,
|
||||
Delete: 0,
|
||||
Follow: 0,
|
||||
Accept: 0,
|
||||
Reject: 0,
|
||||
Announce: 0,
|
||||
Undo: 0,
|
||||
Like: 0,
|
||||
Dislike: 0,
|
||||
Flag: 0,
|
||||
View: 0,
|
||||
ApproveReply: 0,
|
||||
RejectReply: 0
|
||||
}
|
||||
}
|
||||
|
||||
private buildAPStats () {
|
||||
return {
|
||||
totalActivityPubMessagesProcessed: this.inboxMessages.processed,
|
||||
|
||||
totalActivityPubMessagesSuccesses: this.inboxMessages.successes,
|
||||
|
||||
// Dirty, but simpler and with type checking
|
||||
totalActivityPubCreateMessagesSuccesses: this.inboxMessages.successesPerType.Create,
|
||||
totalActivityPubUpdateMessagesSuccesses: this.inboxMessages.successesPerType.Update,
|
||||
totalActivityPubDeleteMessagesSuccesses: this.inboxMessages.successesPerType.Delete,
|
||||
totalActivityPubFollowMessagesSuccesses: this.inboxMessages.successesPerType.Follow,
|
||||
totalActivityPubAcceptMessagesSuccesses: this.inboxMessages.successesPerType.Accept,
|
||||
totalActivityPubRejectMessagesSuccesses: this.inboxMessages.successesPerType.Reject,
|
||||
totalActivityPubAnnounceMessagesSuccesses: this.inboxMessages.successesPerType.Announce,
|
||||
totalActivityPubUndoMessagesSuccesses: this.inboxMessages.successesPerType.Undo,
|
||||
totalActivityPubLikeMessagesSuccesses: this.inboxMessages.successesPerType.Like,
|
||||
totalActivityPubDislikeMessagesSuccesses: this.inboxMessages.successesPerType.Dislike,
|
||||
totalActivityPubFlagMessagesSuccesses: this.inboxMessages.successesPerType.Flag,
|
||||
totalActivityPubViewMessagesSuccesses: this.inboxMessages.successesPerType.View,
|
||||
totalActivityPubApproveReplyMessagesSuccesses: this.inboxMessages.successesPerType.ApproveReply,
|
||||
totalActivityPubRejectReplyMessagesSuccesses: this.inboxMessages.successesPerType.RejectReply,
|
||||
|
||||
totalActivityPubCreateMessagesErrors: this.inboxMessages.errorsPerType.Create,
|
||||
totalActivityPubUpdateMessagesErrors: this.inboxMessages.errorsPerType.Update,
|
||||
totalActivityPubDeleteMessagesErrors: this.inboxMessages.errorsPerType.Delete,
|
||||
totalActivityPubFollowMessagesErrors: this.inboxMessages.errorsPerType.Follow,
|
||||
totalActivityPubAcceptMessagesErrors: this.inboxMessages.errorsPerType.Accept,
|
||||
totalActivityPubRejectMessagesErrors: this.inboxMessages.errorsPerType.Reject,
|
||||
totalActivityPubAnnounceMessagesErrors: this.inboxMessages.errorsPerType.Announce,
|
||||
totalActivityPubUndoMessagesErrors: this.inboxMessages.errorsPerType.Undo,
|
||||
totalActivityPubLikeMessagesErrors: this.inboxMessages.errorsPerType.Like,
|
||||
totalActivityPubDislikeMessagesErrors: this.inboxMessages.errorsPerType.Dislike,
|
||||
totalActivityPubFlagMessagesErrors: this.inboxMessages.errorsPerType.Flag,
|
||||
totalActivityPubViewMessagesErrors: this.inboxMessages.errorsPerType.View,
|
||||
totalActivityPubApproveReplyMessagesErrors: this.inboxMessages.errorsPerType.ApproveReply,
|
||||
totalActivityPubRejectReplyMessagesErrors: this.inboxMessages.errorsPerType.RejectReply,
|
||||
|
||||
totalActivityPubMessagesErrors: this.inboxMessages.errors,
|
||||
|
||||
activityPubMessagesProcessedPerSecond: this.buildActivityPubMessagesProcessedPerSecond(),
|
||||
totalActivityPubMessagesWaiting: this.inboxMessages.waiting
|
||||
}
|
||||
}
|
||||
|
||||
private async buildRegistrationRequestsStats () {
|
||||
if (!CONFIG.STATS.REGISTRATION_REQUESTS.ENABLED) {
|
||||
return {
|
||||
averageRegistrationRequestResponseTimeMs: null,
|
||||
totalRegistrationRequests: null,
|
||||
totalRegistrationRequestsProcessed: null
|
||||
}
|
||||
}
|
||||
|
||||
const res = await UserRegistrationModel.getStats()
|
||||
|
||||
return pick(res, [ 'averageRegistrationRequestResponseTimeMs', 'totalRegistrationRequests', 'totalRegistrationRequestsProcessed' ])
|
||||
}
|
||||
|
||||
private async buildAbuseStats () {
|
||||
if (!CONFIG.STATS.ABUSES.ENABLED) {
|
||||
return {
|
||||
averageAbuseResponseTimeMs: null,
|
||||
totalAbuses: null,
|
||||
totalAbusesProcessed: null
|
||||
}
|
||||
}
|
||||
|
||||
const res = await AbuseModel.getStats()
|
||||
|
||||
return pick(res, [ 'averageAbuseResponseTimeMs', 'totalAbuses', 'totalAbusesProcessed' ])
|
||||
}
|
||||
|
||||
static get Instance () {
|
||||
return this.instance || (this.instance = new this())
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
StatsManager
|
||||
}
|
||||
Reference in New Issue
Block a user