diff options
-rw-r--r-- | server/lib/activitypub/inbox-manager.ts | 12 | ||||
-rw-r--r-- | server/lib/activitypub/process/process.ts | 5 | ||||
-rw-r--r-- | server/lib/stat-manager.ts | 92 | ||||
-rw-r--r-- | server/tests/api/server/stats.ts | 17 | ||||
-rw-r--r-- | shared/models/server/server-stats.model.ts | 30 |
5 files changed, 137 insertions, 19 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 @@ | |||
1 | import { AsyncQueue, queue } from 'async' | 1 | import { queue, QueueObject } from 'async' |
2 | import { logger } from '@server/helpers/logger' | 2 | import { logger } from '@server/helpers/logger' |
3 | import { SCHEDULER_INTERVALS_MS } from '@server/initializers/constants' | 3 | import { SCHEDULER_INTERVALS_MS } from '@server/initializers/constants' |
4 | import { MActorDefault, MActorSignature } from '@server/types/models' | 4 | import { MActorDefault, MActorSignature } from '@server/types/models' |
5 | import { Activity } from '@shared/models' | 5 | import { Activity } from '@shared/models' |
6 | import { processActivities } from './process' | ||
7 | import { StatsManager } from '../stat-manager' | 6 | import { StatsManager } from '../stat-manager' |
7 | import { processActivities } from './process' | ||
8 | 8 | ||
9 | type QueueParam = { | 9 | type 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' | |||
16 | import { processViewActivity } from './process-view' | 16 | import { processViewActivity } from './process-view' |
17 | import { APProcessorOptions } from '../../../types/activitypub-processor.model' | 17 | import { APProcessorOptions } from '../../../types/activitypub-processor.model' |
18 | import { MActorDefault, MActorSignature } from '../../../types/models' | 18 | import { MActorDefault, MActorSignature } from '../../../types/models' |
19 | import { StatsManager } from '@server/lib/stat-manager' | ||
19 | 20 | ||
20 | const processActivity: { [ P in ActivityType ]: (options: APProcessorOptions<Activity>) => Promise<any> } = { | 21 | const 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 | |||
5 | import { VideoModel } from '@server/models/video/video' | 5 | import { VideoModel } from '@server/models/video/video' |
6 | import { VideoCommentModel } from '@server/models/video/video-comment' | 6 | import { VideoCommentModel } from '@server/models/video/video-comment' |
7 | import { VideoFileModel } from '@server/models/video/video-file' | 7 | import { VideoFileModel } from '@server/models/video/video-file' |
8 | import { ServerStats, VideoRedundancyStrategyWithManual } from '@shared/models' | 8 | import { ActivityType, ServerStats, VideoRedundancyStrategyWithManual } from '@shared/models' |
9 | 9 | ||
10 | class StatsManager { | 10 | class 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' | |||
21 | import { getStats } from '../../../../shared/extra-utils/server/stats' | 21 | import { getStats } from '../../../../shared/extra-utils/server/stats' |
22 | import { addVideoCommentThread } from '../../../../shared/extra-utils/videos/video-comments' | 22 | import { addVideoCommentThread } from '../../../../shared/extra-utils/videos/video-comments' |
23 | import { ServerStats } from '../../../../shared/models/server/server-stats.model' | 23 | import { ServerStats } from '../../../../shared/models/server/server-stats.model' |
24 | import { ActivityType } from '@shared/models' | ||
24 | 25 | ||
25 | const expect = chai.expect | 26 | const 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 | ||
diff --git a/shared/models/server/server-stats.model.ts b/shared/models/server/server-stats.model.ts index d17c43945..0f8cfc6cf 100644 --- a/shared/models/server/server-stats.model.ts +++ b/shared/models/server/server-stats.model.ts | |||
@@ -1,5 +1,4 @@ | |||
1 | import { VideoRedundancyStrategyWithManual } from '../redundancy' | 1 | import { VideoRedundancyStrategyWithManual } from '../redundancy' |
2 | |||
3 | export interface ServerStats { | 2 | export interface ServerStats { |
4 | totalUsers: number | 3 | totalUsers: number |
5 | totalDailyActiveUsers: number | 4 | totalDailyActiveUsers: number |
@@ -20,6 +19,35 @@ export interface ServerStats { | |||
20 | videosRedundancy: VideosRedundancyStats[] | 19 | videosRedundancy: VideosRedundancyStats[] |
21 | 20 | ||
22 | totalActivityPubMessagesProcessed: number | 21 | totalActivityPubMessagesProcessed: number |
22 | totalActivityPubMessagesSuccesses: number | ||
23 | totalActivityPubMessagesErrors: number | ||
24 | |||
25 | totalActivityPubCreateMessagesSuccesses: number | ||
26 | totalActivityPubUpdateMessagesSuccesses: number | ||
27 | totalActivityPubDeleteMessagesSuccesses: number | ||
28 | totalActivityPubFollowMessagesSuccesses: number | ||
29 | totalActivityPubAcceptMessagesSuccesses: number | ||
30 | totalActivityPubRejectMessagesSuccesses: number | ||
31 | totalActivityPubAnnounceMessagesSuccesses: number | ||
32 | totalActivityPubUndoMessagesSuccesses: number | ||
33 | totalActivityPubLikeMessagesSuccesses: number | ||
34 | totalActivityPubDislikeMessagesSuccesses: number | ||
35 | totalActivityPubFlagMessagesSuccesses: number | ||
36 | totalActivityPubViewMessagesSuccesses: number | ||
37 | |||
38 | totalActivityPubCreateMessagesErrors: number | ||
39 | totalActivityPubUpdateMessagesErrors: number | ||
40 | totalActivityPubDeleteMessagesErrors: number | ||
41 | totalActivityPubFollowMessagesErrors: number | ||
42 | totalActivityPubAcceptMessagesErrors: number | ||
43 | totalActivityPubRejectMessagesErrors: number | ||
44 | totalActivityPubAnnounceMessagesErrors: number | ||
45 | totalActivityPubUndoMessagesErrors: number | ||
46 | totalActivityPubLikeMessagesErrors: number | ||
47 | totalActivityPubDislikeMessagesErrors: number | ||
48 | totalActivityPubFlagMessagesErrors: number | ||
49 | totalActivityPubViewMessagesErrors: number | ||
50 | |||
23 | activityPubMessagesProcessedPerSecond: number | 51 | activityPubMessagesProcessedPerSecond: number |
24 | totalActivityPubMessagesWaiting: number | 52 | totalActivityPubMessagesWaiting: number |
25 | } | 53 | } |