CocosCreator2.x Log工具

前言

CocosCreator项目中总会遇到一些问题,有时候就需要一个比较好用的Log工具来记录,遇到问题时把这些Log发到服务器或者复制到哪里,可以比较方便的分析问题。

使用方法

设置Log等级

//设置打印的log等级
Logger.SetLevel(LogLv.DEBUG);

打印Log

//打印log,带脚本名称
Logger.debug('游戏开始','GameManager')
//打印log
Logger.debug('游戏开始')

Log追踪

debug方法中的注释打开即可

//下面两行打开
let stackFunc = (new Error).stack.split("\n")[2].split(" ")[5];
let logMsg = tag == "" ? "[DEBUG] " + msg + " at " + stackFunc : "[DEBUG] [" + tag + "] " + msg;
//将这一句注释
//let logMsg = tag == "" ? "[DEBUG] " + msg : "[DEBUG] [" + tag + "] " + msg;

复制到剪贴板

Logger.PrintLog();

源码

在项目中创建一个LogUtil.ts,将以下内容复制到里面。

/**
 * 日志等级枚举
 */
export enum LogLv {
    DEBUG = 0,
    INFO,
    WARN,
    ERROR
}
/**
 * 日志信息
 *
 * @export
 * @class LogInfo
 */
export class LogInfo {
    level: number;
    msg: string;
    time: string;
}

/**
 * 日志
 *
 * @export
 * @class Logger
 */
export default class Logger {
    /**
     * 最大记录条数
     *
     * @private
     * @static
     * @type {number}
     * @memberof Logger
     */
    private static MAX_LEN: number = 100000;

    /**
     *
     * 当log满了之后删掉几个
     * @private
     * @static
     * @type {number}
     * @memberof Logger
     */
    private static CLEAR_COUNT: number = 1;

    /**
     * log等级
     * 
     * @public
     * @static
     * @type {number}
     * @memberof Logger
     */
    private static level: number = 0;

    /**
     * log列表
     *
     * @private
     * @static
     * @type {Array<LogInfo>}
     * @memberof Logger
     */
    private static logs: Array<LogInfo> = [];

    /**
     * 设置Log记录等级
     *
     * @static
     * @param {LogLv} level
     * @memberof Logger
     */
    public static SetLevel(level: LogLv): void {
        this.level = Number(level);
    }
    /**
     * 收集、打印调试等级的日志
     * Logger.debug("log");
     * @static
     * @param {string} msg
     * @param {string} [tag="default"]
     * @return {*}  {void}
     * @memberof Logger
     */
    public static debug(msg: string, tag: string = "",): void {
        if (Logger.level > LogLv.DEBUG) {
            return;
        }
        //测试功能 自动寻找方法
        // let stackFunc = (new Error).stack.split("\n")[2].split(" ")[5];
        // let logMsg = tag == "" ? "[DEBUG] " + msg + " at " + stackFunc : "[DEBUG] [" + tag + "] " + msg;
        let logMsg = tag == "" ? "[DEBUG] " + msg : "[DEBUG] [" + tag + "] " + msg;
        Logger._addLog(LogLv.DEBUG, logMsg);
        console.log(logMsg);
    }

    public static info(msg: string, tag: string = "",): void {
        if (Logger.level > LogLv.INFO) {
            return;
        }
        let logMsg = tag == "" ? "[INFO] " + msg : "[INFO] [" + tag + "] " + msg;
        Logger._addLog(LogLv.INFO, logMsg);
        console.info(logMsg);
    }

    public static warn(msg: string, tag: string = "",): void {
        if (Logger.level > LogLv.WARN) {
            return;
        }
        let logMsg = tag == "" ? "[WARN] " + msg : "[WARN] [" + tag + "] " + msg;
        Logger._addLog(LogLv.WARN, logMsg);
        console.warn(logMsg);
    }

    public static error(msg: string, tag: string = "",): void {
        if (Logger.level > LogLv.ERROR) {
            return;
        }
        let logMsg = tag == "" ? "[ERROR] " + msg : "[ERROR] [" + tag + "] " + msg;
        Logger._addLog(LogLv.ERROR, logMsg);
        console.error(logMsg);
    }

    /**
     * 添加缓存日志
     *
     * @private
     * @static
     * @param {LogLv} level
     * @param {string} logMsg
     * @memberof Logger
     */
    private static _addLog(level: LogLv, logMsg: string): void {
        if (Logger.logs.length >= Logger.MAX_LEN) {
            Logger.logs.splice(0, Logger.CLEAR_COUNT);
        }
        Logger.logs.push({
            level: level,
            msg: logMsg,
            time: this.FormatDate(Date.now(), "yyyy-MM-dd HH:mm:ss")
        });
    }

    /**
     * 输出所有Log
     *
     * @static
     * @memberof Logger
     */
    public static PrintLog() {
        //线上环境这个dir会有问题,所以换成for循环
        //console.dir(Logger.logs);
        let logStr = new String("");
        for (let i = 0; i < Logger.logs.length; i++) {
            const element = Logger.logs[i];
            logStr += element.time + " " + element.msg + "\n";
        }
        cc.sys.localStorage.setItem("log", logStr);
        // console.log(logStr);
        // 存储到剪贴板
        // console.log("当前平台是:" + cc.sys.platform);
        if (cc.sys.platform == cc.sys.WECHAT_GAME) {

            wx.setClipboardData({
                data: logStr.toString(), //复制内容
                success: function (res) {
                    // wx.getClipboardData({
                    //     success: function(res) {
                    //         console.log("复制成功:", res.data);
                    //         return true;
                    //     }
                    // });
                    Logger.debug("success复制成功:");
                    // return true;
                }
            });
        } else {
            this.CopyTextEvent(logStr.toString());
        }


        // wx.setClipboardData(Object object)
    }
    // 拷贝文本
    public static CopyTextEvent(copyStr: string) {
        const el = document.createElement('textarea');
        el.value = copyStr;

        // Prevent keyboard from showing on mobile
        el.setAttribute('readonly', '');
        //el.style.contain = 'strict';
        el.style.position = 'absolute';
        el.style.left = '-9999px';
        el.style.fontSize = '12pt'; // Prevent zooming on iOS

        const selection = getSelection()!;
        let originalRange;
        if (selection.rangeCount > 0) {
            originalRange = selection.getRangeAt(0);
        }

        document.body.appendChild(el);
        el.select();

        // Explicit selection workaround for iOS
        el.selectionStart = 0;
        el.selectionEnd = copyStr.length;

        let success = false;
        try {
            success = document.execCommand('copy');
        } catch (err) { }

        document.body.removeChild(el);

        if (originalRange) {
            selection.removeAllRanges();
            selection.addRange(originalRange);
        }
    }
    /**
     * 格式化时间
     * 调用 FormatDate(strDate, "yyyy-MM-dd HH:mm:ss")
     * @param strDate (中国标准时间)时间戳等
     * @param strFormat 返回格式
     * @returns
     */
    public static FormatDate(strDate: any, strFormat?: any) {
        if (!strDate) return;
        if (!strFormat) strFormat = "yyyy-MM-dd";
        switch (typeof strDate) {
            case "string":
                strDate = new Date(strDate.replace(/-/g, "/"));
                break;
            case "number":
                strDate = new Date(strDate);
                break;
        }
        if (strDate instanceof Date) {
            const dict: any = {
                yyyy: strDate.getFullYear(),
                M: strDate.getMonth() + 1,
                d: strDate.getDate(),
                H: strDate.getHours(),
                m: strDate.getMinutes(),
                s: strDate.getSeconds(),
                MM: ("" + (strDate.getMonth() + 101)).substr(1),
                dd: ("" + (strDate.getDate() + 100)).substr(1),
                HH: ("" + (strDate.getHours() + 100)).substr(1),
                mm: ("" + (strDate.getMinutes() + 100)).substr(1),
                ss: ("" + (strDate.getSeconds() + 100)).substr(1)
            };
            return strFormat.replace(/(yyyy|MM?|dd?|HH?|ss?|mm?)/g, function () {
                return dict[arguments[0]];
            });
        }
    }

    /**
     * eLog - displays calling line number & message & dumps vars as pretty json string
     * @param {string} msg - string to display in log message
     * @param {any} dispVars - any number of variables (ellipsis , aka Rest parameters) to dump
     * {@link https://github.com/evanw/node-source-map-support usable by typescript node-source-map-support module}
     * {@link https://github.com/mozilla/source-map/ Mozilla source-map library & project}
     * {@link http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/ good introduction to sourcemaps}
    */
    private static eLog(msg: string, ...dispVars: any[]) {
        //console.dir((new Error).stack);
        /**
         * go one line back for the caller
         * @type {string}
         */
        let stackLine = (new Error).stack.split("\n")[2];
        console.dir(stackLine);
        let stackLineSelect = stackLine.split(" ");
        for (let i = 0; i < stackLineSelect.length; i++) {
            const element = stackLineSelect[i];
            Logger.debug("---" + element)
        }
        let selectFunction = stackLineSelect[5];
        Logger.debug("触发方法为" + selectFunction);
        /**
         * retrieve the file basename & positional data, after the last `/` to the `)` 
         */
        // 
        let caller_line = stackLine.slice(stackLine.lastIndexOf('/'), stackLine.lastIndexOf(')'))
        console.dir(caller_line);

        /**
         *  test for no `/` ; if there is no `/` then use filename without a prefixed path
         */
        // if (caller_line.length == 0) {
        //     caller_line = stackLine.slice(stackLine.lastIndexOf('('), stackLine.lastIndexOf(')'))
        // }
        // 
        /**
         * filename_base - parse out the file basename; remove first `/` char and go to `:`
         */
        //let filename_base = caller_line.slice(0 + 1, caller_line.indexOf(':'));
        /**
         * line_no - parse out the line number ; remove first `:` char and go to 2nd `:`
         */
        //let line_no = caller_line.slice(caller_line.indexOf(':') + 1, caller_line.lastIndexOf(':'));
        /**
         * line_pos - line positional - from the last `:` to the end of the string
         */
        //let line_pos = caller_line.slice(caller_line.lastIndexOf(':') + 1);
        //Logger.debug(`eLog called by ${filename_base} on line# ${line_no} @ char# ${line_pos} said:\n${msg}`);
        // print out the input variables as pretty JSON strings
        // dispVars.forEach(value => {
        //     Logger.debug(JSON.stringify(value, null, 2));
        // });
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值