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 {
|
||||
constructor() {
|
||||
this._socket = null;
|
||||
@@ -85,6 +87,58 @@ class SocketManager {
|
||||
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.
|
||||
// Subsequent calls return the same promise.
|
||||
_ensureSocket() {
|
||||
@@ -111,6 +165,8 @@ class SocketManager {
|
||||
this.reauthPromise = this._reauthenticate();
|
||||
});
|
||||
|
||||
this._installSocketTelemetry(this._socket);
|
||||
|
||||
// Register any listeners that arrived before the socket was ready
|
||||
this._preSocketListeners.forEach(({ event, callback }) => {
|
||||
this._socket.on(event, callback);
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
|
||||
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, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
@@ -13,6 +17,10 @@ function send(payload) {
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
function send(payload) {
|
||||
reportJsErrorTelemetry(payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register global listeners once. Safe to call in browser only.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user