Skip to content

Commit b3c95fe

Browse files
committed
Added metrics collectors for brain
Added pusher metrics collectors for extra
1 parent 898f62c commit b3c95fe

File tree

8 files changed

+167
-0
lines changed

8 files changed

+167
-0
lines changed

src/metrics/brain-metrics.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type * as FN from '@soketi/impl/types';
2+
import { Brain } from '../brain';
3+
import { Metrics } from './metrics';
4+
import { Connections } from '../ws';
5+
6+
export class BrainMetrics extends Metrics {
7+
metrics: FN.JSON.Object = {};
8+
9+
constructor(
10+
readonly brain: Brain,
11+
readonly connections: Connections,
12+
) {
13+
super(connections);
14+
}
15+
16+
async snapshot(namespace: string): Promise<void> {
17+
this.snapshotInProgress = true;
18+
19+
await this.brain.set(`metrics:${namespace}`, {
20+
connections: this.connections.connections.size,
21+
});
22+
23+
this.snapshotInProgress = false;
24+
}
25+
26+
async get(namespace: string): Promise<FN.JSON.Object> {
27+
return (await this.brain.get(`metrics:${namespace}`)) || {};
28+
}
29+
30+
async cleanup(): Promise<void> {
31+
//
32+
}
33+
}

src/metrics/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './brain-metrics';
2+
export * from './metrics';

src/metrics/metrics.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type * as FN from '@soketi/impl/types';
2+
import { Connections } from '../ws';
3+
4+
export abstract class Metrics {
5+
snapshotInProgress = false;
6+
7+
constructor(
8+
readonly connections: Connections,
9+
) {
10+
//
11+
}
12+
13+
abstract snapshot(namespace: string): Promise<void>;
14+
abstract get(namespace: string): Promise<FN.JSON.Object>;
15+
16+
async cleanup(): Promise<void> {
17+
//
18+
}
19+
}

src/pusher/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from './apps';
22
export * from './channels';
3+
export * from './metrics';
34
export * from './queue';
45
export * from './ws';
56
export * from './utils';

src/pusher/metrics/brain-metrics.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Brain } from '../../brain';
2+
import { BrainMetrics } from '../../metrics';
3+
import { PusherConnections } from '../ws';
4+
5+
export class PusherBrainMetrics extends BrainMetrics {
6+
constructor(
7+
readonly brain: Brain,
8+
readonly connections: PusherConnections,
9+
) {
10+
super(brain, connections);
11+
}
12+
13+
async snapshot(namespace: string): Promise<void> {
14+
this.snapshotInProgress = true;
15+
16+
await this.brain.set(`metrics:${namespace}`, {
17+
connections: this.connections.connections.size,
18+
channels: [...this.connections.channels].map(([channel, connections]) => ({
19+
channel,
20+
connections: connections.size,
21+
})),
22+
users: [...this.connections.users].map(([user, connections]) => ({
23+
user,
24+
connections,
25+
})),
26+
started: this.connections.started.toISOString(),
27+
});
28+
29+
this.snapshotInProgress = false;
30+
}
31+
}

src/pusher/metrics/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './brain-metrics';

tests/pusher/ws.test.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { PusherConnection, PusherConnections } from '../../src/pusher/ws';
66
import { describe, test, expect, beforeEach } from 'vitest';
77
import { createHmac } from 'crypto';
88
import { Brain, LocalBrain } from '../../src/brain';
9+
import { PusherBrainMetrics } from '../../src/pusher';
910

1011
const pusherUtil = require('pusher/lib/util');
1112
const Pusher = require('pusher');
@@ -192,6 +193,11 @@ describe('pusher/ws', () => {
192193
const conn = new PusherConnection('test', {
193194
send: async (message) => {
194195
if (message.indexOf('pusher:signin_success') !== -1) {
196+
expect(message).toBe(JSON.stringify({
197+
event: 'pusher:signin_success',
198+
data: await messageData(conn.id),
199+
}));
200+
195201
await conns.terminateUserConnections(userData.id);
196202
}
197203
},
@@ -208,6 +214,69 @@ describe('pusher/ws', () => {
208214
data: await messageData(conn.id),
209215
});
210216
}));
217+
218+
test('join and leave triggers metrics change', async () => {
219+
const app = await AppsRegistry.getById('app-id') as TestApp;
220+
const conns = new LocalConnections(app, gossiper, brain);
221+
const metrics = new PusherBrainMetrics(brain, conns);
222+
223+
const conn = new PusherConnection('test', {
224+
send: (message) => {
225+
//
226+
},
227+
close: (code, reason) => {
228+
//
229+
},
230+
});
231+
232+
await conns.newConnection(conn);
233+
234+
await conns.subscribeToChannel(conn, {
235+
event: 'pusher:subscribe',
236+
data: {
237+
channel: 'test',
238+
},
239+
});
240+
241+
expect([...conn.subscribedChannels]).toEqual(['test']);
242+
expect(conn.presence).toEqual(new Map());
243+
expect(conns.channels.get('test')).lengthOf(1);
244+
245+
await metrics.snapshot(app.id);
246+
expect(await metrics.get(app.id)).toEqual({
247+
connections: 1,
248+
channels: [{
249+
channel: 'test',
250+
connections: 1,
251+
}],
252+
users: [],
253+
started: conns.started.toISOString(),
254+
});
255+
256+
await conns.unsubscribeFromChannel(conn, 'test');
257+
258+
expect([...conn.subscribedChannels]).toEqual([]);
259+
expect(conn.presence).toEqual(new Map());
260+
expect(conns.channels.get('test')).toBeUndefined();
261+
262+
await metrics.snapshot(app.id);
263+
expect(await metrics.get(app.id)).toEqual({
264+
connections: 1,
265+
channels: [],
266+
users: [],
267+
started: conns.started.toISOString(),
268+
});
269+
270+
await conns.removeConnection(conn);
271+
272+
await metrics.snapshot(app.id);
273+
expect(await metrics.get(app.id)).toEqual({
274+
connections: 0,
275+
channels: [],
276+
users: [],
277+
started: conns.started.toISOString(),
278+
});
279+
});
211280
});
212281

213282
class LocalConnections extends PusherConnections {

tests/ws/router.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { Connection, Connections, Router as WsRouter } from '../../src/ws';
2+
import { LocalBrain } from '../../src/brain';
3+
import { BrainMetrics } from '../../src/metrics';
24
import { describe, test, expect } from 'vitest';
35

46
describe('ws/router', () => {
@@ -11,9 +13,18 @@ describe('ws/router', () => {
1113

1214
const connections = new LocalConnections();
1315
const conn = new Connection('test', { });
16+
const brain = new LocalBrain();
17+
const metrics = new BrainMetrics(brain, connections);
1418

1519
await connections.newConnection(conn);
1620
WsRouter.handleNewConnection(conn);
21+
22+
await metrics.snapshot('test');
23+
expect(await metrics.get('test')).toEqual({
24+
connections: 1,
25+
});
26+
27+
expect(await metrics.get('test2')).toEqual({});
1728
}));
1829

1930
test('onConnectionClosed', () => new Promise<void>(async (done) => {

0 commit comments

Comments
 (0)