Skip to content

Commit

Permalink
Add WebSocket connection metrics in turms-client-js turms-im#947
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesChenX committed Mar 7, 2022
1 parent 3f084d5 commit 538fbb2
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 7 deletions.
2 changes: 1 addition & 1 deletion turms-client-js/src/driver/state-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default class StateStore {
return !!this._sharedContextService;
}

get websocket(): WebSocketClient {
get websocket(): WebSocketClient | undefined {
return this._websocket;
}

Expand Down
5 changes: 5 additions & 0 deletions turms-client-js/src/driver/turms-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { TurmsNotification } from '../model/proto/notification/turms_notificatio
import { TurmsRequest } from '../model/proto/request/turms_request';
import { ParsedNotification } from '../model/parsed-notification';
import SystemUtil from '../util/system-util';
import WebSocketMetrics from '../transport/websocket-metrics';

export default class TurmsDriver {

Expand Down Expand Up @@ -127,6 +128,10 @@ export default class TurmsDriver {
return this._stateStore.isConnected;
}

get connectionMetrics(): WebSocketMetrics | undefined {
return this._stateStore.websocket?.metrics;
}

// Connection Listeners

addOnConnectedListener(listener: () => void): void {
Expand Down
24 changes: 21 additions & 3 deletions turms-client-js/src/transport/plain-websocket-client.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
import WebSocketClient, { EventListener } from './websocket-client';
import WebSocketMetrics from './websocket-metrics';

export default class PlainWebSocketClient extends WebSocketClient {

private readonly _ws: WebSocket;
private _metrics = new WebSocketMetrics();

constructor(url: string, listener: EventListener) {
super(url, listener);
const connectStart = new Date().getTime();
const ws = new WebSocket(url);
ws.binaryType = 'arraybuffer';
ws.onopen = (): void => this.notifyOnOpen();
ws.onopen = (): void => {
this._metrics.connectTime = new Date().getTime() - connectStart;
this.notifyOnOpen();
};
// onClose will always be triggered with a CloseEvent instance when
// 1. rejected by the HTTP upgrade error response
// 2. disconnected no matter by error (after onerror) or else,
// so we don't need to add a listener on onerror
ws.onclose = (e): void => this.notifyOnClose(e);
ws.onmessage = (e): void => this.notifyOnMessage(e.data);
ws.onclose = (e): void => {
this._metrics = new WebSocketMetrics();
this.notifyOnClose(e);
};
ws.onmessage = (e): void => {
const data = e.data as ArrayBufferLike;
this.notifyOnMessage(data);
this._metrics.dataReceived += data.byteLength;
};
this._ws = ws;
}

Expand All @@ -26,13 +39,18 @@ export default class PlainWebSocketClient extends WebSocketClient {
return this._ws.readyState === WebSocket.OPEN;
}

override get metrics(): WebSocketMetrics {
return this._metrics;
}

override close(): void {
this._ws.close();
}

override send(data: ArrayBufferLike | Blob | ArrayBufferView): Promise<void> {
try {
this._ws.send(data);
this._metrics.dataSent += data instanceof Blob ? data.size : data.byteLength;
return Promise.resolve();
} catch (e) {
return Promise.reject(e);
Expand Down
4 changes: 4 additions & 0 deletions turms-client-js/src/transport/websocket-client.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import WebSocketMetrics from './websocket-metrics';

type OnCloseParams = {
code: number,
reason: string
Expand Down Expand Up @@ -27,6 +29,8 @@ export default abstract class WebSocketClient {

abstract get isConnected(): boolean;

abstract get metrics(): WebSocketMetrics;

protected notifyOnOpen(): void {
this._listener.onOpen();
}
Expand Down
6 changes: 6 additions & 0 deletions turms-client-js/src/transport/websocket-metrics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default class WebSocketMetrics {
connectTime?: number;

dataReceived = 0;
dataSent = 0;
}
20 changes: 17 additions & 3 deletions turms-client-js/src/transport/worker-websocket-client.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,42 @@
import WebSocketClient, { EventListener } from './websocket-client';
import SharedContextService, { NotificationType, RequestType } from '../driver/service/shared-context-service';
import WebSocketMetrics from './websocket-metrics';

export default class WorkerWebSocketClient extends WebSocketClient {

private readonly _sharedContextService: SharedContextService;

private _isConnecting: boolean;
private _isConnected: boolean;
private _metrics = new WebSocketMetrics();

constructor(url: string, listener: EventListener, sharedContextService: SharedContextService) {
super(url, listener);
let connectStart;
sharedContextService.addNotificationListener(NotificationType.WEBSOCKET_CONNECTING, () => {
connectStart = new Date().getTime();
this._isConnecting = true;
this._isConnected = false;
});
sharedContextService.addNotificationListener(NotificationType.WEBSOCKET_CONNECTED, () => {
this._isConnecting = false;
this._isConnected = true;
this._metrics.connectTime = new Date().getTime() - connectStart;
this.notifyOnOpen();
});
sharedContextService.addNotificationListener(NotificationType.WEBSOCKET_CLOSED, notification => {
this._isConnecting = false;
this._isConnected = false;
this._metrics = new WebSocketMetrics();
this.notifyOnClose({
code: notification.data.code,
reason: notification.data.reason
});
});
sharedContextService.addNotificationListener(NotificationType.WEBSOCKET_MESSAGE_RECEIVED, notification => {
this.notifyOnMessage(notification.data);
const data = notification.data as ArrayBufferLike;
this._metrics.dataReceived += data.byteLength;
this.notifyOnMessage(data);
});
this._sharedContextService = sharedContextService;
sharedContextService.request({
Expand All @@ -47,13 +55,17 @@ export default class WorkerWebSocketClient extends WebSocketClient {
}

override get isConnecting(): boolean {
throw this._isConnecting;
return this._isConnecting;
}

override get isConnected(): boolean {
return this._isConnected;
}

override get metrics(): WebSocketMetrics {
return this._metrics;
}

override close(): void {
// do nothing
}
Expand All @@ -62,7 +74,9 @@ export default class WorkerWebSocketClient extends WebSocketClient {
return this._sharedContextService.request({
type: RequestType.SEND_DATA,
data
}).then();
}).then(() => {
this._metrics.dataSent += data instanceof Blob ? data.size : data.byteLength;
});
}

}

0 comments on commit 538fbb2

Please sign in to comment.