更多内容请访问:与华为官方共建的鸿蒙技术社区https://harmonyos.51cto.com目录指南Logger源码解析知识点移植到鸿蒙思维导读本文基于https://gitee.com/openharmony-tpc/logger,分析Logger的源码以及移植到Harmony需要做的工作。在Android到鸿蒙系列:Timber中,我已经提到我喜欢把Logger和Timber一起使用。原因很简单,因为Timber的界面简洁,而Logger的输出风格漂亮。常规套路:FormatStrategyformatStrategy=PrettyFormatStrategy.newBuilder().tag("DwGG")//(Optional)Globaltagforeverylog.DefaultPRETTY_LOGGER.build();Logger.addLogAdapter(newAndroidLogAdapter(formatStrategy));Timber.plant(newTimber.DebugTree(){@Overrideprotectedvoidlog(intpriority,Stringtag,Stringmessage,Throwablet){Logger.log(priority,tag,message,t);}});Logger源码分析Timber只有一个文件,600多行代码,Logger相对复杂,但结构也很简单,阅读源码很容易。与Timber一样,Logger具有出色的可扩展性。Timber有一个内置的DebugTree(在控制台输出日志)。Logger内置了AndroidLogAdapter(控制台输出)和DiskLogAdapter(输出日志到本地磁盘)。先看图,有个整体的认识:解释上图:1.Logger也是使用delegate模式。操作全部委托给Printerprinter2。Printer是日志能力的抽象(即定义了日志工具的api),类似于Timber中的Tree。定义的API有:日志相关API:v()、d()、i()、e()、wtf()和xml()、json()支持xml和json数据格式。设置临时标签:t()LogAdapter相关api:addAdapter(LogAdapteradapter),clearLogAdapters()Printer的默认实现是LoggerPrinter,我们可以自定义自己的实现。但是,在大多数情况下似乎没有必要。3、与Timber相比,Logger进一步抽象了Timber中的Tree。使用LogAdapter适配不同的日志能力,比如Android控制台输出(AndroidLogAdapter),保存到磁盘(DiskLogAdapter)。从类名我们也可以看出使用了适配器(apapter)模式。当然,我们也可以定义鸿蒙HiLog控制台输出的LogAdapter(取个名字:HarmonyLogAdapter)。4.FormatStrategy格式化原始数据,决定LogAdapter输出日志样式。AndroidLogAdapter中默认实现是PrettyFormatStrategy(可以显示线程信息,统一tag:“PRETTY_LOGGER”,线程栈);DiskLogAdapter中的默认实现是CsvFormatStrategy(csv文件格式);5、LogStrategy最终确定FormatStrategy输出日志的目标(如:控制台LogcatLogStrategy、磁盘DiskLogStrategy)更详细的分析请移步:Android日志系统第三方库------Logger源码分析知识点1.临时标签的实现方法很简单,Logger.t("临时标签").d(xxx);设置一个临时标签。使用一次并移除。最后也是委托给Printer执行。为了性能,LoggerPrinter和Timber一样,也使用ThreadLocal以空间换取时间。2、在多线程支持方面,只锁定了LoggerPrinter的synchronizedvoidlog()。在我看来,LoggerPrinter的addAdapter(LogAdapteradapter)和clearLogAdapters()都应该被锁定。因为log()方法是加锁的,所以要保证这个方法的执行效率。否则,如果一个线程写日志的时间过长,会影响其他线程的执行。3、接上一个,DiskLogStrategy在写文件时是在一个独立的HandlerThread线程中执行的,可以保证LoggerPrinter的voidlog()方法的执行时间。移植到鸿蒙通过上面的分析,我们可以知道移植到鸿蒙需要做的工作如下:1、实现HarmonyLogAdapter提供控制台输出的能力,其中PrettyFormatStrategy基本可以复用,只需要修改LogcatLogStrategy的实现和将android.util替换为HiLog.Log相关操作。publicPrettyFormatStrategybuild(){if(logStrategy==null){logStrategy=newLogcatLogStrategy();}returnnewPrettyFormatStrategy(this);}2.修改DiskLogAdapter以提供将日志输出到文件的能力。其中CsvFormatStrategy基本可以复用,只要修改日志文件路径和Handler相关类的设置即可。StringdiskPath=Environment.getExternalStorageDirectory().getAbsolutePath();Stringfolder=diskPath+File.separatorChar+"logger";HandlerThreadht=newHandlerThread("AndroidFileLogger."+folder);ht.start();Handlerhandler=newDiskLogStrategy.WriteHandler(ht.getLooper(),文件夹,MAX_BYTES);修改为:Stringfolder="/storage/emulated/0/"+File.separatorChar+"logger";StringnewThreadName="FileLogger"+folder;EventRunnerht=EventRunner.create(newThreadName);EventHandlerhandler=newDiskLogStrategy.WriteHandler(ht,folder,MAX_BYTES);同样,DiskLogStrategy中的Handler也应该改为EventHandler。将上图视为最终效果。从代码中可以看出,HiLogLabel是固定的,所以domain和tag都是固定的。为了达到自定义标签的目的,将自定义标签输出到消息中,所以我们可以看到两个“PRETTY_LOGGER”,从视觉上看还不够完美。publicclassLogcatLogStrategyimplementsLogStrategy{staticfinalStringDEFAULT_TAG="NO_TAG";staticfinalStringTAG_LOG="[PRETTY_LOGGER]";staticfinalintDOMAIN_ID=0xD000F00;staticfinalHiLogLabelLABEL_LOG=newHiLogLabel(3,DOMAIN_ID,TAG_LOGSTimberLOG);}优化方法可参考Harmontoyos.com,更多信息请访问51,与华为官方合作搭建的鸿蒙技术社区
