ニジカ投稿局 https://tv.nizika.tv
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

stat-manager.ts 8.6 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. import Bluebird from 'bluebird'
  2. import { CONFIG } from '@server/initializers/config.js'
  3. import { ActorFollowModel } from '@server/models/actor/actor-follow.js'
  4. import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy.js'
  5. import { UserModel } from '@server/models/user/user.js'
  6. import { VideoModel } from '@server/models/video/video.js'
  7. import { VideoChannelModel } from '@server/models/video/video-channel.js'
  8. import { VideoCommentModel } from '@server/models/video/video-comment.js'
  9. import { VideoFileModel } from '@server/models/video/video-file.js'
  10. import { VideoPlaylistModel } from '@server/models/video/video-playlist.js'
  11. import { ActivityType, ServerStats, VideoRedundancyStrategyWithManual } from '@peertube/peertube-models'
  12. import { UserRegistrationModel } from '@server/models/user/user-registration.js'
  13. import { AbuseModel } from '@server/models/abuse/abuse.js'
  14. import { pick } from '@peertube/peertube-core-utils'
  15. class StatsManager {
  16. private static instance: StatsManager
  17. private readonly instanceStartDate = new Date()
  18. private readonly inboxMessages = {
  19. processed: 0,
  20. errors: 0,
  21. successes: 0,
  22. waiting: 0,
  23. errorsPerType: this.buildAPPerType(),
  24. successesPerType: this.buildAPPerType()
  25. }
  26. private constructor () {}
  27. updateInboxWaiting (inboxMessagesWaiting: number) {
  28. this.inboxMessages.waiting = inboxMessagesWaiting
  29. }
  30. addInboxProcessedSuccess (type: ActivityType) {
  31. this.inboxMessages.processed++
  32. this.inboxMessages.successes++
  33. this.inboxMessages.successesPerType[type]++
  34. }
  35. addInboxProcessedError (type: ActivityType) {
  36. this.inboxMessages.processed++
  37. this.inboxMessages.errors++
  38. this.inboxMessages.errorsPerType[type]++
  39. }
  40. async getStats () {
  41. const { totalLocalVideos, totalLocalVideoViews, totalVideos } = await VideoModel.getStats()
  42. const { totalLocalVideoComments, totalVideoComments } = await VideoCommentModel.getStats()
  43. const {
  44. totalUsers,
  45. totalDailyActiveUsers,
  46. totalWeeklyActiveUsers,
  47. totalMonthlyActiveUsers,
  48. totalAdmins,
  49. totalModerators
  50. } = await UserModel.getStats()
  51. const { totalInstanceFollowers, totalInstanceFollowing } = await ActorFollowModel.getStats()
  52. const { totalLocalVideoFilesSize } = await VideoFileModel.getStats()
  53. const {
  54. totalLocalVideoChannels,
  55. totalLocalDailyActiveVideoChannels,
  56. totalLocalWeeklyActiveVideoChannels,
  57. totalLocalMonthlyActiveVideoChannels
  58. } = await VideoChannelModel.getStats()
  59. const { totalLocalPlaylists } = await VideoPlaylistModel.getStats()
  60. const videosRedundancyStats = await this.buildRedundancyStats()
  61. const data: ServerStats = {
  62. totalUsers,
  63. totalDailyActiveUsers,
  64. totalWeeklyActiveUsers,
  65. totalMonthlyActiveUsers,
  66. totalModerators: CONFIG.STATS.TOTAL_MODERATORS.ENABLED
  67. ? totalModerators
  68. : null,
  69. totalAdmins: CONFIG.STATS.TOTAL_ADMINS.ENABLED
  70. ? totalAdmins
  71. : null,
  72. totalLocalVideos,
  73. totalLocalVideoViews,
  74. totalLocalVideoComments,
  75. totalLocalVideoFilesSize,
  76. totalVideos,
  77. totalVideoComments,
  78. totalLocalVideoChannels,
  79. totalLocalDailyActiveVideoChannels,
  80. totalLocalWeeklyActiveVideoChannels,
  81. totalLocalMonthlyActiveVideoChannels,
  82. totalLocalPlaylists,
  83. totalInstanceFollowers,
  84. totalInstanceFollowing,
  85. videosRedundancy: videosRedundancyStats,
  86. ...await this.buildAbuseStats(),
  87. ...await this.buildRegistrationRequestsStats(),
  88. ...this.buildAPStats()
  89. }
  90. return data
  91. }
  92. private buildActivityPubMessagesProcessedPerSecond () {
  93. const now = new Date()
  94. const startedSeconds = (now.getTime() - this.instanceStartDate.getTime()) / 1000
  95. return this.inboxMessages.processed / startedSeconds
  96. }
  97. private buildRedundancyStats () {
  98. const strategies = CONFIG.REDUNDANCY.VIDEOS.STRATEGIES
  99. .map(r => ({
  100. strategy: r.strategy as VideoRedundancyStrategyWithManual,
  101. size: r.size
  102. }))
  103. strategies.push({ strategy: 'manual', size: null })
  104. return Bluebird.mapSeries(strategies, r => {
  105. return VideoRedundancyModel.getStats(r.strategy)
  106. .then(stats => Object.assign(stats, { strategy: r.strategy, totalSize: r.size }))
  107. })
  108. }
  109. private buildAPPerType () {
  110. return {
  111. Create: 0,
  112. Update: 0,
  113. Delete: 0,
  114. Follow: 0,
  115. Accept: 0,
  116. Reject: 0,
  117. Announce: 0,
  118. Undo: 0,
  119. Like: 0,
  120. Dislike: 0,
  121. Flag: 0,
  122. View: 0,
  123. ApproveReply: 0,
  124. RejectReply: 0
  125. }
  126. }
  127. private buildAPStats () {
  128. return {
  129. totalActivityPubMessagesProcessed: this.inboxMessages.processed,
  130. totalActivityPubMessagesSuccesses: this.inboxMessages.successes,
  131. // Dirty, but simpler and with type checking
  132. totalActivityPubCreateMessagesSuccesses: this.inboxMessages.successesPerType.Create,
  133. totalActivityPubUpdateMessagesSuccesses: this.inboxMessages.successesPerType.Update,
  134. totalActivityPubDeleteMessagesSuccesses: this.inboxMessages.successesPerType.Delete,
  135. totalActivityPubFollowMessagesSuccesses: this.inboxMessages.successesPerType.Follow,
  136. totalActivityPubAcceptMessagesSuccesses: this.inboxMessages.successesPerType.Accept,
  137. totalActivityPubRejectMessagesSuccesses: this.inboxMessages.successesPerType.Reject,
  138. totalActivityPubAnnounceMessagesSuccesses: this.inboxMessages.successesPerType.Announce,
  139. totalActivityPubUndoMessagesSuccesses: this.inboxMessages.successesPerType.Undo,
  140. totalActivityPubLikeMessagesSuccesses: this.inboxMessages.successesPerType.Like,
  141. totalActivityPubDislikeMessagesSuccesses: this.inboxMessages.successesPerType.Dislike,
  142. totalActivityPubFlagMessagesSuccesses: this.inboxMessages.successesPerType.Flag,
  143. totalActivityPubViewMessagesSuccesses: this.inboxMessages.successesPerType.View,
  144. totalActivityPubApproveReplyMessagesSuccesses: this.inboxMessages.successesPerType.ApproveReply,
  145. totalActivityPubRejectReplyMessagesSuccesses: this.inboxMessages.successesPerType.RejectReply,
  146. totalActivityPubCreateMessagesErrors: this.inboxMessages.errorsPerType.Create,
  147. totalActivityPubUpdateMessagesErrors: this.inboxMessages.errorsPerType.Update,
  148. totalActivityPubDeleteMessagesErrors: this.inboxMessages.errorsPerType.Delete,
  149. totalActivityPubFollowMessagesErrors: this.inboxMessages.errorsPerType.Follow,
  150. totalActivityPubAcceptMessagesErrors: this.inboxMessages.errorsPerType.Accept,
  151. totalActivityPubRejectMessagesErrors: this.inboxMessages.errorsPerType.Reject,
  152. totalActivityPubAnnounceMessagesErrors: this.inboxMessages.errorsPerType.Announce,
  153. totalActivityPubUndoMessagesErrors: this.inboxMessages.errorsPerType.Undo,
  154. totalActivityPubLikeMessagesErrors: this.inboxMessages.errorsPerType.Like,
  155. totalActivityPubDislikeMessagesErrors: this.inboxMessages.errorsPerType.Dislike,
  156. totalActivityPubFlagMessagesErrors: this.inboxMessages.errorsPerType.Flag,
  157. totalActivityPubViewMessagesErrors: this.inboxMessages.errorsPerType.View,
  158. totalActivityPubApproveReplyMessagesErrors: this.inboxMessages.errorsPerType.ApproveReply,
  159. totalActivityPubRejectReplyMessagesErrors: this.inboxMessages.errorsPerType.RejectReply,
  160. totalActivityPubMessagesErrors: this.inboxMessages.errors,
  161. activityPubMessagesProcessedPerSecond: this.buildActivityPubMessagesProcessedPerSecond(),
  162. totalActivityPubMessagesWaiting: this.inboxMessages.waiting
  163. }
  164. }
  165. private async buildRegistrationRequestsStats () {
  166. if (!CONFIG.STATS.REGISTRATION_REQUESTS.ENABLED) {
  167. return {
  168. averageRegistrationRequestResponseTimeMs: null,
  169. totalRegistrationRequests: null,
  170. totalRegistrationRequestsProcessed: null
  171. }
  172. }
  173. const res = await UserRegistrationModel.getStats()
  174. return pick(res, [ 'averageRegistrationRequestResponseTimeMs', 'totalRegistrationRequests', 'totalRegistrationRequestsProcessed' ])
  175. }
  176. private async buildAbuseStats () {
  177. if (!CONFIG.STATS.ABUSES.ENABLED) {
  178. return {
  179. averageAbuseResponseTimeMs: null,
  180. totalAbuses: null,
  181. totalAbusesProcessed: null
  182. }
  183. }
  184. const res = await AbuseModel.getStats()
  185. return pick(res, [ 'averageAbuseResponseTimeMs', 'totalAbuses', 'totalAbusesProcessed' ])
  186. }
  187. static get Instance () {
  188. return this.instance || (this.instance = new this())
  189. }
  190. }
  191. // ---------------------------------------------------------------------------
  192. export {
  193. StatsManager
  194. }