console 方法

(function(window) {
    var LOG_LEVELS = ["DEBUG", "LOG", "INFO", "WARN", "ERROR"], //日志级别
        //TODO 是否可以做成队列阈值和倒计时时间由UI配置?
        THRESHOLD = 200, // 触发日志上传的阈值,设置大一点,避免高频的请求导致并发问题
        TIMER = 1000, // 倒计时,间隔发送时间
        URL = location.protocol + "//__rosin__.qq.com",
        KEY = +new Date() + '_' + parseInt(Math.random() * 1e8); // 每个页面生成一个唯一key

    // https的请求,使用另外的通信协议
    if(location.protocol === "https:") {
        URL = "https://" + location.host + '/?__rosin__';
    }

    /**
     * 上传任务队列
     * 队列长度达到阈值触发POST日志
     * @type {{_queueArr: Array, add: add, _post: _post}}
     */
    var queue = {
        _queueArr: [], //数组模拟队列
        add: function() {
            Array.prototype.push.apply(this._queueArr, arguments);
            clock.start();

            //队列达到阈值就触发上传
            if (this._queueArr.length >= THRESHOLD) {
                this._post(this._queueArr.splice(0, this._queueArr.length));
                return;
            }
        },
        _post: function(logArr) {
            var headers = {};
            var setHeader = function(name, value) {
                headers[name.toLowerCase()] = [name, value]
            };
            var xhr = new XMLHttpRequest();
            var nativeSetHeader = xhr.setRequestHeader;

            setHeader('Accept', '*/*');

            setHeader('Content-Type', 'application/x-www-form-urlencoded');

            xhr.setRequestHeader = setHeader;
            xhr.onreadystatechange = function(){}; // do nothing
            xhr.open('POST', URL, true);
            // chrome 控制台会看到一个报错
            // A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true.
            // xhr.withCredentials = true;

            for (name in headers) nativeSetHeader.apply(xhr, headers[name]);
            
            xhr.send(JSON.stringify(logArr));
        }
    },

    /**
     * 自定义日志对象
     * @type {{DELIMITER: string, _record: _record, debug: debug, log: log, info: info, warn: warn, error: error}}
     */
    FConsole = {
        DELIMITER: " ", //分隔符
        JSON_TAG_LEFT: '\uFFFE', // 用于标识json对象字符串的等宽字符
        JSON_TAG_RIGHT: '\uFEFF',
        _record: function(logLevel) {
            var log = {
                "key": KEY,
                "level": logLevel, //日志级别
                "time": new Date().getTime() //日志时间,时间戳
                // "url"  : window.location.href //记录日志的URL
            },
            content = ""; //日志内容

            for (var i = 1; i < arguments.length; i++) {
                if (Array.isArray(arguments[i])) {
                    content += (i === 1 ? "" : FConsole.DELIMITER) + FConsole.JSON_TAG_LEFT + "[" + arguments[i] + "]" + FConsole.JSON_TAG_RIGHT;
                } else if (typeof arguments[i] === "object") {
                    content += (i === 1 ? "" : FConsole.DELIMITER) + FConsole.JSON_TAG_LEFT + JSON.stringify(arguments[i]) + FConsole.JSON_TAG_RIGHT;
                } else {
                    content += (i === 1 ? "" : FConsole.DELIMITER) + arguments[i];
                }
            }
            log["content"] = content;

            //日志记录加入队列
            queue.add(log)
        },
        debug: function() {
            Array.prototype.unshift.call(arguments, LOG_LEVELS[0]);
            FConsole._record.apply(FConsole, arguments);
        },
        log: function() {
            Array.prototype.unshift.call(arguments, LOG_LEVELS[1]);
            FConsole._record.apply(FConsole, arguments);
        },
        info: function() {
            Array.prototype.unshift.call(arguments, LOG_LEVELS[2]);
            FConsole._record.apply(FConsole, arguments);
        },
        warn: function() {
            Array.prototype.unshift.call(arguments, LOG_LEVELS[3]);
            FConsole._record.apply(FConsole, arguments);
        },
        error: function() {
            Array.prototype.unshift.call(arguments, LOG_LEVELS[4]);
            FConsole._record.apply(FConsole, arguments);
        }
    },

扫描二维码关注公众号,回复: 1252434 查看本文章

    /**
     * 全局定时器,监听队列
     * @type {{timeout: null, start: Function, clear: Function}}
     */
    clock = {
        timeout: null,
        start: function() {
            var self = this;
            if (!this.timeout) this.timeout = setInterval(function() {
                if (queue._queueArr.length > 0) {
                    queue._post(queue._queueArr.splice(0, queue._queueArr.length));
                }
            }, TIMER);
        },
        clear: function() {
            clearTimeout(this.timeout);
            this.timeout = null;
        }
    };


    function _extendObj(obj) {
        if (typeof obj !== 'object') return obj;
        var source, prop;
        for (var i = 1, length = arguments.length; i < length; i++) {
            source = arguments[i];
            for (prop in source) {
                if (Object.prototype.hasOwnProperty.call(source, prop)) {
                    // 不覆盖原方法执行,只是加个壳
                    (function(obj, prop) {
                        if (typeof obj[prop] === "function") {
                            var oldFun = obj[prop].bind(obj);
                            obj[prop] = function() {
                                source[prop].apply(source, arguments);
                                // oldFun.apply(obj, arguments);
                                oldFun(arguments[0]);
                            };
                        } else {
                            obj[prop] = source[prop];
                        }
                    })(obj, prop);
                }
            }
        }
        return obj;
    };
    //将自定义的日志API覆盖到原生console中
   // _extendObj(window.console, FConsole);

})(window);

猜你喜欢

转载自my.oschina.net/u/3449950/blog/1618455