课程名称:移动端架构师
课程章节:HiLog库架构设计与开发
课程讲师:CrazyCodeBoy LovelyChubby
课程内容:
架构易用高扩展的日志组件HiLog
日志组件是一款中大型APP所不可或缺的一部分,好的一款日志组件不仅能够起到收集日志的作用,更能够实现日志操作的多样化。
例如:日志的保存,日志的可视化,对象打印,日志的在线收集,线上问题定位的辅助
HiLog库疑难点分析与架构设计
需求分析
能够打印对照信息
支持任何数据类型的打印
支持实现日志可视化
能够实现文件打印模块
支持不同打印器的插拔
日志经历的几个过程
技术点分析
| 日志收集 | 日志加工 | 日志打印 |
|---|---|---|
| 面向接口编程 | 堆栈信息相关技术 | 文件IO技术(文件打印) |
| 设计模式 | 序列化 | 多线程技术(线程复用、线程同步) |
| 解耦设计 | 日志格式化 | UI以及列表相关技术 |
疑难点分析
堆栈信息获取
打印器插拔设计
线程复用防止频繁的创建线程
线程同步
架构设计
HiLogFormatter.java
org.devio.hi.library.logHiLogFormatter<> {
String (data)}HiStackTraceFormatter.java
org.devio.hi.library.logHiStackTraceFormatter HiLogFormatter<StackTraceElement[]> {
String (StackTraceElement[] stackTrace) {
StringBuilder sb = StringBuilder()(stackTrace == || stackTrace.== ) {
} (stackTrace.== ) {
+ stackTrace[].toString()} {
(i = len = stackTrace.i < leni++) {
(i == ) {
sb.append()}
(i != len - ) {
sb.append()sb.append(stackTrace[i].toString())sb.append()} {
sb.append()sb.append(stackTrace[i].toString())}
}
sb.toString()}
}
}HiThreadFormatter.java
org.devio.hi.library.logHiThreadFormatter HiLogFormatter<Thread> {
String (Thread data) {
+ data.getName()}
}HiLogPrinter.java
org.devio.hi.library.logandroidx.annotation.HiLogPrinter {
(HiLogConfig configlevelString tagString printString)}HiConsolePrinter.java
org.devio.hi.library.logandroid.util.Logandroidx.annotation.org.devio.hi.library.log.HiLogConfig.HiConsolePrinter HiLogPrinter {
(HiLogConfig configlevelString tagString printString) {
len = printString.length()countOfSub = len / (countOfSub > ) {index = (i = i < countOfSubi++) {Log.(leveltagprintString.substring(indexindex + ))index += }
(index != len) {Log.(leveltagprintString.substring(indexlen))}} {
Log.(leveltagprintString)}
}
}HiFilePrinter.java
org.devio.hi.library.logandroidx.annotation.java.io.BufferedWriterjava.io.Filejava.io.FileWriterjava.io.IOExceptionjava.text.SimpleDateFormatjava.util.Datejava.util.Localejava.util.TimeZonejava.util.concurrent.BlockingQueuejava.util.concurrent.ExecutorServicejava.util.concurrent.Executorsjava.util.concurrent.LinkedBlockingQueueHiFilePrinter HiLogPrinter {
ExecutorService = Executors.()String LogWriter PrintWorker HiFilePrinter HiFilePrinter (String logPathretentionTime) {
(== ) {
= HiFilePrinter(logPathretentionTime)}
}
(String logPathretentionTime) {
.= logPath.= retentionTime.= LogWriter().= PrintWorker()cleanExpiredLog()}
(HiLogConfig configlevelString tagString printString) {
timeMillis = System.()(!.isRunning()) {
.start()}
.put(HiLogMo(timeMillisleveltagprintString))}
(HiLogMo logMo) {
String lastFileName = .getPreFileName()(lastFileName == ) {
String newFileName = genFileName()(.isReady()) {
.close()}
(!.ready(newFileName)) {
}
}
.append(logMo.flattenedLog())}
String () {
SimpleDateFormat sdf = SimpleDateFormat(Locale.)sdf.setTimeZone(TimeZone.())sdf.format(Date(System.()))}
() {
(<= ) {
}
currentTimeMillis = System.()File logDir = File()File[] files = logDir.listFiles()(files == ) {
}
(File file : files) {
(currentTimeMillis - file.lastModified() > ) {
file.delete()}
}
}
PrintWorker Runnable {
BlockingQueue<HiLogMo> = LinkedBlockingQueue<>()(HiLogMo log) {
{
.put(log)} (InterruptedException e) {
e.printStackTrace()}
}
() {
() {
}
}
() {
() {
.execute()= }
}
() {
HiLogMo log{
() {
log = .take()doPrint(log)}
} (InterruptedException e) {
e.printStackTrace()() {
= }
}
}
}
LogWriter {
String File BufferedWriter () {
!= }
String () {
}
(String newFileName) {
= newFileName= File(newFileName)(!.exists()) {
{
File parent = .getParentFile()(!parent.exists()) {
parent.mkdirs()}
.createNewFile()} (IOException e) {
e.printStackTrace()= = }
}
{
= BufferedWriter(FileWriter())} (Exception e) {
e.printStackTrace()= = }
}
() {
(!= ) {
{
.close()} (IOException e) {
e.printStackTrace()} {
= = = }
}
}
(String flattenedLog) {
{
.write(flattenedLog).newLine().flush()} (IOException e) {
e.printStackTrace()}
}
}
}HiViewPrinter.java
org.devio.hi.library.logandroid.app.Activityandroid.view.LayoutInflaterandroid.view.Viewandroid.view.ViewGroupandroid.widget.FrameLayoutandroid.widget.TextViewandroidx.annotation.androidx.recyclerview.widget.LinearLayoutManagerandroidx.recyclerview.widget.RecyclerVieworg.devio.hi.library.Rjava.util.ArrayListjava.util.ListHiViewPrinter HiLogPrinter {
RecyclerView LogAdapter HiViewPrinterProvider (Activity activity) {
FrameLayout rootView = activity.findViewById(android.R.id.)= RecyclerView(activity)= LogAdapter(LayoutInflater.(.getContext()))LinearLayoutManager layoutManager = LinearLayoutManager(.getContext()).setLayoutManager(layoutManager).setAdapter()= HiViewPrinterProvider(rootView)}
HiViewPrinterProvider () {
}
(HiLogConfig configlevelString tagString printString) {
.addItem(HiLogMo(System.()leveltagprintString)).smoothScrollToPosition(.getItemCount() - )}
LogAdapter RecyclerView.Adapter<LogViewHolder> {
LayoutInflater List<HiLogMo> = ArrayList<>()(LayoutInflater inflater) {
.= inflater}
(HiLogMo logItem) {
.add(logItem)notifyItemInserted(.size() - )}
LogViewHolder (ViewGroup parentviewType) {
View itemView = .inflate(R.layout.parent)LogViewHolder(itemView)}
(LogViewHolder holderposition) {
HiLogMo logItem = .get(position)color = getHighlightColor(logItem.)holder..setTextColor(color)holder..setTextColor(color)holder..setText(logItem.getFlattened())holder..setText(logItem.)}
(logLevel) {
highlight(logLevel) {
HiLogType.:
highlight = HiLogType.:
highlight = HiLogType.:
highlight = HiLogType.:
highlight = HiLogType.:
highlight = :
highlight = }
highlight}
() {
.size()}
}
LogViewHolder RecyclerView.ViewHolder {
TextView TextView (View itemView) {
(itemView)= itemView.findViewById(R.id.)= itemView.findViewById(R.id.)}
}
}HiLogConfig.java
org.devio.hi.library.logHiLogConfig {
= HiThreadFormatter = HiThreadFormatter()HiStackTraceFormatter = HiStackTraceFormatter()JsonParser () {
}
String () {
}
() {
}
() {
}
() {
}
HiLogPrinter[] () {
}
JsonParser {
String (Object src)}
}HiLog.java
org.devio.hi.library.logandroidx.annotation.java.util.Arraysjava.util.ListHiLog {
String {
String className = HiLog..getName()= className.substring(className.lastIndexOf() + )}
(Object... contents) {
(HiLogType.contents)}
(String tagObject... contents) {
(HiLogType.tagcontents)}
(Object... contents) {
(HiLogType.contents)}
(String tagObject... contents) {
(HiLogType.tagcontents)}
(Object... contents) {
(HiLogType.contents)}
(String tagObject... contents) {
(HiLogType.tagcontents)}
(Object... contents) {
(HiLogType.contents)}
(String tagObject... contents) {
(HiLogType.tagcontents)}
(Object... contents) {
(HiLogType.contents)}
(String tagObject... contents) {
(HiLogType.tagcontents)}
(Object... contents) {
(HiLogType.contents)}
(String tagObject... contents) {
(HiLogType.tagcontents)}
(typeObject... contents) {
(typeHiLogManager.().getConfig().getGlobalTag()contents)}
(typeString tagObject... contents) {
(HiLogManager.().getConfig()typetagcontents)}
(HiLogConfig configtypeString tagObject... contents) {
(!config.enable()) {
}
StringBuilder sb = StringBuilder()(config.includeThread()) {
String threadInfo = HiLogConfig..format(Thread.())sb.append(threadInfo).append()}
(config.stackTraceDepth() > ) {
String stackTrace = HiLogConfig..format(
HiStackTraceUtil.(Throwable().getStackTrace()config.stackTraceDepth()))sb.append(stackTrace).append()}
String body = (contentsconfig)(body != ) {body = body.replace()}
sb.append(body)List<HiLogPrinter> printers =
config.printers() != ? Arrays.(config.printers()) : HiLogManager.().getPrinters()(printers == ) {
}
(HiLogPrinter printer : printers) {
printer.print(configtypetagsb.toString())}
}
String (Object[] contentsHiLogConfig config) {
(config.injectJsonParser() != ) {
(contents.== && contents[] String) {
(String) contents[]}
config.injectJsonParser().toJson(contents)}
StringBuilder sb = StringBuilder()(Object o : contents) {
sb.append(o.toString()).append()}
(sb.length() > ) {
sb.deleteCharAt(sb.length() - )}
sb.toString()}
}HiLogManager.java
org.devio.hi.library.logandroidx.annotation.java.util.ArrayListjava.util.Arraysjava.util.ListHiLogManager {
HiLogConfig HiLogManager List<HiLogPrinter> = ArrayList<>()(HiLogConfig configHiLogPrinter[] printers) {
.= config..addAll(Arrays.(printers))}
HiLogManager () {
}
(HiLogConfig configHiLogPrinter... printers) {
= HiLogManager(configprinters)}
HiLogConfig () {
}
List<HiLogPrinter> () {
}
(HiLogPrinter printer) {
.add(printer)}
(HiLogPrinter printer) {
(!= ) {
.remove(printer)}
}
}HiLogType.java
org.devio.hi.library.logandroid.util.Logandroidx.annotation.java.lang.annotation.java.lang.annotation.RetentionPolicyHiLogType {
({})
(RetentionPolicy.)
@{
}
= Log.= Log.= Log.= Log.= Log.= Log.}HiStackTraceUtil.java
org.devio.hi.library.logHiStackTraceUtil {
StackTraceElement[] (StackTraceElement[] stackTraceString ignorePackagemaxDepth) {
((stackTraceignorePackage)maxDepth)}
StackTraceElement[] (StackTraceElement[] stackTraceString ignorePackage) {
ignoreDepth = allDepth = stackTrace.String className(i = allDepth - i >= i--) {
className = stackTrace[i].getClassName()(ignorePackage != && className.startsWith(ignorePackage)) {
ignoreDepth = i + }
}
realDepth = allDepth - ignoreDepthStackTraceElement[] realStack = StackTraceElement[realDepth]System.(stackTraceignoreDepthrealStackrealDepth)realStack}
StackTraceElement[] (StackTraceElement[] callStackmaxDepth) {
realDepth = callStack.(maxDepth > ) {
realDepth = Math.(maxDepthrealDepth)}
StackTraceElement[] realStack = StackTraceElement[realDepth]System.(callStackrealStackrealDepth)realStack}
}HiViewPrinterProvider.java
org.devio.hi.library.logandroid.graphics.Colorandroid.view.Gravityandroid.view.Viewandroid.view.ViewGroupandroid.widget.FrameLayoutandroid.widget.TextViewandroidx.recyclerview.widget.RecyclerVieworg.devio.hi.library.util.HiDisplayUtilHiViewPrinterProvider {
FrameLayout View FrameLayout RecyclerView (FrameLayout rootViewRecyclerView recyclerView) {
.= rootView.= recyclerView}
String = String = () {
(.findViewWithTag() != ) {
}
FrameLayout.LayoutParams params =
FrameLayout.LayoutParams(ViewGroup.LayoutParams.ViewGroup.LayoutParams.)params.= Gravity.| Gravity.View floatingView = genFloatingView()floatingView.setTag()floatingView.setBackgroundColor(Color.)floatingView.setAlpha()params.= HiDisplayUtil.(.getResources()).addView(genFloatingView()params)}
() {
(.findViewWithTag() != ) {
}
FrameLayout.LayoutParams params =
FrameLayout.LayoutParams(ViewGroup.LayoutParams.HiDisplayUtil.(.getResources()))params.= Gravity.View logView = genLogView()logView.setTag().addView(genLogView()params)= }
() {
= .removeView(genLogView())}
() {
.removeView(genFloatingView())}
View () {
(!= ) {
}
TextView textView = TextView(.getContext())textView.setOnClickListener(View.OnClickListener() {
(View v) {
(!) {
showLogView()}
}
})textView.setText()= textView}
View () {
(!= ) {
}
FrameLayout logView = FrameLayout(.getContext())logView.setBackgroundColor(Color.)logView.addView()FrameLayout.LayoutParams params =
FrameLayout.LayoutParams(ViewGroup.LayoutParams.ViewGroup.LayoutParams.)params.= Gravity.TextView closeView = TextView(.getContext())closeView.setOnClickListener(View.OnClickListener() {
(View v) {
closeLogView()}
})closeView.setText()logView.addView(closeViewparams).= logView}
}HiLogMo.java
org.devio.hi.library.logjava.text.SimpleDateFormatjava.util.LocaleHiLogMo {
SimpleDateFormat = SimpleDateFormat(Locale.)String String (timeMillislevelString tagString log) {
.= timeMillis.= level.= tag.= log}
String () {
getFlattened() + + }
String () {
format() + + + + + }
String (timeMillis) {
.format(timeMillis)}
}HiLog日志框架的初始化
MApplication : Application() {
() {
.onCreate()
HiLogManager.init(
: HiLogConfig() {
(): JsonParser? {
JsonParser src JSONObject.toJSONString(src) }
(): String {
}
(): Boolean {
}
(): Boolean {
}
(): Int {
}
}HiConsolePrinter()HiFilePrinter.getInstance(..)
)
}
}HiLog日志框架的使用
HiLog.d("hilog")课程收获:
谢谢老师,讲的非常细致,很容易懂,期待后边的学习