最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

安全高效可视化的日志解决方案

IT圈 admin 33浏览 0评论

2023年12月11日发(作者:尉彦珺)

安全高效可视化的日志解决方案

背景

一条工单引发的日志需求

我们的业务收到了一个信息泄漏的工单,漏洞是明文打印日志。

我们当时使用的是某网络库自带的日志系统(以下简称 A 系统),会直接将明文写入到了日志文件当中,这样就有信息泄漏的风险。

我们搜集了当前使用 A 系统的痛点:

1. 明文打印,造成隐私泄漏;

2. 关键日志丢失;

3. 无法方便的打印当前的堆栈,线程等信息;

4. 不支持各种格式化输出。

为了解决这个问题,我们设计并实现了 TinyLog。

TinyLog 能支持日志的加密和压缩,减少日志文件大小并确保隐私不会泄漏;能够支持各种格式化输出,且比较方便的打印出当前的堆栈,

线程等信息;我们在设计的时候也考虑到了日志丢失的问题,在 crash 的场景,也能够确保当前的 crash 堆栈能够被记录下来;此外我们

还提供了图形化展示日志的接口,能够将日志图形化的展示出来,方便开发同学快速的定位到问题。

TinyLog 的总体设计作为一个日志组件,安全和高效是我们的一个核心需求。安全包括两点,日志不丢失以及隐私不泄漏;高效就是日志组件不能影响应用的性

能。我们在设计 TinyLog 的时候也充分考虑到了这两点,以下是 TinyLog 的总体设计图:

客户端加密,服务端解密。服务端提供明文下载以及图形化展示日志的功能。客户端来保证打印日志的高效性,服务端来保证安全性。

g SDK如何才能支持多种格式化输出,并能保持良好的性能呢?

以下是 TinyLog SDK 的结构图:

我们将 TinyLog SDK 分为三层,分别是输入层,处理层和输出层。其中处理层包含了很多日志的配置项,能够满足各种场景的格式化输

出;另外,在输出层,我们将加密,压缩以及文件写入的功能下沉到 c++,保证了良好的性能。

输入层:

输入层为对外提供的接口,主要提供了初始化方法以及日志打印的方法。我们参考了系统打印日志的接口,并在其基础上进行扩充,降低业

务方的接入成本。以下为 TinyLog 和系统日志打印的接口对比,以 info 等级为例:

系统原有的两个日志打印的接口,我们将其扩充为4个,并在其基础上进行了增强。如系统接口 i(String tag,String msg),第二个参数只

能是字符串对象,而我们将其增强为 i(String tag,T obj),第二个参数可以是任何对象,我们会匹配对应的格式化方法,将其进行格式化处

理。比如第二个参数是 json 对象,我们就会使用 JsonFormatter 将 json 对象进行格式化,若输入的对象在 TinyLog 内部未匹配到任何

Formatter ,则会直接调用该对象的 toString 方法。

处理层:

在这一层,日志会被分发给 Logger,每个 Logger 都包含一个 LogConfig(配置信息)和 Printer(输出), Logger 会根据

LogConfig 将日志封装成为一个日志对象,然后传递给 Printer 输出。LogConfig 的配置信息包括日志等级过滤,是否打印线程,是否打

印边框等,以及各种格式化方法。

我们将格式化抽象成了一个 Formatter 接口,并默认实现了各种场景的格式化方法,具体如下表格所示,业务方也可根据需要自己实现

Formatter 接口。

格式化

DefaultBorderFormatter

DefaultJsonArrayFormatter

DefaultJsonFormatter

DefaultStackTraceFormatter

DefaultThreadFormatter

DefaultThrowableFormatter

DefaultXmlFormatter

备注

边框格式化

Json数组格式化

Json对象格式化

堆栈格式化

线程格式化

异常信息格式化

xml格式化

输出层:

我们将输出抽象成了 Printer 接口,TinyLog 默认实现了 ConsolePrinter 和 FilePrinter,分别将日志输出到控制台和文件当中。若输出

到文件,则可以将日志上传到服务端。业务方也可以自定义 Printer,将日志输出到任何地方。

让日志的输出更加友好

TinyLog 能够很轻松的打印当前的线程信息,堆栈信息以及常见的对象,并默认实现了各种格式化方法,包括边框,json,线程,堆栈

等。

例如,以下是打印一个 json 对象,分别使用系统 Log 和 TinyLog 的对比:

防止日志丢失如何防止日志丢失是一个非常重要的问题,我们最初使用 A 系统的时候,经常有同事抱怨关键信息丢失。因此在设计 TinyLog 的时候,我

们也考虑到了这个问题。

(1)使用 mmap

我们分析了 A 系统,发现其日志打印的流程如下图左边所示:

这样的结构就会有日志丢失的风险,因为使用了内存缓存,一旦发生 crash,缓存当中的日志就丢失了。

怎样才能防止日志丢失呢?最好的办法就是打印每条日志的时候立刻写进入文件,可是这样就会频繁的触发 IO,存在性能的问题。经过调

研之后,我们使用 mmap 的方式,既能够防止日志丢失,又能保证性能,如下图右边所示。

为什么使用 mmap 性能又好,还不会造成数据丢失呢?以下是标准 IO 和 mmap 在写场景的对比图,标准 IO 下,当我们需要将写入的数据

从用户空间拷贝到内核空间,然后系统会定期的将数据写入磁盘;而使用 mmap,用户空间和内核空间通过映射同一个普通文件实现内存

共享,我们在用户空间内写入的数据相当于直接写入到了内核空间,减少了一次内存拷贝,性能得到提升。而且一旦数据写入到了内核空

间,此时 app 即使发生了 crash 也不会造成数据的丢失,仍然能够由系统保证写入到磁盘上。

以下是我做的一个对比实验,把50 byte 的日志分别写入内存,mmap和文件 10w 次,以下是实验结果:

机器

三星(s20)

iphone 6s

写入内存

16ms

4.9ms

写入mmap

32ms

4.3ms

写入文件

815ms

987ms

可以看出,mmap 在性能上接近于内存。

(2)异常捕获

Android 版本 sdk 我们在 java 层做了全局的异常捕获,当 TinyLog 监测到异常发生时,会立刻将当前的异常信息堆栈写入到日志当中,

当日志写完之后才释放异常。以此确保当 crash 发生时,能够将 crash 的堆栈信息保留下来。

ios 版本 sdk 需要依赖 bugly 或其他崩溃采集组件,在其 crash 回调函数中调用 TinyLog 接口写入 crash 堆栈。

安全兼顾性能

加密算法通常分为对称加密和非对称加密,以下为各自的特点:

分类

对称加密

特点

加密和解密的密钥是一样的

速度

非对称加密

分类

公钥加密,私钥解密

特点

速度

对于日志 sdk 这个场景,若选用对称加密,则必须要将密钥放到 sdk 当中,才能够完成日志文件的加密,这样会有密钥泄漏的风险;

若选用非对称加密,公钥存入 sdk,私钥存在服务端,能够保证安全,但是性能不太好。

因此我们综合了一下,使用了混合加密的方法,既能保证安全又能兼顾性能,具体的流程如下图所示:

1. 客户端和服务端先要约定一套公钥和私钥;

2. 当客户端创建日志块时,随机生成一串字符串 key,此时使用公钥加密随机生成的 key 得到 key’,将 key’ 记录到日志文件当中,

然后 key 当作对称加密的密钥来加密日志;

3. 服务端在解密时,需要先将 key’ 从日志文件当中读出,然后使用私钥解密出 key,再使用对称加密的方式解密日志得到明文。

虽然非对称加密方式比较慢,但在混合加密的场景只有在创建日志块的时候才会使用一次,而真正加密日志的方法使用的是性能较好的对称

加密,每个日志块的密钥均为随机生成,而真正记录在日志文件当中的密钥为加密过后的密文。因此在性能上接近对称加密,而安全性又接近

于非对称加密。

以下为加密 1w 条 100 byte 日志的对比实验,使用的是三星 s20:

分类

非对称加密

对称加密

时间

1070ms

33ms

混合加密

分类

50ms

时间

图形化显示日志接口

如何让日志更加清晰和直观的展示?

目前我们团队的开发同学使用 fancylog 的插件来查看日志,fancylog 是一个能够可视化显示日志的插件,其原理是根据配置好的正则表

达式规则,将给定的日志文件图形化的显示出来,能够极大的提高查看日志的效率。

既然是通过正则表达式来匹配,那我们何不将一些通用的方法抽象出来形成接口,然后为这些接口提供对应的正则表达式,这样只要使用这

个接口打印出来的日志,就能够被 fancylog 解析出来,而无需自己配置了。

以下为 TinyLog 当中提供的图形化显示日志的接口:

类别

场景

接口

loadScene(String sceneName)

loadSceneSuccess(String sceneName)

loadSceneFailed(String sceneName)

操作switchFront(String msg)

switchBack(String msg)

click(String msg)

异常exception(String msg,Exception exception)

crash(String msg,Exception exception)

过程processStart(String msg)

processing(String msg)

processEnd(String msg)

其他event(String event)

备注

加载场景

加载成功

加载失败

切前台

切后台

点击事件

出现异常

crash

开始

进行中

结束

自定义event

当我们的日志上传到日志网站之后就能够自动的图形化展示了,如下图所示

非侵入式的打印日志

有同事提出,目前 TinyLog 所提供的图形化展示接口,是一种侵入式的结构化日志实现方式,业务方需要在代码中显示的调用 fancylog,

才能够实现日志的结构化展示。既然这样我们何不使用注解的方式,实现无侵入式的打印日志呢。

因此,我们设计并实现了 FancyLogger 组件,我们自定义了一些日志的注解,并针对被注解标记的方法增加切面,当对应的方法执行完成

时,便触发日志打印的逻辑。

以下为 FancyLogger 当中包含的注解:

注解

ActivityCycle

FragmentCycle

Click

Crash

Event

ExceptionLog

LoadScene

ProcessLog

Switch

备注

Activity生命周期,类注解

Fragment生命周期,类注解

点击事件,方法注解

crash,方法注解

自定义事件,方法注解

异常,方法注解

加载场景,方法注解

过程方法注解

切前后台,方法注解

FancyLogger 当中提供了两种注解,分别是方法注解和类注解,其中类注解为 ActivityCycle 和 FragmentCycle 能够自动的打印

Activity 和 Fragment 的生命周期。

以下分别为方法注解和类注解的示例。

方法注解

如下所示,在 testEvent 方法上面添加 Click 注解

@Click(msg = "testEvent")

public void testEvent(){

Log.i("测试","执行了testEvent");

}

当我们执行 testEvent 方法时,会有如下打印,其中第一条日志为执行 testEvent 方法内部的日志,第二条日志为 FancyLogger 打印的

日志。

类注解

如下所示,在 MainActivity 类上增加 ActivityCycle 注解

@ActivityCycle(tag="MainActivity")

public class MainActivity extends AppCompatActivity {

...

}

当 Activity 执行了对应的生命周期的方法时,会有如下日志打印:

TinyLog 的性能测试

以下为瞬间写入 10w 条 50byte 日志信息在各个不同维度的数据,其中内存,cpu峰值均使用 PerfDog 进行测试。

时间

机器

三星s20

iphone11

不压缩不加密

269.2ms

604.9ms

压缩加密

276.6ms

815.8ms

日志文件大小

机器

三星s20

iphone11

不压缩不加密

12.3MB

10.3MB

压缩加密

851KB

904KB

内存占用

以下场景使用 TinyLog demo 进行测试。

三星s20

场景

打开应用

初始化 TinyLog

写入10w条日志峰值

写入10w条之后的内存

不压缩不加密

60MB

63MB

83MB

67MB

压缩加密

63MB

66MB

91MB

70MB

iphone11

场景

打开应用

初始化 TinyLog

写入10w条日志峰值

写入10w条之后的内存

不压缩不加密

38MB

38.2MB

38.7MB

38.6MB

压缩加密

38MB

38.3MB

39.8MB

39MB

cpu 峰值

机器

三星s20

iphone11

不压缩不加密

18%

10%

压缩加密

18%

10%

g 服务端

日志多维度搜索

TinyLog 上传日志时候,支持自定义 tag。例如,用户反馈的场景可以增加 type 为 user,crash 场景可以增加 type 为 crash。我们除了

可以按照日志上传时间进行搜索之外,还可以根据自定义的 tag 进行搜索。这样我们就可以根据不同的 tag 更加精准的定位到日志。

一键图形化展示日志

日志上传到服务端之后,点击在线查看,便可以将日志图形化展示出来。如下图所示,我们通过右边的图形就可以快速的定位到问题。点击

右边红色的菱形模块,就能够定位到左边日志。

3.本地解压解密工具如果我们遇到一些特殊场景,不方便上传日志,TinyLog 提供了本地解密工具,我们只需要将日志导出,用本地解密工具进行解密。本地解

密工具只是将大部分解密的步骤放在本地,核心的非对称解密步骤仍然放在服务端,不会造成密钥的泄漏。

2023年12月11日发(作者:尉彦珺)

安全高效可视化的日志解决方案

背景

一条工单引发的日志需求

我们的业务收到了一个信息泄漏的工单,漏洞是明文打印日志。

我们当时使用的是某网络库自带的日志系统(以下简称 A 系统),会直接将明文写入到了日志文件当中,这样就有信息泄漏的风险。

我们搜集了当前使用 A 系统的痛点:

1. 明文打印,造成隐私泄漏;

2. 关键日志丢失;

3. 无法方便的打印当前的堆栈,线程等信息;

4. 不支持各种格式化输出。

为了解决这个问题,我们设计并实现了 TinyLog。

TinyLog 能支持日志的加密和压缩,减少日志文件大小并确保隐私不会泄漏;能够支持各种格式化输出,且比较方便的打印出当前的堆栈,

线程等信息;我们在设计的时候也考虑到了日志丢失的问题,在 crash 的场景,也能够确保当前的 crash 堆栈能够被记录下来;此外我们

还提供了图形化展示日志的接口,能够将日志图形化的展示出来,方便开发同学快速的定位到问题。

TinyLog 的总体设计作为一个日志组件,安全和高效是我们的一个核心需求。安全包括两点,日志不丢失以及隐私不泄漏;高效就是日志组件不能影响应用的性

能。我们在设计 TinyLog 的时候也充分考虑到了这两点,以下是 TinyLog 的总体设计图:

客户端加密,服务端解密。服务端提供明文下载以及图形化展示日志的功能。客户端来保证打印日志的高效性,服务端来保证安全性。

g SDK如何才能支持多种格式化输出,并能保持良好的性能呢?

以下是 TinyLog SDK 的结构图:

我们将 TinyLog SDK 分为三层,分别是输入层,处理层和输出层。其中处理层包含了很多日志的配置项,能够满足各种场景的格式化输

出;另外,在输出层,我们将加密,压缩以及文件写入的功能下沉到 c++,保证了良好的性能。

输入层:

输入层为对外提供的接口,主要提供了初始化方法以及日志打印的方法。我们参考了系统打印日志的接口,并在其基础上进行扩充,降低业

务方的接入成本。以下为 TinyLog 和系统日志打印的接口对比,以 info 等级为例:

系统原有的两个日志打印的接口,我们将其扩充为4个,并在其基础上进行了增强。如系统接口 i(String tag,String msg),第二个参数只

能是字符串对象,而我们将其增强为 i(String tag,T obj),第二个参数可以是任何对象,我们会匹配对应的格式化方法,将其进行格式化处

理。比如第二个参数是 json 对象,我们就会使用 JsonFormatter 将 json 对象进行格式化,若输入的对象在 TinyLog 内部未匹配到任何

Formatter ,则会直接调用该对象的 toString 方法。

处理层:

在这一层,日志会被分发给 Logger,每个 Logger 都包含一个 LogConfig(配置信息)和 Printer(输出), Logger 会根据

LogConfig 将日志封装成为一个日志对象,然后传递给 Printer 输出。LogConfig 的配置信息包括日志等级过滤,是否打印线程,是否打

印边框等,以及各种格式化方法。

我们将格式化抽象成了一个 Formatter 接口,并默认实现了各种场景的格式化方法,具体如下表格所示,业务方也可根据需要自己实现

Formatter 接口。

格式化

DefaultBorderFormatter

DefaultJsonArrayFormatter

DefaultJsonFormatter

DefaultStackTraceFormatter

DefaultThreadFormatter

DefaultThrowableFormatter

DefaultXmlFormatter

备注

边框格式化

Json数组格式化

Json对象格式化

堆栈格式化

线程格式化

异常信息格式化

xml格式化

输出层:

我们将输出抽象成了 Printer 接口,TinyLog 默认实现了 ConsolePrinter 和 FilePrinter,分别将日志输出到控制台和文件当中。若输出

到文件,则可以将日志上传到服务端。业务方也可以自定义 Printer,将日志输出到任何地方。

让日志的输出更加友好

TinyLog 能够很轻松的打印当前的线程信息,堆栈信息以及常见的对象,并默认实现了各种格式化方法,包括边框,json,线程,堆栈

等。

例如,以下是打印一个 json 对象,分别使用系统 Log 和 TinyLog 的对比:

防止日志丢失如何防止日志丢失是一个非常重要的问题,我们最初使用 A 系统的时候,经常有同事抱怨关键信息丢失。因此在设计 TinyLog 的时候,我

们也考虑到了这个问题。

(1)使用 mmap

我们分析了 A 系统,发现其日志打印的流程如下图左边所示:

这样的结构就会有日志丢失的风险,因为使用了内存缓存,一旦发生 crash,缓存当中的日志就丢失了。

怎样才能防止日志丢失呢?最好的办法就是打印每条日志的时候立刻写进入文件,可是这样就会频繁的触发 IO,存在性能的问题。经过调

研之后,我们使用 mmap 的方式,既能够防止日志丢失,又能保证性能,如下图右边所示。

为什么使用 mmap 性能又好,还不会造成数据丢失呢?以下是标准 IO 和 mmap 在写场景的对比图,标准 IO 下,当我们需要将写入的数据

从用户空间拷贝到内核空间,然后系统会定期的将数据写入磁盘;而使用 mmap,用户空间和内核空间通过映射同一个普通文件实现内存

共享,我们在用户空间内写入的数据相当于直接写入到了内核空间,减少了一次内存拷贝,性能得到提升。而且一旦数据写入到了内核空

间,此时 app 即使发生了 crash 也不会造成数据的丢失,仍然能够由系统保证写入到磁盘上。

以下是我做的一个对比实验,把50 byte 的日志分别写入内存,mmap和文件 10w 次,以下是实验结果:

机器

三星(s20)

iphone 6s

写入内存

16ms

4.9ms

写入mmap

32ms

4.3ms

写入文件

815ms

987ms

可以看出,mmap 在性能上接近于内存。

(2)异常捕获

Android 版本 sdk 我们在 java 层做了全局的异常捕获,当 TinyLog 监测到异常发生时,会立刻将当前的异常信息堆栈写入到日志当中,

当日志写完之后才释放异常。以此确保当 crash 发生时,能够将 crash 的堆栈信息保留下来。

ios 版本 sdk 需要依赖 bugly 或其他崩溃采集组件,在其 crash 回调函数中调用 TinyLog 接口写入 crash 堆栈。

安全兼顾性能

加密算法通常分为对称加密和非对称加密,以下为各自的特点:

分类

对称加密

特点

加密和解密的密钥是一样的

速度

非对称加密

分类

公钥加密,私钥解密

特点

速度

对于日志 sdk 这个场景,若选用对称加密,则必须要将密钥放到 sdk 当中,才能够完成日志文件的加密,这样会有密钥泄漏的风险;

若选用非对称加密,公钥存入 sdk,私钥存在服务端,能够保证安全,但是性能不太好。

因此我们综合了一下,使用了混合加密的方法,既能保证安全又能兼顾性能,具体的流程如下图所示:

1. 客户端和服务端先要约定一套公钥和私钥;

2. 当客户端创建日志块时,随机生成一串字符串 key,此时使用公钥加密随机生成的 key 得到 key’,将 key’ 记录到日志文件当中,

然后 key 当作对称加密的密钥来加密日志;

3. 服务端在解密时,需要先将 key’ 从日志文件当中读出,然后使用私钥解密出 key,再使用对称加密的方式解密日志得到明文。

虽然非对称加密方式比较慢,但在混合加密的场景只有在创建日志块的时候才会使用一次,而真正加密日志的方法使用的是性能较好的对称

加密,每个日志块的密钥均为随机生成,而真正记录在日志文件当中的密钥为加密过后的密文。因此在性能上接近对称加密,而安全性又接近

于非对称加密。

以下为加密 1w 条 100 byte 日志的对比实验,使用的是三星 s20:

分类

非对称加密

对称加密

时间

1070ms

33ms

混合加密

分类

50ms

时间

图形化显示日志接口

如何让日志更加清晰和直观的展示?

目前我们团队的开发同学使用 fancylog 的插件来查看日志,fancylog 是一个能够可视化显示日志的插件,其原理是根据配置好的正则表

达式规则,将给定的日志文件图形化的显示出来,能够极大的提高查看日志的效率。

既然是通过正则表达式来匹配,那我们何不将一些通用的方法抽象出来形成接口,然后为这些接口提供对应的正则表达式,这样只要使用这

个接口打印出来的日志,就能够被 fancylog 解析出来,而无需自己配置了。

以下为 TinyLog 当中提供的图形化显示日志的接口:

类别

场景

接口

loadScene(String sceneName)

loadSceneSuccess(String sceneName)

loadSceneFailed(String sceneName)

操作switchFront(String msg)

switchBack(String msg)

click(String msg)

异常exception(String msg,Exception exception)

crash(String msg,Exception exception)

过程processStart(String msg)

processing(String msg)

processEnd(String msg)

其他event(String event)

备注

加载场景

加载成功

加载失败

切前台

切后台

点击事件

出现异常

crash

开始

进行中

结束

自定义event

当我们的日志上传到日志网站之后就能够自动的图形化展示了,如下图所示

非侵入式的打印日志

有同事提出,目前 TinyLog 所提供的图形化展示接口,是一种侵入式的结构化日志实现方式,业务方需要在代码中显示的调用 fancylog,

才能够实现日志的结构化展示。既然这样我们何不使用注解的方式,实现无侵入式的打印日志呢。

因此,我们设计并实现了 FancyLogger 组件,我们自定义了一些日志的注解,并针对被注解标记的方法增加切面,当对应的方法执行完成

时,便触发日志打印的逻辑。

以下为 FancyLogger 当中包含的注解:

注解

ActivityCycle

FragmentCycle

Click

Crash

Event

ExceptionLog

LoadScene

ProcessLog

Switch

备注

Activity生命周期,类注解

Fragment生命周期,类注解

点击事件,方法注解

crash,方法注解

自定义事件,方法注解

异常,方法注解

加载场景,方法注解

过程方法注解

切前后台,方法注解

FancyLogger 当中提供了两种注解,分别是方法注解和类注解,其中类注解为 ActivityCycle 和 FragmentCycle 能够自动的打印

Activity 和 Fragment 的生命周期。

以下分别为方法注解和类注解的示例。

方法注解

如下所示,在 testEvent 方法上面添加 Click 注解

@Click(msg = "testEvent")

public void testEvent(){

Log.i("测试","执行了testEvent");

}

当我们执行 testEvent 方法时,会有如下打印,其中第一条日志为执行 testEvent 方法内部的日志,第二条日志为 FancyLogger 打印的

日志。

类注解

如下所示,在 MainActivity 类上增加 ActivityCycle 注解

@ActivityCycle(tag="MainActivity")

public class MainActivity extends AppCompatActivity {

...

}

当 Activity 执行了对应的生命周期的方法时,会有如下日志打印:

TinyLog 的性能测试

以下为瞬间写入 10w 条 50byte 日志信息在各个不同维度的数据,其中内存,cpu峰值均使用 PerfDog 进行测试。

时间

机器

三星s20

iphone11

不压缩不加密

269.2ms

604.9ms

压缩加密

276.6ms

815.8ms

日志文件大小

机器

三星s20

iphone11

不压缩不加密

12.3MB

10.3MB

压缩加密

851KB

904KB

内存占用

以下场景使用 TinyLog demo 进行测试。

三星s20

场景

打开应用

初始化 TinyLog

写入10w条日志峰值

写入10w条之后的内存

不压缩不加密

60MB

63MB

83MB

67MB

压缩加密

63MB

66MB

91MB

70MB

iphone11

场景

打开应用

初始化 TinyLog

写入10w条日志峰值

写入10w条之后的内存

不压缩不加密

38MB

38.2MB

38.7MB

38.6MB

压缩加密

38MB

38.3MB

39.8MB

39MB

cpu 峰值

机器

三星s20

iphone11

不压缩不加密

18%

10%

压缩加密

18%

10%

g 服务端

日志多维度搜索

TinyLog 上传日志时候,支持自定义 tag。例如,用户反馈的场景可以增加 type 为 user,crash 场景可以增加 type 为 crash。我们除了

可以按照日志上传时间进行搜索之外,还可以根据自定义的 tag 进行搜索。这样我们就可以根据不同的 tag 更加精准的定位到日志。

一键图形化展示日志

日志上传到服务端之后,点击在线查看,便可以将日志图形化展示出来。如下图所示,我们通过右边的图形就可以快速的定位到问题。点击

右边红色的菱形模块,就能够定位到左边日志。

3.本地解压解密工具如果我们遇到一些特殊场景,不方便上传日志,TinyLog 提供了本地解密工具,我们只需要将日志导出,用本地解密工具进行解密。本地解

密工具只是将大部分解密的步骤放在本地,核心的非对称解密步骤仍然放在服务端,不会造成密钥的泄漏。

发布评论

评论列表 (0)

  1. 暂无评论