为 Taro 应用添加自定义 Logger

293 阅读2分钟

为什么需要自定义 Logger ?

也许会好奇,console.log 不是挺好用的吗,为什么要花精力去自定义 Logger 呢?其实思想跟统一路由是一个道理的,通过自定义Logger,我们可以更好地管理应用中的所有打印,比如统一打印内容的格式,统一打印信息的级别等,甚至如果后期需要做类似后端的 logger 记录也是可以轻松做到的。

那应该怎么实现自定义 Logger 呢?

其实就很简单的方法,通过对 console.log 包装一层函数,然后让外界使用包装过的函数间接调用 console.log 就可以了,这里我列出了我常用的方案给大家参考:

src/hooks/useAppLoggerHook.ts

import { appDebugLogger, appErrorLogger, appInfoLogger, appWarnLogger } from '@/utils/logger'
import { useRef } from 'react'

/** 应用自定义 logger hook */
export const useAppLoggerHook = (module: string) => {
  const moduleNameRef = useRef(module)

  const debugLogger = (msg: Parameters<typeof appInfoLogger>[1], msgObj?: Parameters<typeof appInfoLogger>[2]) => {
    appDebugLogger(moduleNameRef.current, msg, msgObj)
  }
  const infoLogger = (msg: Parameters<typeof appInfoLogger>[1], msgObj?: Parameters<typeof appInfoLogger>[2]) => {
    appInfoLogger(moduleNameRef.current, msg, msgObj)
  }
  const warnLogger = (msg: Parameters<typeof appInfoLogger>[1], msgObj?: Parameters<typeof appInfoLogger>[2]) => {
    appWarnLogger(moduleNameRef.current, msg, msgObj)
  }
  const errorLogger = (msg: Parameters<typeof appInfoLogger>[1], msgObj?: Parameters<typeof appInfoLogger>[2]) => {
    appErrorLogger(moduleNameRef.current, msg, msgObj)
  }

  return {
    debugLogger,
    infoLogger,
    warnLogger,
    errorLogger,
  }
}

src/utils/logger/index.ts

const isProd = process.env.APP_ENV === 'PROD'

const colorHash = {
  error: '#E0282E',
  warn: '#F2BD27',
  ready: '#00B96B',
  info: '#1677FF',
  debug: '#626262',
}

function handleLogWithStyle(_module: string, type: keyof typeof colorHash, msg: string, msgObj: any) {
  if (isProd) {
    return
  }
  // console.log('colorHash[type]', colorHash[type])
  if (msg && msgObj) {
    console.log(
      `%c${_module} ${type}::%c${msg}`,
      `padding: 2px 5px; border-radius: 3px 0 0 3px; color: #fff; background: ${colorHash[type]}; font-weight: bold;`,
      `padding: 2px 5px; border-radius: 0 3px 3px 0; color: ${colorHash[type]}; background: #fff; font-weight: bold;`,
      msgObj
    )
  } else if (msg) {
    console.log(
      `%c${_module} ${type}::%c${msg}`,
      `padding: 2px 5px; border-radius: 3px 0 0 3px; color: #fff; background: ${colorHash[type]}; font-weight: bold;`,
      `padding: 2px 5px; border-radius: 0 3px 3px 0; color: ${colorHash[type]}; background: #fff; font-weight: bold;`
    )
  } else if (msgObj) {
    console.log(
      `%c${_module} ${type}::%c${msg}`,
      `padding: 2px 5px; border-radius: 3px; color: #fff; background: ${colorHash[type]}; font-weight: bold;`,
      `padding: 2px 5px; border-radius: 0 3px 3px 0; color: ${colorHash[type]}; background: #fff; font-weight: bold;`,
      msgObj
    )
  }
}

export const appDebugLogger = (_module: string, msg?: string, msgObj?: any) => {
  handleLogWithStyle(_module, 'debug', msg || '', msgObj || undefined)
}
export const appInfoLogger = (_module: string, msg?: string, msgObj?: any) => {
  handleLogWithStyle(_module, 'info', msg || '', msgObj || undefined)
}
export const appWarnLogger = (_module: string, msg?: string, msgObj?: any) => {
  handleLogWithStyle(_module, 'warn', msg || '', msgObj || undefined)
}
export const appErrorLogger = (_module: string, msg?: string, msgObj?: any) => {
  handleLogWithStyle(_module, 'error', msg || '', msgObj || undefined)
}

使用方法:src/pages/index/index.tsx

const {
	infoLogger,
} = useAppLoggerHook('Home Page')

infoLogger('This is example info logger')
warnLogger('This is example warn logger')
errorLogger('This is example error logger')

最终打印的效果: image.png

在 utils 下的 logger.ts 文件中有 appDebugLogger、appInfoLogger、appWarnLogger、appErrorLogger 这四个代理 console.log 函数,其实也是简单地对平时使用 console.log 的场景做了分类,如果后续有需要对应用中的打印信息上传后日志服务器(比如说微信小程序的日志),方便后续查询,也是可以在这几个代理函数里实现逻辑的。此外因为这几个函数又是统一调用了 handleLogWithStyle 函数,所以也可以在 handleLogWithStyle 函数中实现打印(日志上传)开关功能的。

希望对大家有帮助~