1
\$\begingroup\$

I've written some integrated tool which allows to save the console.log output to a file. The point is that this tool forwards each console.log call to the server by sending serial HTTP requests. So you will have a file containing all logs as the result.

It should be noted that the tool consist of two parts: client-side and server-side. The server-side part is a PHP script which must be placed on some web server; it processes requests from the client-side part. The client-side part (generated by the server-side part) is embedded as JavaScript code in a web page. It stores all logged data in some buffer and send its content to the server-side part as the buffer is about to be overflowed.

It seems to be worked. However I would like to see a general review for it.

Here is a sample of the client-side part:

if (!('logflush' in window)) {
(function() {

window.logflush = {
    log: function(s) {
        if (arguments.length <= 1) {
            if (typeof s == 'undefined') flushEx();
            else log(s);
            return;
        }
        var aArg = Array.prototype.slice.call(arguments, 1),
            n = aArg.length, i = 0;
        log(s.replace(/%[difso]/g, function(m) {
            return i < n? outExpr(aArg[i++]) : m;
        }));
    }
};
// Substitute console object so console.log() become alias of logflush.log()
window.console = window.logflush;

// Log session ID:
var ID = 'some_id';
// Flush processing URL:
var URL = 'http://example.com/script.php';
// Log buffer size (in bytes):
var BUFF_SIZE = 1000;
// Flush interval: minimal time between two consecutive flush requests
var INTERVAL = 1500;
// Background flush interval (background flushes aren't initiated by log calls unlike usual flushes)
var INTERVAL_BK = 30500;

// Queue of log flushes:
var aQueue = [];
// Log buffer:
var sBuff = '';
// Current flush timeout id:
var iTmr = 0;
// Page load timestamp:
var iStamp0 = 0;
// Current flush starting timestamp:
var iStamp = 0;
var nBkFlag = 0;

function log(s) {
    if (!ID || !s) return false;
    s = (iStamp0? (now()- iStamp0)+ '\t' : '')+ s+ '\n';
    if (encodeURIComponent(sBuff + s).length > BUFF_SIZE)
        push2Queue();
    sBuff += s;
    if (aQueue.length) flushEx();
    if (!nBkFlag) {
        nBkFlag = 1;
        setInterval(flushEx, INTERVAL_BK);
    }
    return true;
}

function flush() {
    if (!ID) return;
    if (iTmr) clearTimeout(iTmr);
    iTmr = iStamp = 0;
    if (!aQueue.length && sBuff)
        push2Queue();
    if (!aQueue.length) return;
    send('id='+ID+'&data='+ encodeURIComponent(aQueue.shift()), 1);
    iStamp = now();
    iTmr = setTimeout(flush, INTERVAL);
}

function flushEx() {
    if (!iStamp || now() - iStamp >= INTERVAL) flush();
}

function push2Queue() {
    if (aQueue.length > 30) aQueue.length = 0;
    aQueue.push(sBuff);
    sBuff = '';
}

function send(query) {
    var oReq = window.XMLHttpRequest? new XMLHttpRequest() :
        (window.ActiveXObject? new ActiveXObject('Microsoft.XMLHTTP') : null);
    if (!oReq) return;
    oReq.onreadystatechange = function() {
        if (oReq.readyState == 4 && oReq.status == 200 && oReq.responseText)
            onResponse(oReq.responseText);
    };
    oReq.open('POST', URL, true);
    oReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    oReq.send(query);
}

function onResponse(v) {
    if (v == 'denied') ID = '';
}

function now() {
    return (new Date()).getTime();
}

function outExpr(x) {
    if (typeof x != 'object' || x instanceof Date || x instanceof RegExp)
        return x;
    var s = '';
    for (var key in x)
        s += ', '+ key+ ':'+ outExpr(x[key]);
    return '{'+ (s? s.substr(2) : s)+ '}';
}

})();
}

Note that the body of send function may be different depending on the server-side script's location. If it is on different domain than the client-side part, then send function implements cross-domain request:

function send(query) {
    var script = document.createElement('script');
    script.src = URL+ '?'+ query+ '&callback=onResponse&_='+ now();
    document.body.appendChild(script);
}

Github repo.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.