feat: Implement socket error telemetry in SocketManager to enhance error reporting for socket.io events
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
import { reportJsErrorTelemetry } from '../utils/jsErrorTelemetry.js';
|
||||||
|
|
||||||
class SocketManager {
|
class SocketManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._socket = null;
|
this._socket = null;
|
||||||
@@ -85,6 +87,58 @@ class SocketManager {
|
|||||||
return this.reauthPromise;
|
return this.reauthPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report socket.io client errors to /api/telemetry/js-errors (richer than promise rejections alone).
|
||||||
|
*/
|
||||||
|
_installSocketTelemetry(socket) {
|
||||||
|
const report = (eventName, err) => {
|
||||||
|
const message =
|
||||||
|
err && typeof err.message === 'string' && err.message.trim()
|
||||||
|
? err.message
|
||||||
|
: err != null
|
||||||
|
? String(err)
|
||||||
|
: eventName;
|
||||||
|
reportJsErrorTelemetry({
|
||||||
|
message,
|
||||||
|
name: err && err.name,
|
||||||
|
stack: err && err.stack,
|
||||||
|
url: typeof window !== 'undefined' ? window.location.href : undefined,
|
||||||
|
context: {
|
||||||
|
type: 'socket.io',
|
||||||
|
event: eventName,
|
||||||
|
connected: Boolean(socket.connected),
|
||||||
|
...(socket.id ? { socketId: socket.id } : {}),
|
||||||
|
...(socket.io?.engine?.transport?.name
|
||||||
|
? { transport: socket.io.engine.transport.name }
|
||||||
|
: {}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.on('connect_error', (err) => {
|
||||||
|
report('connect_error', err);
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('error', (err) => {
|
||||||
|
report('error', err);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (socket.io) {
|
||||||
|
socket.io.on('reconnect_error', (err) => {
|
||||||
|
report('reconnect_error', err);
|
||||||
|
});
|
||||||
|
socket.io.on('reconnect_failed', () => {
|
||||||
|
report('reconnect_failed', new Error('reconnect_failed'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socket.io?.engine) {
|
||||||
|
socket.io.engine.on('error', (err) => {
|
||||||
|
report('engine_error', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Lazily import socket.io-client and create the socket on first use.
|
// Lazily import socket.io-client and create the socket on first use.
|
||||||
// Subsequent calls return the same promise.
|
// Subsequent calls return the same promise.
|
||||||
_ensureSocket() {
|
_ensureSocket() {
|
||||||
@@ -111,6 +165,8 @@ class SocketManager {
|
|||||||
this.reauthPromise = this._reauthenticate();
|
this.reauthPromise = this._reauthenticate();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._installSocketTelemetry(this._socket);
|
||||||
|
|
||||||
// Register any listeners that arrived before the socket was ready
|
// Register any listeners that arrived before the socket was ready
|
||||||
this._preSocketListeners.forEach(({ event, callback }) => {
|
this._preSocketListeners.forEach(({ event, callback }) => {
|
||||||
this._socket.on(event, callback);
|
this._socket.on(event, callback);
|
||||||
|
|||||||
@@ -5,7 +5,11 @@
|
|||||||
|
|
||||||
const TELEMETRY_PATH = '/api/telemetry/js-errors';
|
const TELEMETRY_PATH = '/api/telemetry/js-errors';
|
||||||
|
|
||||||
function send(payload) {
|
/**
|
||||||
|
* POST a single error report (same shape as one element of `errors[]`).
|
||||||
|
* Used by global handlers and by SocketManager for socket.io failures.
|
||||||
|
*/
|
||||||
|
export function reportJsErrorTelemetry(payload) {
|
||||||
fetch(TELEMETRY_PATH, {
|
fetch(TELEMETRY_PATH, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
@@ -13,6 +17,10 @@ function send(payload) {
|
|||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function send(payload) {
|
||||||
|
reportJsErrorTelemetry(payload);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register global listeners once. Safe to call in browser only.
|
* Register global listeners once. Safe to call in browser only.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user