前言:主要事项
1、异常数据的发现及补充、日志分类优化
2、日志数据的文件保存、滚动存储
3、日志文件上传
4、日志回捞
一、日志收集
1、日志分类
1.1、日志目标
| 序号 | 目标(Target) | ||
|---|---|---|---|
| 1 | app | ||
| 2 | sdk | 三方库 | |
| 3 | h5 | 网页 |
1.2、日志类型
| 序号 | 类型 | 描述 | |
|---|---|---|---|
| 1 | api_app | app中的网络请求 | |
| 2 | api_app_cache | app中的网络请求的网络缓存请求 | |
| 3 | api_buriedPoint | 埋点的网络请求 | |
| 4 | sdk_other | sdk的各种事件(初始化等) | |
| 5 | sdk_api | sdk中的网络请求 | |
| 6 | dart | 语法 | |
| 7 | widget | 视图(布局像素越界等) | |
| 8 | click_other | 点击、 | |
| 9 | click_share | 分享 | |
| 10 | native_route | 路由/跳转 | |
| 11 | h5_route | 与网页跳转有关 | |
| 12 | h5_js | js交互 | |
| 13 | monitor_network | 监控:网络类型变化 | |
| 14 | monitor_lifecycle | 监控:生命周期变化 | |
| 15 | buriedPoint_other | 埋点数据生成等 | |
| 16 | im | IM | |
| 17 | heartbeat | 心跳 | |
| 18 | other | 其他 |
2、日志等级
| 序号 | 目标(Level) | 描述 | |
|---|---|---|---|
| 1 | Normal | 正常信息(目前用于请求开始) | |
| 2 | Success | 成功信息(目前用于请求结束:成功) | |
| 3 | Warning | 警告信息(目前用于请求结束:报错) | |
| 4 | Error | 错误日志(目前用于请求结束:失败) | |
| 5 | Dangerous | 危险(处理白屏等) | 一般会进行额外的埋点 |
3、日志整合归类
| 序号 | 列表 | 标志 | 包含 |
|---|---|---|---|
| 1 | 全部 | all | 所有 |
| 2 | 警告 | warning | 所有的警告 |
| 3 | 错误 | error | 所有的错误 |
| 4 | 接口 | api | api_app、api_cache(不包括sdk_api、api_buriedPoint) |
| 5 | 点击 | click | click_share、click_other、h5_js |
| 6 | 路由 | route | navite_route、h5_route |
| 7 | 网页 | H5 | h5_route、h5_js |
| 8 | sdk | sdk | sdk_api、sdk_other |
| 9 | code | code | dart、widget |
| 10 | 埋点 | buriedPoint | api_buriedPoint、buriedPoint_other |
| 11 | 监控 | monitor | monitor_lifecycle、monitor_network |
| 12 | 其他 | other | other |
| 13 | api结果 | api_result | type=api_app & level != Normal |
| 14 | im | im | 本地缓存消息、历史消息、收到的消息等 |
| 15 | 心跳 | heartbeat |
4、日志的补充收集及其策略
要收集的数据已在上述《1.2、日志类型》中说明。
4.1、页面跳转
详见上述 《3、日志整合归类》中的”路由”
4.2、截断的收集
| 序号 | 关键字 | 场景 |
|---|---|---|
| 1 | break | for 、 swtich |
| 2 | return |
4.3、用户关键行为
| 序号 | 行为 | 用途的场景说明 |
|---|---|---|
| 1 | 用户的资源选择 | 判断选择的本地资源是否上传到错误的存储桶 |
二、日志数据的文件保存、滚动存储
1、数据的文件保存
写入xlog文件中。
2、数据的文件滚动存储
2.1、日志的过期清理
1、本地日志文件结构
1 | -- Document |
2、日志保留清理的配置信息(摘自/同 下文的日志接口中的《日志文件配置信息》)
序号 说明 字段 示例 接口回值1 最多保留几个天的日志目录 maxDayDirCount 7 接口回值2 最多每天保留几个文件 maxDayFileCount 10 接口回值3 每个日志文件超过多少后创建新文件 perFileMaxMB 5
3、清理方案
清理时机:在切换前后台的时候,
- 日志配置信息的更新
- 根据最新的日志配置信息,延迟10s后(避免影响启动),进行清理判断及清理
- 遍历总日志目录 Document/log 下的所有日志文件夹
- 如果天日志文件夹个数超过保留个数(避免是用保留时间,导致保留时间内只有一个日志,也被删掉),则按顺序删除早期日志
- 遍历天日志目录 Document/log/yyyy-MM-dd 下的所有日志文件夹
- 如果天日志文件夹个数超过保留个数(避免是用保留时间,导致保留时间内只有一个日志,也被删掉),则按顺序删除早期日志
2.2、日志文件的滚动写入
要增加的日志记录,如果添加后会超过日志文件的大小,则使用新文件写入。
细节点:
1、日志文件的大小判断,不要每次都去读取文件,而是记录住大小变化
2、日志不要有一条写一条,而是使用写入缓冲区+定时器,5s尝试写入一次
3、数据的加密、解密
1、加密:
写入日志字符串时候,对编码后的字节数据,额外增加一个三位随机值。
1 | /// 使用 GZip 压缩算法将字符串进行压缩,并返回压缩后的字节数据(List<int> 类型)。 |
2、解密:
使用python脚本对log文件进行解密
1 | import sys |
三、日志文件上传
1、日志文件命名及目录规范
以用户1000001在2020-01时候上传声音文件 beautiful_scenery.aac为例,其路径完整示例如下:
1 | https://media.xxx.com/app1_test1/audio/1/1000001/2020-01/beautiful_scenery.aac |
要上传的存储桶:
| 序号 | 说明 | 参数 | 约定值示例 |
|---|---|---|---|
| 1 | 存储桶region regionGetFunction |
网络环境 | ap-shanghai |
| 2 | 存储桶bucket bucketGetFunction |
网络环境 | xxx-pro-image-1302324914 |
| 3 | 上传成功后,桶的映射路径值 cosFileUrlPrefixGetFunction |
1、图片桶:https://images.xxx.com/ 2、媒体桶:https://media.xxx.com/ 3、日志桶:https://static.xxx.com/ |
|
| 4 | 要上传到桶的哪个相对路径下 cosFileRelativePathGetFunction 上传成功后完整路径=以上桶值+此相对路径 |
见下文 | 见下文 eg:app1_test1/audio/1/1000001/2020-01/beautiful_scenery.aac |
《要上传到桶的哪个相对路径下 cosFileRelativePathGetFunction 》的文件路径分批说明:
| 序号 | 层次说明 | 层次值算法 | 层次值描述 |
|---|---|---|---|
| 1.1 | 存储桶里相对路径的前缀 | app标志_环境标志 eg:app1_pro、app1_test1、app1_dev1 |
文件区分 |
| 1.2 | 是否在存储桶里进行进一步路径区分(可选) | 根据场景决定是否对桶进行进一步分类。 if ( mediaType == xxx ) { if(mediaScene == yyy) { } } |
如 1、都是图片,但自拍图片要求独立出来 2、都是多媒体,但音视频要区分开 |
| 2.1 | 用户1级 | int.parse(uid) % 1000; // 取余数 | 用户名取余,有效减少同层上文件夹个数 |
| 2.2 | 用户2级 | uid | 用户名 |
| 3 | 年月 | DateTime.now().toString().substring(0, 7); | 年-月 |
| 4 | 文件名 | ${fileOriginName}_ ${DateTime.now().microsecondsSinceEpoch} .$fileExtensionType |
文件名 |
附1:MediaType 媒体类型
| 序号 | UploadMediaType 媒体类型 | 描述 | |
|---|---|---|---|
| 1 | unkonw | 未知(默认值) | |
| 2 | image | 图片 | |
| 3 | audio | 音频 | |
| 4 | video | 视频 | |
| 5 | xlog | 日志文件 |
附2:MediaScene场景 说明
| 序号 | UploadMediaScene场景 | 描述 |
|---|---|---|
| 1 | unkonw | 未知(默认值) |
| 2 | selfie | 自拍(安全等级较多) |
| 3 | im | 会话聊天 |
| 4 | live | 直播 |
四、日志接口
1、日志记录接口(区别于回捞接口,需要在回捞前就有日志信息)
1、是否记录日志的开关及其配置信息
| 序号 | 说明 | 字段 | 示例 |
|---|---|---|---|
| 网页配置1 | 是否开启日志记录 | isLogOn | 1:开启、其他:关 |
| 网页配置2 | 要开启日志的用户(灰度上线) (当且仅当开启上述日志记录时有效) 📢:未配置但开关为开时为全记录 |
logUserids | [“101”, “102”] |
| 网页配置3 | 要开启日志的设备(灰度上线) (当且仅当开启上述日志记录时有效) 📢:未配置但开关为开时为全记录 |
logDeviceIds | [“udid001”, “udid002”] |
| 接口回值1 | 是否进行日志记录(灰度上线) | needLog | 1:记录、其他:不记录 |
2、不需要记录什么日志信息
| 序号 | 说明 | 字段 | 示例 |
|---|---|---|---|
| 接口回值1 | 不需要记录的日志类型 | ignoreLogLevel | [“Normal”, “Success”] |
| 接口回值2 | 不需要记录的日志等级 | ignoreLogType | [“api_buriedPoint”, “buriedPoint_other”] |
3、日志文件配置信息
| 序号 | 说明 | 字段 | 示例 |
|---|---|---|---|
| 接口回值1 | 最多保留几个天的日志目录 | maxDayDirCount | 7 |
| 接口回值2 | 最多每天保留几个文件 | maxDayFileCount | 10 |
| 接口回值3 | 每个日志文件超过多少后创建新文件 | perFileMaxMB | 5 |
4、日志文件问题回滚
| 序号 | 说明 | 字段 | 示例 |
|---|---|---|---|
| 网页配置1 | 强制删除什么时间前的日志 | removeLogBeforeDate | 2020-12-31 |
| 网页配置2 | 强制删除哪个用户的日志 | removeUserids | [“101”, “102”] |
| 网页配置2 | 强制删除哪个设备的日志 | logDeviceIds | [“udid001”, “udid002”] |
| 接口回值1 | 强制删除什么时间前的日志(不删除时空) | removeLogBeforeDate | 2020-12-31 或 空值 |
接口名定义:
1 | function getLoggerConfig(userid, deviceId) |
接口结果的json示例如下:
1 | { |
2、日志回捞及问题回滚接口
1、日志回捞
| 序号 | 说明 | 字段 | 示例 |
|---|---|---|---|
| 网页配置1 | 要回捞日志的用户 | salvageUserids | [“101”, “102”] |
| 网页配置2 | 要回捞日志的设备 | salvageDeviceIds | [“udid001”, “udid002”] |
| 网页配置3 | 日志回捞的开始时间 | salvageStartDate | 2020-01-01 |
| 网页配置4 | 日志回捞的结束时间 | salvageEndDate | 2020-01-07 |
| 接口回值1 | 此用户此设备日志回捞的开始时间 | salvageStartDate | 2020-01-01 |
| 接口回值1 | 此用户此设备日志回捞的结束时间 | salvageEndDate | 2020-01-07 |
2、日志文件问题回滚
| 序号 | 说明 | 字段 | 示例 |
|---|---|---|---|
| 网页配置1 | 强制删除什么时间前的日志 | removeLogBeforeDate | 2020-12-31 |
| 网页配置2 | 强制删除哪个用户的日志 | removeUserids | [“101”, “102”] |
| 网页配置2 | 强制删除哪个设备的日志 | logDeviceIds | [“udid001”, “udid002”] |
| 接口回值1 | 强制删除什么时间前的日志(不删除时空) | removeLogBeforeDate | 2020-12-31 或 空值 |
接口名定义:
1 | function getLoggerSalvageAndRevert(salvageUserids, salvageDeviceIds) |
接口结果的json示例如下:
1 | { |
3、日志文件上传到cos后同步给后台
用途:日志文件上传到cos后同步给后台,后台数据库记录每个用户,每个设备都捞到了什么数据。
接口名定义:
1 | function addLoggerFile(userid, deviceId) |
接口结果的json示例如下:
1 | { |
四、日志回捞
1、后台通过接口返回要回捞的信息。
2、前端用户在下次使用,收到后台信息时候,进行本地日志的上传。在腾云存储桶能收到对应日志,即代表成功。
五、方案实施
灰度方案:请参照 灰度系统 。(附:日志记录开关里目前已有灰度策略。)
目的:避免功能异常,出现集体性问题。