aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-02-26 10:28:11 +0100
committerChocobozzz <me@florianbigard.com>2021-02-26 10:28:11 +0100
commit543442a3be9d7740749eb3918dc59f502ff042f9 (patch)
tree3d2959757b7907ea9be8a6f6a69d4bab8521dbc3 /server
parentcb2e36618ca5986949d4326ea939b5b08f3a9a82 (diff)
downloadPeerTube-543442a3be9d7740749eb3918dc59f502ff042f9.tar.gz
PeerTube-543442a3be9d7740749eb3918dc59f502ff042f9.tar.zst
PeerTube-543442a3be9d7740749eb3918dc59f502ff042f9.zip
Add more AP stats to stats endpoint
It will help to understand if the federation correctly works or not
Diffstat (limited to 'server')
-rw-r--r--server/lib/activitypub/inbox-manager.ts12
-rw-r--r--server/lib/activitypub/process/process.ts5
-rw-r--r--server/lib/stat-manager.ts92
-rw-r--r--server/tests/api/server/stats.ts17
4 files changed, 108 insertions, 18 deletions
diff --git a/server/lib/activitypub/inbox-manager.ts b/server/lib/activitypub/inbox-manager.ts
index 18ae49532..282e7ce66 100644
--- a/server/lib/activitypub/inbox-manager.ts
+++ b/server/lib/activitypub/inbox-manager.ts
@@ -1,10 +1,10 @@
1import { AsyncQueue, queue } from 'async' 1import { queue, QueueObject } from 'async'
2import { logger } from '@server/helpers/logger' 2import { logger } from '@server/helpers/logger'
3import { SCHEDULER_INTERVALS_MS } from '@server/initializers/constants' 3import { SCHEDULER_INTERVALS_MS } from '@server/initializers/constants'
4import { MActorDefault, MActorSignature } from '@server/types/models' 4import { MActorDefault, MActorSignature } from '@server/types/models'
5import { Activity } from '@shared/models' 5import { Activity } from '@shared/models'
6import { processActivities } from './process'
7import { StatsManager } from '../stat-manager' 6import { StatsManager } from '../stat-manager'
7import { processActivities } from './process'
8 8
9type QueueParam = { 9type QueueParam = {
10 activities: Activity[] 10 activities: Activity[]
@@ -16,16 +16,12 @@ class InboxManager {
16 16
17 private static instance: InboxManager 17 private static instance: InboxManager
18 18
19 private readonly inboxQueue: AsyncQueue<QueueParam> 19 private readonly inboxQueue: QueueObject<QueueParam>
20
21 private messagesProcessed = 0
22 20
23 private constructor () { 21 private constructor () {
24 this.inboxQueue = queue<QueueParam, Error>((task, cb) => { 22 this.inboxQueue = queue<QueueParam, Error>((task, cb) => {
25 const options = { signatureActor: task.signatureActor, inboxActor: task.inboxActor } 23 const options = { signatureActor: task.signatureActor, inboxActor: task.inboxActor }
26 24
27 this.messagesProcessed++
28
29 processActivities(task.activities, options) 25 processActivities(task.activities, options)
30 .then(() => cb()) 26 .then(() => cb())
31 .catch(err => { 27 .catch(err => {
@@ -35,7 +31,7 @@ class InboxManager {
35 }) 31 })
36 32
37 setInterval(() => { 33 setInterval(() => {
38 StatsManager.Instance.updateInboxStats(this.messagesProcessed, this.getActivityPubMessagesWaiting()) 34 StatsManager.Instance.updateInboxWaiting(this.getActivityPubMessagesWaiting())
39 }, SCHEDULER_INTERVALS_MS.updateInboxStats) 35 }, SCHEDULER_INTERVALS_MS.updateInboxStats)
40 } 36 }
41 37
diff --git a/server/lib/activitypub/process/process.ts b/server/lib/activitypub/process/process.ts
index e60dd2a5b..5cef75665 100644
--- a/server/lib/activitypub/process/process.ts
+++ b/server/lib/activitypub/process/process.ts
@@ -16,6 +16,7 @@ import { processFlagActivity } from './process-flag'
16import { processViewActivity } from './process-view' 16import { processViewActivity } from './process-view'
17import { APProcessorOptions } from '../../../types/activitypub-processor.model' 17import { APProcessorOptions } from '../../../types/activitypub-processor.model'
18import { MActorDefault, MActorSignature } from '../../../types/models' 18import { MActorDefault, MActorSignature } from '../../../types/models'
19import { StatsManager } from '@server/lib/stat-manager'
19 20
20const processActivity: { [ P in ActivityType ]: (options: APProcessorOptions<Activity>) => Promise<any> } = { 21const processActivity: { [ P in ActivityType ]: (options: APProcessorOptions<Activity>) => Promise<any> } = {
21 Create: processCreateActivity, 22 Create: processCreateActivity,
@@ -75,8 +76,12 @@ async function processActivities (
75 76
76 try { 77 try {
77 await activityProcessor({ activity, byActor, inboxActor, fromFetch }) 78 await activityProcessor({ activity, byActor, inboxActor, fromFetch })
79
80 StatsManager.Instance.addInboxProcessedSuccess(activity.type)
78 } catch (err) { 81 } catch (err) {
79 logger.warn('Cannot process activity %s.', activity.type, { err }) 82 logger.warn('Cannot process activity %s.', activity.type, { err })
83
84 StatsManager.Instance.addInboxProcessedError(activity.type)
80 } 85 }
81 } 86 }
82} 87}
diff --git a/server/lib/stat-manager.ts b/server/lib/stat-manager.ts
index f9d69b0dc..547d7a56b 100644
--- a/server/lib/stat-manager.ts
+++ b/server/lib/stat-manager.ts
@@ -5,7 +5,7 @@ import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy
5import { VideoModel } from '@server/models/video/video' 5import { VideoModel } from '@server/models/video/video'
6import { VideoCommentModel } from '@server/models/video/video-comment' 6import { VideoCommentModel } from '@server/models/video/video-comment'
7import { VideoFileModel } from '@server/models/video/video-file' 7import { VideoFileModel } from '@server/models/video/video-file'
8import { ServerStats, VideoRedundancyStrategyWithManual } from '@shared/models' 8import { ActivityType, ServerStats, VideoRedundancyStrategyWithManual } from '@shared/models'
9 9
10class StatsManager { 10class StatsManager {
11 11
@@ -13,14 +13,31 @@ class StatsManager {
13 13
14 private readonly instanceStartDate = new Date() 14 private readonly instanceStartDate = new Date()
15 15
16 private inboxMessagesProcessed = 0 16 private inboxMessages = {
17 private inboxMessagesWaiting = 0 17 processed: 0,
18 errors: 0,
19 successes: 0,
20 waiting: 0,
21 errorsPerType: this.buildAPPerType(),
22 successesPerType: this.buildAPPerType()
23 }
18 24
19 private constructor () {} 25 private constructor () {}
20 26
21 updateInboxStats (inboxMessagesProcessed: number, inboxMessagesWaiting: number) { 27 updateInboxWaiting (inboxMessagesWaiting: number) {
22 this.inboxMessagesProcessed = inboxMessagesProcessed 28 this.inboxMessages.waiting = inboxMessagesWaiting
23 this.inboxMessagesWaiting = inboxMessagesWaiting 29 }
30
31 addInboxProcessedSuccess (type: ActivityType) {
32 this.inboxMessages.processed++
33 this.inboxMessages.successes++
34 this.inboxMessages.successesPerType[type]++
35 }
36
37 addInboxProcessedError (type: ActivityType) {
38 this.inboxMessages.processed++
39 this.inboxMessages.errors++
40 this.inboxMessages.errorsPerType[type]++
24 } 41 }
25 42
26 async getStats () { 43 async getStats () {
@@ -50,9 +67,7 @@ class StatsManager {
50 67
51 videosRedundancy: videosRedundancyStats, 68 videosRedundancy: videosRedundancyStats,
52 69
53 totalActivityPubMessagesProcessed: this.inboxMessagesProcessed, 70 ...this.buildAPStats()
54 activityPubMessagesProcessedPerSecond: this.buildActivityPubMessagesProcessedPerSecond(),
55 totalActivityPubMessagesWaiting: this.inboxMessagesWaiting
56 } 71 }
57 72
58 return data 73 return data
@@ -62,7 +77,7 @@ class StatsManager {
62 const now = new Date() 77 const now = new Date()
63 const startedSeconds = (now.getTime() - this.instanceStartDate.getTime()) / 1000 78 const startedSeconds = (now.getTime() - this.instanceStartDate.getTime()) / 1000
64 79
65 return this.inboxMessagesProcessed / startedSeconds 80 return this.inboxMessages.processed / startedSeconds
66 } 81 }
67 82
68 private buildRedundancyStats () { 83 private buildRedundancyStats () {
@@ -82,6 +97,63 @@ class StatsManager {
82 ) 97 )
83 } 98 }
84 99
100 private buildAPPerType () {
101 return {
102 Create: 0,
103 Update: 0,
104 Delete: 0,
105 Follow: 0,
106 Accept: 0,
107 Reject: 0,
108 Announce: 0,
109 Undo: 0,
110 Like: 0,
111 Dislike: 0,
112 Flag: 0,
113 View: 0
114 }
115 }
116
117 private buildAPStats () {
118 return {
119 totalActivityPubMessagesProcessed: this.inboxMessages.processed,
120
121 totalActivityPubMessagesSuccesses: this.inboxMessages.successes,
122
123 // Dirty, but simpler and with type checking
124 totalActivityPubCreateMessagesSuccesses: this.inboxMessages.successesPerType.Create,
125 totalActivityPubUpdateMessagesSuccesses: this.inboxMessages.successesPerType.Update,
126 totalActivityPubDeleteMessagesSuccesses: this.inboxMessages.successesPerType.Delete,
127 totalActivityPubFollowMessagesSuccesses: this.inboxMessages.successesPerType.Follow,
128 totalActivityPubAcceptMessagesSuccesses: this.inboxMessages.successesPerType.Accept,
129 totalActivityPubRejectMessagesSuccesses: this.inboxMessages.successesPerType.Reject,
130 totalActivityPubAnnounceMessagesSuccesses: this.inboxMessages.successesPerType.Announce,
131 totalActivityPubUndoMessagesSuccesses: this.inboxMessages.successesPerType.Undo,
132 totalActivityPubLikeMessagesSuccesses: this.inboxMessages.successesPerType.Like,
133 totalActivityPubDislikeMessagesSuccesses: this.inboxMessages.successesPerType.Dislike,
134 totalActivityPubFlagMessagesSuccesses: this.inboxMessages.successesPerType.Flag,
135 totalActivityPubViewMessagesSuccesses: this.inboxMessages.successesPerType.View,
136
137 totalActivityPubCreateMessagesErrors: this.inboxMessages.errorsPerType.Create,
138 totalActivityPubUpdateMessagesErrors: this.inboxMessages.errorsPerType.Update,
139 totalActivityPubDeleteMessagesErrors: this.inboxMessages.errorsPerType.Delete,
140 totalActivityPubFollowMessagesErrors: this.inboxMessages.errorsPerType.Follow,
141 totalActivityPubAcceptMessagesErrors: this.inboxMessages.errorsPerType.Accept,
142 totalActivityPubRejectMessagesErrors: this.inboxMessages.errorsPerType.Reject,
143 totalActivityPubAnnounceMessagesErrors: this.inboxMessages.errorsPerType.Announce,
144 totalActivityPubUndoMessagesErrors: this.inboxMessages.errorsPerType.Undo,
145 totalActivityPubLikeMessagesErrors: this.inboxMessages.errorsPerType.Like,
146 totalActivityPubDislikeMessagesErrors: this.inboxMessages.errorsPerType.Dislike,
147 totalActivityPubFlagMessagesErrors: this.inboxMessages.errorsPerType.Flag,
148 totalActivityPubViewMessagesErrors: this.inboxMessages.errorsPerType.View,
149
150 totalActivityPubMessagesErrors: this.inboxMessages.errors,
151
152 activityPubMessagesProcessedPerSecond: this.buildActivityPubMessagesProcessedPerSecond(),
153 totalActivityPubMessagesWaiting: this.inboxMessages.waiting
154 }
155 }
156
85 static get Instance () { 157 static get Instance () {
86 return this.instance || (this.instance = new this()) 158 return this.instance || (this.instance = new this())
87 } 159 }
diff --git a/server/tests/api/server/stats.ts b/server/tests/api/server/stats.ts
index 332c09585..eb474c1f5 100644
--- a/server/tests/api/server/stats.ts
+++ b/server/tests/api/server/stats.ts
@@ -21,6 +21,7 @@ import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
21import { getStats } from '../../../../shared/extra-utils/server/stats' 21import { getStats } from '../../../../shared/extra-utils/server/stats'
22import { addVideoCommentThread } from '../../../../shared/extra-utils/videos/video-comments' 22import { addVideoCommentThread } from '../../../../shared/extra-utils/videos/video-comments'
23import { ServerStats } from '../../../../shared/models/server/server-stats.model' 23import { ServerStats } from '../../../../shared/models/server/server-stats.model'
24import { ActivityType } from '@shared/models'
24 25
25const expect = chai.expect 26const expect = chai.expect
26 27
@@ -201,6 +202,22 @@ describe('Test stats (excluding redundancy)', function () {
201 const second: ServerStats = res2.body 202 const second: ServerStats = res2.body
202 203
203 expect(second.totalActivityPubMessagesProcessed).to.be.greaterThan(first.totalActivityPubMessagesProcessed) 204 expect(second.totalActivityPubMessagesProcessed).to.be.greaterThan(first.totalActivityPubMessagesProcessed)
205 const apTypes: ActivityType[] = [
206 'Create', 'Update', 'Delete', 'Follow', 'Accept', 'Announce', 'Undo', 'Like', 'Reject', 'View', 'Dislike', 'Flag'
207 ]
208
209 const processed = apTypes.reduce(
210 (previous, type) => previous + second['totalActivityPub' + type + 'MessagesSuccesses'],
211 0
212 )
213 expect(second.totalActivityPubMessagesProcessed).to.equal(processed)
214 expect(second.totalActivityPubMessagesSuccesses).to.equal(processed)
215
216 expect(second.totalActivityPubMessagesErrors).to.equal(0)
217
218 for (const apType of apTypes) {
219 expect(second['totalActivityPub' + apType + 'MessagesErrors']).to.equal(0)
220 }
204 221
205 await wait(6000) 222 await wait(6000)
206 223