Viewing File: /usr/local/cpanel/base/sharedjs/LogTail.js
/* jshint -W035 */
/* jshint -W116 */
(function(window) {
"use strict";
var YAHOO = window.YAHOO;
var QUEUE_TIMER_INTERVAL = 250;
var MAX_TAIL_ERRORS = 10; // cpsrvd may send a 307 or 301 so we need to be able to reconnect
var MAX_ERROR_COUNT = 150;
var IE_READY_STATE_MAP = {
"uninitialized": 0,
"loading": 1,
"loaded": 2,
"interactive": 3,
"complete": 4
};
var LogTail = function(systemId, sessionId, tail_name, masterErrorProcessorObj) {
this._systemId = systemId;
this._sessionId = sessionId;
this._logs = {};
this._termination_integer = Math.floor(Math.random() * (10000000000));
this._termination_sequence = "[tail_end:" + this._termination_integer + "]";
this._tail_name = tail_name;
this._tail_errors = 0;
this._deletedLogs = {};
this._string_position = 0;
this._reached_end = 0;
this._logsChanged = 0;
this._masterErrorProcessorObj = masterErrorProcessorObj;
};
YAHOO.lang.augmentObject(LogTail.prototype, {
start: function() {
alert("Please use .addLog and .delLog");
},
abort: function() {
console.trace("failed to create abort object");
},
delLog: function(logFile) {
delete this._logs[logFile];
this._deletedLogs[logFile] = 1;
if (!this.hasLogs()) {
this._logsChanged = 0;
if (this._queue_timer) {
window.clearInterval(this._queue_timer);
this._queue_timer = null;
}
}
},
processLogQueue: function() {
if (this._logsChanged) {
if (this.hasLogs()) {
this._send_request();
}
this._logsChanged = 0;
}
if (!this._reached_end) {
this._process_request();
}
},
addRawLog: function(logFile, logProcessorFunc) {
this.addLog(logFile, logProcessorFunc);
this._logs[logFile]["raw"] = 1;
},
addLog: function(logFile, logProcessorFunc) {
if (!this.hasLogs()) {
if (this._queue_timer) {
window.clearInterval(this._queue_timer);
this._queue_timer = null;
}
this._queue_timer = window.setInterval(this.processLogQueue.bind(this), QUEUE_TIMER_INTERVAL);
}
this._logs[logFile] = {
"bytes_processed": 0,
"raw": 0,
"err_count": 0,
"logProcessorFunc": logProcessorFunc
};
this._logsChanged = 1;
},
hasLogs: function() {
for (var k in this._logs) {
if (this._logs.hasOwnProperty(k)) {
return true;
}
}
},
logCount: function() {
return Object.keys(this._logs).length;
},
_send_request: function() {
if (this._request && YAHOO.util.Connect.isCallInProgress(this._request)) {
YAHOO.util.Connect.abort(this._request);
}
this._string_position = 0;
this._reached_end = 0;
this._deletedLogs = {};
var query = {
system_id: this._systemId,
session_id: this._sessionId,
"termination_integer": this._termination_integer
};
var file_count = 0;
for (var logFile in this._logs) {
if (this._logs.hasOwnProperty(logFile)) {
file_count++;
query["log_file" + file_count] = logFile;
query["log_file_position" + file_count] = this._logs[logFile].bytes_processed;
}
}
var target_url = "../cgi/live_tail_log.cgi" + "?" + CPANEL.util.make_query_string(query);
if (YAHOO.env.ua.ie && YAHOO.env.ua.ie < 9) {
if (this._iframeEl) {
this._iframeEl.parentNode.removeChild(this._iframeEl);
}
this._iframeEl = document.createElement("iframe");
this._iframeEl.style.display = "none";
DOM.get("content").appendChild(this._iframeEl);
this._iframeEl.contentWindow.location.href = target_url;
} else {
this._request = YAHOO.util.Connect.asyncRequest(
"GET",
target_url, {
"success": this._process_request.bind(this),
"failure": this._handle_tail_failure.bind(this),
}
);
}
this.abort = function() {
this._reached_end = 1;
if (this._iframeEl) {
this._iframeEl.contentWindow.location.href = "about:blank";
}
if (this._request) {
YAHOO.util.Connect.abort(this._request);
}
};
this.abort.bind(this);
return 1;
},
// YUI 2 assigns values of 0 for non-HTTP responses and -1 for aborted
// transactions. In either of these cases, we should NOT print an error.
_handle_tail_failure: function(o) {
if ((o.status > 0) && (o.status !== 200)) {
++this._tail_errors;
var errmsg = LOCALE.maketext("[asis,live_tail_log] encountered an internal error: [_1]", o.statusText);
if (o.status !== 301 && o.status !== 307 && this._masterErrorProcessorObj) {
this._masterErrorProcessorObj.renderMessage(errmsg);
}
if ( this._tail_errors >= MAX_TAIL_ERRORS) {
var finalmsg = LOCALE.maketext("[asis,live_tail_log] encountered the maximum allowed errors ([numf,_1]) and will not continue.", this._tail_errors);
if (this._masterErrorProcessorObj) {
this._masterErrorProcessorObj.renderMessage(finalmsg);
} else {
alert(o.statusText);
alert(finalmsg);
}
this.abort();
return 0;
}
}
this._logsChanged = 1; /* force request to be resent */
},
_process_request: function(o) {
var xhr;
if (o) { /* yuiCallback */
xhr = o;
xhr.readyState = 4;
} else if (this._request && this._request.conn) { /* poll */
xhr = this._request.conn;
} else if (this._iframeEl) {
if (!this._iframeEl.contentWindow.document.body) {
return; /* not loaded yet */
}
xhr = {
"readyState": IE_READY_STATE_MAP[this._iframeEl.readyState],
"responseText": this._iframeEl.contentWindow.document.body.innerText ? this._iframeEl.contentWindow.document.body.innerText : this._iframeEl.contentWindow.document.body.textContent
};
/* IE work around */
if (xhr.readyState === 4) {
xhr.responseText += this._newline;
}
} else {
return;
}
var rawdata;
try {
rawdata = xhr.responseText.substr(this._string_position);
} catch (e) {
return;
}
var lastEndofLine = rawdata.lastIndexOf(this._newline);
if (lastEndofLine > -1) {
this._string_position += (lastEndofLine + this._newline.length);
var newdata = rawdata.substr(0, lastEndofLine);
var log_data_arr = newdata.split(this._newline);
for (var i = 0; i < log_data_arr.length; i++) {
if (log_data_arr[i] === ".") {
this._tail_errors = 0;
/* keep alive */
continue;
} else if (log_data_arr[i] === this._termination_sequence) {
/* end of stream */
this._reached_end = 1;
continue;
} else if ( log_data_arr[i] === "" ) {
continue;
} else if (log_data_arr[i].indexOf("|") === -1) {
this._handle_tail_failure({ "status": 500, "statusText": log_data_arr[i] });
continue;
}
var demultiplexedData = log_data_arr[i].split("|");
var logFile = demultiplexedData.shift();
var server_length = parseInt(demultiplexedData.shift());
var data = demultiplexedData.join("|");
if (data) {
if (this._deletedLogs[logFile]) {
// console.log("deleted log: " + log_data_arr[i]);
} else if (!this._logs[logFile]) {
// console.log("unknown log: " + log_data_arr[i]);
} else {
this._tail_errors = 0;
this._logs[logFile].bytes_processed += server_length;
this._log_processor(logFile, data);
}
} else {
// If there is no data we don't want to log it - this allows us to ignore empty lines
}
}
}
if (xhr.readyState === 4) {
if (this._reached_end) {
this._logs = {};
if (this._queue_timer) {
window.clearInterval(this._queue_timer);
this._queue_timer = null;
}
} else {
this._logsChanged = 1;
}
}
return 1;
},
_log_processor: function(logFile, data) {
if (this._logs[logFile].raw) {
return this._logs[logFile].logProcessorFunc(data, logFile);
}
var msg = "";
try {
if (data.indexOf("{") !== 0) {
throw "Non JSON data passed to parser.";
}
msg = JSON.parse(data);
} catch (e) {
this._logs[logFile].err_count++;
if (this._logs[logFile].err_count === MAX_ERROR_COUNT) {
data = LOCALE.maketext("Too many errors from “[_1]”. Future errors will be suppressed.", logFile);
}
if (this._logs[logFile].err_count <= MAX_ERROR_COUNT) {
msg = {
"type": "error",
"contents": {
"msg": [data]
}
};
}
}
if (msg) {
return this._logs[logFile].logProcessorFunc(msg, logFile);
}
},
_newline: ((YAHOO.env.ua.ie && YAHOO.env.ua.ie < 9) ? "\r\n" : "\n")
});
window.LogTail = LogTail;
}(window));
Back to Directory
File Manager