Shortly after 05:00 UTC this morning, the Stack Exchange WebSocket started misbehaving. It (assumed) initially restarted at 05:01 UTC. Then, starting at 05:10 UTC, the server has been closing the WebSocket connection every couple of minutes. The closure happens 100 seconds after the most recent data is sent by the server.
Normal operation
Normal operation for the WebSocket is that once opened and subscribed the server sends a "hb" every 5 minutes and then closes the connection if it doesn't receive a "hb" message back. As long as these "heartbeat" messages are replied to, the WebSocket can, normally, be kept open indefinitely.
Testing
The following code opens a WebSocket connection to monitor activity on this question. If a "hb" is sent by the server (usually every 5 minutes), then it will reply with a "hb". Under normal conditions, this would keep the connection open indefinitely. Unfortunately, at the moment, the server will close the connection without sending a "hb".
As currently written, the following test will open 10 WebSockets to Stack Exchange all of which will monitor this question. A record is kept of the total number of heartbeat messages received, which should be 1 every 5 minutes for each of the WebSockets, and the total number of times that the WebSockets are closed (by Stack Exchange or other network disruption). Unfortunately, the code doesn't currently track the distribution of how long the WebSockets remain open, as that would be a much more interesting number, both for the performance of Stack Exchange pages, but also for SmokeDetector and other consumers of the WebSocket data.
(() => {
'use strict';
const NUMBER_OF_WEBSOCKETS = 10;
const webSockets = Array(NUMBER_OF_WEBSOCKETS);
webSockets.fill(null);
let closing = false;
let startTime = 0;
const passEl = document.getElementById('pass');
const failEl = document.getElementById('fail');
const failPercentEl = document.getElementById('failPercent');
const startTimeEl = document.getElementById('startTime');
const elapsedTimeEl = document.getElementById('elapsedTime');
const diffLabel = {
days: 'd',
hours: 'h',
minutes: 'm',
seconds: 's',
};
const diffOrder = [
'days',
'hours',
'minutes',
'seconds',
];
function incrementAndShowPercent(addPass, addFail, noAdd) {
if (noAdd || closing) {
return;
}
const pass = +passEl.textContent + addPass;
passEl.textContent = pass;
const fail = +failEl.textContent + addFail;
failEl.textContent = fail;
const failPercent = Math.round((10000 * fail) / (pass + fail))/100
failPercentEl.textContent = failPercent;
if (fail) {
failEl.classList.add('isFailing');
failPercentEl.classList.add('isFailing');
}
/* The elapsed time code was copied, then significantly modified, from
* https://codereview.stackexchange.com/a/160240/53535 by Przemek
* https://codereview.stackexchange.com/users/97934/przemek */
const elapsed = (Date.now() - startTime) / 1000;
const diff = {
days: Math.floor(elapsed / 86400),
hours: Math.floor((elapsed / 3600) % 24),
minutes: Math.floor((elapsed / 60) % 60),
seconds: Math.floor(elapsed % 60),
};
const elapsedText = diffOrder.reduce((sum, key) => {
if (sum || diff[key] || key === 'seconds') {
sum += ` ${diff[key]}${diffLabel[key]}`;
}
return sum;
}, '').trim();
elapsedTimeEl.textContent = elapsedText;
}
function startAWebSocket(entry, socketIndex) {
let webSocket = null;
let noAdd = true;
function registerWebSocket() { // eslint-disable-line no-unused-vars
if (webSocket) {
if (typeof webSocket.removeEventListener === 'function') {
//There can be additional events that mess up the count.
webSocket.removeEventListener('message', socketOnMessage);
}
if (typeof webSocket.close === 'function') {
// Close any existing WebSocket.
webSocket.close();
}
}
webSocket = new WebSocket('wss://qa.sockets.stackexchange.com');
webSockets[socketIndex] = webSocket;
webSocket.addEventListener('message', socketOnMessage);
webSocket.addEventListener('open', () => {
webSocket.send('4-question-400186');
console.info(`WS[${socketIndex}]: Open & Subscribed to this question`);
noAdd = false;
});
webSocket.addEventListener('close', event => {
if (!noAdd && !closing) {
console.error(`WS[${socketIndex}]: Closed: event.code`, event.code, ':: event:', event);
incrementAndShowPercent(0, 1, noAdd);
noAdd = true;
registerWebSocket();
} else {
if (event.wasClean !== true || event.reason !== 'ok' || event.code !== 1000) {
console.error(`WS[${socketIndex}]: Closed: event.code`, event.code, ':: event:', event);
} else {
console.info(`WS[${socketIndex}]: Closed: normal closure`);
}
}
});
webSocket.addEventListener('error', event => {
console.error(`WS[${socketIndex}]: Error:`);
console.log(`WS[${socketIndex}]: Error: event`, event);
});
}
function socketOnMessage(event) {
const messageObject = JSON.parse(event.data);
const data = messageObject.data;
let dataObject = data;
try {
dataObject = JSON.parse(data);
} catch(error) {
// Ignore any errors
}
messageObject.data = dataObject;
if (messageObject.action === 'hb') {
//The hb is every 5 minutes.
incrementAndShowPercent(1, 0, noAdd);
webSocket.send(data);
console.info(`WS[${socketIndex}]: heartbeat received & responded to`);
} else {
console.log(`WS[${socketIndex}]: non-heartbeat: messageObject:`, messageObject);
}
}
registerWebSocket();
}
function startAllWebSockets() {
console.log(`vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv Start test with ${NUMBER_OF_WEBSOCKETS} WebSockets`);
webSockets.forEach(startAWebSocket);
}
function stopAllWebSockets() {
closing = true;
Promise.all(webSockets.map((webSocket) => new Promise((resolve) => {
webSocket.addEventListener('close', resolve);
webSocket.close();
})))
.then(() => {
console.log('WS: All WebSockets closed at end of test');
console.log('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ End test');
webSockets.fill(null);
closing = false;
});
}
document.getElementById('start').addEventListener('click', () => {
passEl.textContent = 0;
failEl.textContent = 0;
failEl.classList.remove('isFailing');
failPercentEl.textContent = 0;
failPercentEl.classList.remove('isFailing');
startTime = Date.now();
startTimeEl.textContent = (new Date(startTime)).toISOString();
closing = false;
startAllWebSockets();
});
document.getElementById('stop').addEventListener('click', stopAllWebSockets);
})();
span:not([id]) {
margin-left: 10px;
}
span.extraSpace {
margin-left: 20px;
}
#fail.isFailing,
#failPercent.isFailing {
color: red;
font-weight: bold;
}
#pass,
#failPercent {
color: #00d000;
font-weight: bold;
}
<button id="start">Start/Restart</button>
<button id="stop">Stop</button>
<span> heartbeats: <span id="pass">0</span></span>
<span> Closures: <span id="fail">0</span></span>
<span>Closures %: <span id="failPercent">0</span> %</span>
<span class="extraSpace">Started: <span id="startTime"></span></span>
<span class="extraSpace">Elapsed: <spam id="elapsedTime"></span></span>
</br>You may want to open the Web Console (F12), as it's easier to read the output there.</br>
Monitoring trace
The following is the console output of monitoring the question activity for question #400179 for an hour or so, and shows that the WebSocket wasn't closed until 100 seconds after the most recent activity.
14:39:47.796 Monitor WS: initialized. SE:-Monitor-WebSocket.user.js:679:19
14:39:48.854 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
14:39:48.856 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
14:41:28.703 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
14:41:28.705 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
14:41:30.232 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
14:41:30.234 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
14:43:10.147 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
14:43:10.147 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
14:43:11.771 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
14:43:11.772 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
14:44:37.512 Monitor WS: messageObject:
Object { action: "4-question-400179", data: {…} }
:: data:
Object { a: "score", id: 400179, score: 6 }
SE:-Monitor-WebSocket.user.js:718:13
14:45:20.412 Monitor WS: messageObject:
Object { action: "4-question-400179", data: {…} }
:: data:
Object { a: "score", id: 400179, score: 5 }
SE:-Monitor-WebSocket.user.js:718:13
14:46:12.296 Monitor WS: messageObject:
Object { action: "4-question-400179", data: {…} }
:: data:
Object { a: "score", id: 400179, score: 6 }
SE:-Monitor-WebSocket.user.js:718:13
14:46:27.434 Monitor WS: messageObject:
Object { action: "4-question-400179", data: {…} }
:: data:
Object { a: "score", id: 400179, score: 5 }
SE:-Monitor-WebSocket.user.js:718:13
14:48:07.440 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
14:48:07.443 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
14:48:11.470 Monitor WS: Error: SE:-Monitor-WebSocket.user.js:664:19
14:48:11.471 Monitor WS: Error: event
error { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:665:19
14:48:13.552 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
14:48:13.553 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
14:49:53.472 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
14:49:53.473 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
14:49:55.163 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
14:49:55.164 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
14:51:35.083 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
14:51:35.085 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
14:51:37.594 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
14:51:37.595 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
14:53:17.507 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
14:53:17.507 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
14:53:19.868 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
14:53:19.871 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
14:54:32.212 Monitor WS: messageObject:
Object { action: "4-question-400179", data: {…} }
:: data:
Object { a: "score", id: 400179, score: 6 }
SE:-Monitor-WebSocket.user.js:718:13
14:56:12.217 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
14:56:12.218 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
14:56:14.772 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
14:56:14.773 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
14:57:54.678 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
14:57:54.679 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
14:57:56.247 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
14:57:56.248 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
14:59:36.161 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
14:59:36.162 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
14:59:37.978 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
14:59:37.979 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:01:17.908 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:01:17.910 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:01:20.124 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:01:20.126 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:03:00.026 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:03:00.027 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:03:01.684 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:03:01.685 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:04:41.604 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:04:41.605 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:04:44.258 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:04:44.259 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:06:24.184 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:06:24.185 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:06:25.734 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:06:25.735 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:08:05.655 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:08:05.656 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:08:07.139 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:08:07.140 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:09:47.058 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:09:47.058 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:09:49.131 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:09:49.132 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:11:29.063 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:11:29.064 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:11:31.885 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:11:31.886 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:13:11.801 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:13:11.802 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:13:13.411 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:13:13.412 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:14:53.314 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:14:53.321 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:14:54.847 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:14:54.848 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:16:34.751 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:16:34.752 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:16:37.640 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:16:37.641 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:18:17.552 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:18:17.553 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:18:20.141 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:18:20.142 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:20:00.063 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:20:00.065 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:20:02.329 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:20:02.329 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:21:42.404 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:21:42.405 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:21:44.253 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:21:44.254 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:23:24.172 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:23:24.174 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:23:26.296 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:23:26.297 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:25:06.181 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:25:06.181 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:25:08.551 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:25:08.552 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:26:48.436 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:26:48.436 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:26:50.452 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:26:50.453 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:28:30.372 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:28:30.373 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19
15:28:32.285 Monitor WS: Open: SE:-Monitor-WebSocket.user.js:634:19
15:28:32.286 Monitor WS: Subscribed to site: 4 :: question: 400179 SE:-Monitor-WebSocket.user.js:770:13
15:30:12.191 Monitor WS: Closed: SE:-Monitor-WebSocket.user.js:657:19
15:30:12.192 Monitor WS: Closed: event.code undefined :: event:
close { target: div, isTrusted: false, srcElement: div, currentTarget: div, eventPhase: 2, bubbles: false, cancelable: false, returnValue: true, defaultPrevented: false, composed: false, … }
SE:-Monitor-WebSocket.user.js:658:19