UNIwise / socket.io-prometheus-metrics

Socket.IO prometheus metrics exporter written in typescript
Apache License 2.0
36 stars 17 forks source link

Feature: Binding emit for room messages #16

Open KonkretneKosteczki opened 3 years ago

KonkretneKosteczki commented 3 years ago

Out of all emit possibilities only socket based ones are supported

// sending to the client
socket.emit('hello', 'can you hear me?', 1, 2, 'abc');
// sending to all clients except sender
socket.broadcast.emit('broadcast', 'hello friends!');
// sending to all clients in 'game' room except sender
socket.to('game').emit('nice game', "let's play a game");
// sending to all clients in 'game1' and/or in 'game2' room, except sender
socket.to('game1').to('game2').emit('nice game', "let's play a game (too)");

Please add support to io:

// sending to all clients in 'game' room, including sender
io.in('game').emit('big-announcement', 'the game will start soon');
// sending to all clients in namespace 'myNamespace', including sender
io.of('myNamespace').emit('bigger-announcement', 'the tournament will start soon');
// sending to a specific room in a specific namespace, including sender
io.of('myNamespace').to('room').emit('event', 'message');
// sending to individual socketid (private message)
io.to(socketId).emit('hey', 'I just met you');

It can be done in the exact same way as the socket ones. If i was to write an more generic function for hooking onto emits I would get something like:

private emitHook(
    originalEmit: (event: string, ...data: unknown[]) => boolean,
    emitter: NodeJS.EventEmitter,
    labels: prom.LabelValues<string>
) {
    return (event: string, ...data: unknown[]) => {
        if (this.blacklisted_events.has(event))
            return originalEmit.apply(emitter, [event, ...data]);

        const labelsWEvent = {event: event, ...labels};
        this.metrics.bytesTransmitted.inc(labelsWEvent, SocketIOMetrics.dataToBytes(data));
        this.metrics.eventsSentTotal.inc(labelsWEvent);

        return originalEmit.apply(emitter, [event, ...data]);
    };
}

Which can be used to hook onto socket events

        // Hook into emit (outgoing event)
        socket.emit = this.emitHook(socket.emit, socket, labels);

And io events

    // Hook into emit (outgoing event)
    server.emit = this.emitHook(server.emit, server, labels);
naueramant commented 3 years ago

Thanks for the suggestion. This will be a good candidate for a feature for version 2 of this project. It can be found on the v2 branch but it is very much a work in progress.

Feel free to contribute if you like!