mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-16 17:44:41 +00:00
dashboard: toggle SSE persistent connections based on document visibility
While SSE promises to be properly multiplexed over HTTP/2, it seems browsers still hit a hard limit when opening >6 connections. Since the streams are not critical, it's fine to abstract the eventsource logic to the base widget class where it manages open/closing connections based on tab visiblity. If we need more than 6 parallel streams, we need to revamp the logic to multiplex multiple event types in the backend ourselves, but this is not necessary for now.
This commit is contained in:
parent
341a4ce8c9
commit
a404e9c5a2
@ -188,6 +188,10 @@ class WidgetManager {
|
||||
widget.setId(id);
|
||||
this.widgetClasses[id] = widget;
|
||||
|
||||
document.addEventListener('visibilitychange', (e) => {
|
||||
this.widgetClasses[id].onVisibilityChanged(!document.hidden);
|
||||
});
|
||||
|
||||
if (!id in this.widgetTranslations) {
|
||||
console.error('Missing translations for widget', id);
|
||||
}
|
||||
|
||||
@ -31,6 +31,9 @@ export default class BaseWidget {
|
||||
this.translations = {};
|
||||
this.tickTimeout = 5000; // Default tick timeout
|
||||
this.resizeHandles = "all"
|
||||
this.eventSource = null;
|
||||
this.eventSourceUrl = null;
|
||||
this.eventSourceOnData = null;
|
||||
}
|
||||
|
||||
getResizeHandles() {
|
||||
@ -67,7 +70,40 @@ export default class BaseWidget {
|
||||
}
|
||||
|
||||
onWidgetClose() {
|
||||
return null;
|
||||
this.closeEventSource();
|
||||
}
|
||||
|
||||
openEventSource(url, onMessage) {
|
||||
this.closeEventSource();
|
||||
|
||||
this.eventSourceUrl = url;
|
||||
this.eventSourceOnData = onMessage;
|
||||
this.eventSource = new EventSource(url);
|
||||
this.eventSource.onmessage = onMessage;
|
||||
this.eventSource.onerror = (e) => {
|
||||
if (this.eventSource.readyState == EventSource.closed) {
|
||||
this.closeEventSource();
|
||||
} else {
|
||||
console.error('Unknown error occurred during streaming operation', e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
closeEventSource() {
|
||||
if (this.eventSource !== null) {
|
||||
this.eventSource.close();
|
||||
this.eventSource = null;
|
||||
}
|
||||
}
|
||||
|
||||
onVisibilityChanged(visible) {
|
||||
if (this.eventSourceUrl !== null) {
|
||||
if (visible) {
|
||||
this.openEventSource(this.eventSourceUrl, this.eventSourceOnData);
|
||||
} else if (this.eventSource !== null) {
|
||||
this.closeEventSource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* For testing purposes */
|
||||
|
||||
@ -32,7 +32,6 @@ export default class Cpu extends BaseWidget {
|
||||
constructor() {
|
||||
super();
|
||||
this.resizeHandles = "e, w";
|
||||
this.eventSource = null;
|
||||
}
|
||||
|
||||
_createChart(selector, timeSeries) {
|
||||
@ -85,12 +84,6 @@ export default class Cpu extends BaseWidget {
|
||||
return $container;
|
||||
}
|
||||
|
||||
onwidgetClose() {
|
||||
if (this.eventSource !== null) {
|
||||
this.eventSource.close();
|
||||
}
|
||||
}
|
||||
|
||||
async onMarkupRendered() {
|
||||
ajaxGet('/api/diagnostics/cpu_usage/getcputype', {}, (data, status) => {
|
||||
$('.cpu-type').text(data);
|
||||
@ -104,11 +97,9 @@ export default class Cpu extends BaseWidget {
|
||||
this._createChart('cpu-usage-intr', intr_ts);
|
||||
this._createChart('cpu-usage-user', user_ts);
|
||||
this._createChart('cpu-usage-sys', sys_ts);
|
||||
this.eventSource = new EventSource('/api/diagnostics/cpu_usage/stream');
|
||||
|
||||
this.eventSource.onmessage = function(event) {
|
||||
super.openEventSource('/api/diagnostics/cpu_usage/stream', (event) => {
|
||||
if (!event) {
|
||||
this.eventSource.close();
|
||||
super.closeEventSource();
|
||||
}
|
||||
const data = JSON.parse(event.data);
|
||||
let date = Date.now();
|
||||
@ -116,7 +107,7 @@ export default class Cpu extends BaseWidget {
|
||||
intr_ts.append(date, data.intr);
|
||||
user_ts.append(date, data.user);
|
||||
sys_ts.append(date, data.sys);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
onWidgetResize(elem, width, height) {
|
||||
|
||||
@ -33,7 +33,6 @@ export default class Firewall extends BaseTableWidget {
|
||||
constructor(config) {
|
||||
super();
|
||||
this.config = config;
|
||||
this.eventSource = null;
|
||||
this.ifMap = {};
|
||||
this.counters = {};
|
||||
this.chart = null;
|
||||
@ -86,7 +85,7 @@ export default class Firewall extends BaseTableWidget {
|
||||
|
||||
_onMessage(event) {
|
||||
if (!event) {
|
||||
this.eventSource.close();
|
||||
super.closeEventSource();
|
||||
}
|
||||
|
||||
let actIcons = {
|
||||
@ -190,8 +189,7 @@ export default class Firewall extends BaseTableWidget {
|
||||
return;
|
||||
}
|
||||
|
||||
this.eventSource = new EventSource('/api/diagnostics/firewall/streamLog');
|
||||
this.eventSource.onmessage = this._onMessage.bind(this);
|
||||
super.openEventSource('/api/diagnostics/firewall/streamLog', this._onMessage.bind(this));
|
||||
|
||||
let context = document.getElementById('fw-chart').getContext('2d');
|
||||
let config = {
|
||||
@ -285,9 +283,7 @@ export default class Firewall extends BaseTableWidget {
|
||||
}
|
||||
|
||||
onWidgetClose() {
|
||||
if (this.eventSource !== null) {
|
||||
this.eventSource.close();
|
||||
}
|
||||
super.onWidgetClose();
|
||||
|
||||
if (this.chart !== null) {
|
||||
this.chart.destroy();
|
||||
|
||||
@ -37,7 +37,6 @@ export default class Traffic extends BaseWidget {
|
||||
trafficOut: null
|
||||
};
|
||||
this.initialized = false;
|
||||
this.eventSource = null;
|
||||
this.datasets = {inbytes: [], outbytes: []};
|
||||
}
|
||||
|
||||
@ -155,7 +154,7 @@ export default class Traffic extends BaseWidget {
|
||||
|
||||
_onMessage(event) {
|
||||
if (!event) {
|
||||
this.eventSource.close();
|
||||
super.closeEventSource();
|
||||
}
|
||||
|
||||
const data = JSON.parse(event.data);
|
||||
@ -199,15 +198,12 @@ export default class Traffic extends BaseWidget {
|
||||
}
|
||||
|
||||
async onMarkupRendered() {
|
||||
this.eventSource = new EventSource('/api/diagnostics/traffic/stream/2');
|
||||
this.eventSource.onmessage = this._onMessage.bind(this);
|
||||
super.openEventSource('/api/diagnostics/traffic/stream/1', this._onMessage.bind(this));
|
||||
}
|
||||
|
||||
onWidgetClose() {
|
||||
super.onWidgetClose();
|
||||
this.charts.trafficIn.destroy();
|
||||
this.charts.trafficOut.destroy();
|
||||
if (this.eventSource !== null) {
|
||||
this.eventSource.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user