mirror of
https://github.com/overte-org/overte.git
synced 2025-06-04 00:11:32 +02:00
246 lines
7.2 KiB
JavaScript
246 lines
7.2 KiB
JavaScript
const remote = require('electron').remote;
|
|
const os = require('os');
|
|
const fs = require('fs');
|
|
const Tail = require('always-tail');
|
|
|
|
function cleanPath(path) {
|
|
if (os.type() == "Windows_NT") {
|
|
// Fix path on Windows
|
|
while (path.indexOf('\\') >= 0) {
|
|
path = path.replace('\\', '/', 'g');
|
|
}
|
|
}
|
|
return path;
|
|
}
|
|
|
|
// a: array, b: array
|
|
// Returns: { add: [...], subtract: [...] }
|
|
// add: array of items in b but not a
|
|
// subtract: array of items in a but not b
|
|
function difference(a, b) {
|
|
var add = [];
|
|
var subtract = [];
|
|
for (var k of a) {
|
|
if (b.indexOf(k) == -1) {
|
|
// In a, but not in b
|
|
subtract.push(k);
|
|
}
|
|
}
|
|
for (k of b) {
|
|
if (a.indexOf(k) == -1) {
|
|
// In b, but not in a
|
|
add.push(k);
|
|
}
|
|
}
|
|
return {
|
|
add: add,
|
|
subtract: subtract
|
|
};
|
|
}
|
|
|
|
ready = function() {
|
|
window.$ = require('./vendor/jquery/jquery-2.1.4.min.js');
|
|
|
|
var domainServer = remote.getGlobal('domainServer');
|
|
var acMonitor = remote.getGlobal('acMonitor');
|
|
var openLogDirectory = remote.getGlobal('openLogDirectory');
|
|
|
|
var pendingLines = {
|
|
'ds': new Array(),
|
|
'ac': new Array()
|
|
};
|
|
|
|
var UPDATE_INTERVAL = 16; // Update log at ~60 fps
|
|
var interval = setInterval(flushPendingLines, UPDATE_INTERVAL);
|
|
|
|
var logWatchers = {
|
|
'ds': {
|
|
},
|
|
'ac': {
|
|
}
|
|
};
|
|
|
|
function updateLogWatchers(stream, watchList, newLogFilesByPID) {
|
|
// Consolidate into a list of the log paths
|
|
var newLogFilePaths = [];
|
|
for (var pid in newLogFilesByPID) {
|
|
newLogFilePaths.push(newLogFilesByPID[pid].stdout);
|
|
newLogFilePaths.push(newLogFilesByPID[pid].stderr);
|
|
}
|
|
|
|
var oldLogFilePaths = Object.keys(watchList);
|
|
var diff = difference(oldLogFilePaths, newLogFilePaths);
|
|
// For each removed file, remove it from our watch list
|
|
diff.subtract.forEach(function(removedLogFilePath) {
|
|
watchList[removedLogFilePath].unwatch();
|
|
delete watchList[removedLogFilePath];
|
|
console.log("Unwatching", removedLogFilePath);
|
|
});
|
|
diff.add.forEach(function(addedLogFilePath) {
|
|
const START_AT_X_BYTES_FROM_END = 10000;
|
|
var cleanFilePath = cleanPath(addedLogFilePath);
|
|
|
|
// For larger files we won't want to start tailing from the beginning of the file,
|
|
// so start `START_AT_X_BYTES_FROM_END` bytes from the end of the file.
|
|
var start = 0;
|
|
try {
|
|
var fileInfo = fs.statSync(cleanFilePath);
|
|
start = Math.max(0, fileInfo.size - START_AT_X_BYTES_FROM_END);
|
|
} catch (e) {
|
|
console.error("ERROR READING FILE INFO", e);
|
|
}
|
|
var logTail = new Tail(cleanFilePath, '\n', { start: start, interval: 500 });
|
|
|
|
logTail.on('line', function(msg) {
|
|
pendingLines[stream].push(msg);
|
|
});
|
|
|
|
logTail.on('error', function(error) {
|
|
console.log("ERROR:", error);
|
|
});
|
|
|
|
logTail.watch();
|
|
|
|
watchList[addedLogFilePath] = logTail;
|
|
console.log("Watching", cleanFilePath);
|
|
});
|
|
}
|
|
|
|
function updateLogFiles() {
|
|
// Get ds and ac logs from main application
|
|
var dsLogs = domainServer.getLogs();
|
|
var acLogs = acMonitor.getLogs();
|
|
|
|
updateLogWatchers('ds', logWatchers.ds, dsLogs);
|
|
updateLogWatchers('ac', logWatchers.ac, acLogs);
|
|
}
|
|
|
|
window.onbeforeunload = function(e) {
|
|
clearInterval(interval);
|
|
domainServer.removeListener('logs-updated', updateLogFiles);
|
|
acMonitor.removeListener('logs-updated', updateLogFiles);
|
|
};
|
|
|
|
domainServer.on('logs-updated', updateLogFiles);
|
|
acMonitor.on('logs-updated', updateLogFiles);
|
|
|
|
|
|
const maxLogLines = 2500;
|
|
const ipcRenderer = require('electron').ipcRenderer;
|
|
|
|
var currentTab = 'domain-server';
|
|
var tabStates = {
|
|
'domain-server': {
|
|
atBottom: true,
|
|
size: 0
|
|
},
|
|
'assignment-client': {
|
|
atBottom: true,
|
|
size: 0
|
|
}
|
|
};
|
|
function setCurrentTab(tabId) {
|
|
if (currentTab == tabId) {
|
|
return;
|
|
}
|
|
|
|
var padding = 15;
|
|
$currentTab = $('#' + currentTab);
|
|
tabStates[currentTab].atBottom = $currentTab[0].scrollTop >= ($currentTab[0].scrollHeight - $currentTab.height() - (2 * padding));
|
|
|
|
currentTab = tabId;
|
|
$('ul.tabs li').removeClass('current');
|
|
$('.tab-pane').removeClass('current');
|
|
|
|
$('li[data-tab=' + tabId + ']').addClass('current');
|
|
var $pidLog = $("#" + tabId);
|
|
$pidLog.addClass('current');
|
|
|
|
if (tabStates[tabId].atBottom) {
|
|
$pidLog.scrollTop($pidLog[0].scrollHeight);
|
|
}
|
|
}
|
|
|
|
$('ul.tabs li').click(function() {
|
|
setCurrentTab($(this).attr('data-tab'));
|
|
});
|
|
|
|
setCurrentTab('domain-server');
|
|
setCurrentTab('assignment-client');
|
|
|
|
var filter = "";
|
|
|
|
function shouldDisplayLogMessage(message) {
|
|
return !filter || message.toLowerCase().indexOf(filter) >= 0;
|
|
}
|
|
|
|
function appendLogMessages(name) {
|
|
var array = pendingLines[name];
|
|
if (array.length === 0) {
|
|
return;
|
|
}
|
|
if (array.length > maxLogLines) {
|
|
array = array.slice(-maxLogLines);
|
|
}
|
|
|
|
console.log(name, array.length);
|
|
|
|
var id = name == "ds" ? "domain-server" : "assignment-client";
|
|
var $pidLog = $('#' + id);
|
|
|
|
var size = tabStates[id].size + array.length;
|
|
if (size > maxLogLines) {
|
|
$pidLog.find('div.log-line:lt(' + (size - maxLogLines) + ')').remove();
|
|
}
|
|
|
|
var wasAtBottom = false;
|
|
if (currentTab == id) {
|
|
wasAtBottom = $pidLog[0].scrollTop >= ($pidLog[0].scrollHeight - $pidLog.height());
|
|
}
|
|
|
|
for (line in array) {
|
|
var $logLine = $('<div class="log-line">').text(array[line]);
|
|
if (!shouldDisplayLogMessage(array[line])) {
|
|
$logLine.hide();
|
|
}
|
|
|
|
$pidLog.append($logLine);
|
|
}
|
|
|
|
delete pendingLines[name];
|
|
pendingLines[name] = new Array();
|
|
|
|
if (wasAtBottom) {
|
|
$pidLog.scrollTop($pidLog[0].scrollHeight);
|
|
}
|
|
}
|
|
function flushPendingLines() {
|
|
appendLogMessages('ds');
|
|
appendLogMessages('ac');
|
|
}
|
|
|
|
// Binding a remote function directly does not work, so bind to a function
|
|
// that calls the remote function.
|
|
$('#view-logs').on('click', function() {
|
|
openLogDirectory();
|
|
});
|
|
|
|
// handle filtering of table rows on input change
|
|
$('#search-input').on('input', function() {
|
|
filter = $(this).val().toLowerCase();
|
|
if (filter == "") {
|
|
$('.log-line').show();
|
|
} else {
|
|
$('.log-line').each(function(){
|
|
// decide to hide or show the row if it matches the filter
|
|
if (filter && $(this).text().toLowerCase().indexOf(filter) == -1) {
|
|
$(this).hide();
|
|
} else {
|
|
$(this).show();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
updateLogFiles();
|
|
};
|