强平无效日志太多
强平关键日志太少
强平对账困难
强平很难复现问题
强平缺乏tracing功能
强平缺乏统计报表
强平缺乏监控报警
强平缺乏自动修复策略
强平日志格式缺乏规范化
强平日志分散
强平日志逻辑错误
强平太多无效日志问题
强平日志指标缺乏,对账困难,还原生命周期图困难等问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-77WRiKFU-1656267188054)(C:/D/workspace/trade/doc/%E6%A6%82%E8%A6%81%E8%AE%BE%E8%AE%A1%E6%96%87%E6%A1%A3/5.png)]
入金和强平是互斥操作,同一时刻只能执行一个,入金的优先级更高,因此保证金服务要想入金需要进行入金申请操作,当前双方处理流程:
收集规则:收集强平过程状态变迁日志
日志类别:
强平流程日志表:包括强平流程配置,账户状态和性能监控
强平步骤日志表:包括强平流程每个步骤的账户状态和性能监控
强平过程中永续活动订单日志:包括合约名称,大小,方向,挂单价格,市场价格
强平过程中永续仓位日志
强平过程中期权活动订单日志
强平过程中期权仓位日志
强平过程中RPC调用日志:包括入参,出参,返回码和性能监控
强平过程中rpc被调用日志:包括入参,出参,返回码和性能监控
强平过程中消息队列发送日志:包括往kafka,rocketmq,springApplicationEvent,disruptor发送的日志
强平过程中收日志:包括从kafka,rocketmq,springApplicationEvent,disruptor接收的日志
强平过程中方法调用日志:包括入参,出参,返回码和性能监控
1号轮OptLiquidationWalContentCmp
1号轮TradingResultWalContentCmp
1号轮PerpLiquidationWalContentCmp
3号轮EnterLiqProcessTradingResultProcessCmp
3号轮ManualTakeOverProcessCmp
3号轮LiqTradingResultProcessCmp
3号轮PassThroughTradingResultProcessCmp
3号轮TradingResultLiqConvertProcessCmp
3号轮PerpTradingResultLiqCmp
3号轮LiqInfoUpdateProcessCmp
拦截器TradingResultLiqBizInterceptor
EnterLiqProcessServiceTrImpl
LiquidationServiceTrImpl
PassThroughServiceTrImpl
TradingResultLiqConvertServiceTrImpl
PerpTradingResultLiqImpl
LiqInfoUpdateServiceTrImpl
策略机EnterLiqProcessLiqStgCmp
策略机CancelOrderLiqStgCmp
策略机LiquidationLiqStgCmp
策略机PassThroughLiqStgCmp
策略机PerpLiquidationStgCmp
策略机PerpPartLiqStgCmp
策略机PerpTakeOverStgCmp
策略机LiqInfoUpdateStgCmp
状态机LiqStateMachineService
日志统计:
监控报警:
grafana或悟空监控强平流程返回码,非0,非200则报警
grafana或悟空监控强平流程耗时,大于10秒则报警
grafana或悟空监控强平流程调用频次,每分钟总强平数大于1000次则报警
grafana或悟空监控强平请求返回码,非0,非200则报警
grafana或悟空监控强平请求耗时,大于10秒则报警
grafana或悟空监控强平请求调用频次,每分钟总强平数大于1000次则报警
grafana或悟空监控强平步骤返回码,非0,非200则报警
grafana或悟空监控强平步骤耗时,大于10秒则报警
grafana或悟空监控强平步骤调用频次,每分钟总强平数大于1000次则报警
grafana或悟空监控强平过程中rpc调用返回码,非0,非200则报警
grafana或悟空监控强平过程中rpc调用耗时,大于2秒则报警
grafana或悟空监控强平过程中rpc调用频次,每分钟总rpc调用大于10000次则报警
grafana或悟空监控强平过程中rpc被调用返回码,非0,非200则报警
grafana或悟空监控强平过程中rpc被调用耗时,大于2秒则报警
grafana或悟空监控强平过程中rpc被调用频次,每分钟总rpc调用大于10000次则报警
grafana或悟空监控强平过程中消息队列发送返回码,非0,非200则报警
grafana或悟空监控强平过程中消息队列发送耗时,大于2秒则报警
grafana或悟空监控强平过程中消息队列发送频次,每分钟总rpc调用大于10000次则报警
grafana或悟空监控强平过程中消息队列接收返回码,非0,非200则报警
grafana或悟空监控强平过程中消息队列接收耗时,大于2秒则报警
grafana或悟空监控强平过程中消息队列接收频次,每分钟总rpc调用大于10000次则报警
grafana或悟空监控强平过程中强平核心类调用返回码,非0,非200则报警
grafana或悟空监控强平过程中强平核心类调用耗时,大于2秒则报警
grafana或悟空监控强平过程中强平核心类调用频次,每分钟总强平核心类调用大于10000次则报警
grafana或悟空监控强平中入金插队行为,
grafana或悟空监控强平中交割插队行为
grafana或悟空监控强平中其他互斥操作行为
grafana或悟空监控接管户资金池数据一致性问题
动态开闭:
日志查询:
图表展示:
统计比较
统一界面:根据metric,tracing,logging快速定位和排查问题,减少页面跳转,减少阅读难度。
日志精简:非关键行非关键字段不打印,减少网络io,减少存储,减少阅读难度。
日志完整:关键行关键字段必须打印,方便还原强平流程图,通过数据在IDE进行debug或静态跟踪代码。
异步写入:不影响主线程。
批量写入:减少网络IO。
实时处理:日志从产生,查询,统计,分析秒级完成。
存储方式:每种日志类型写入独立日志文件,日志文件按照时间日期分割,再按照大小分割。
业务拓展:适配未来日志中间件的变更,即使中间件推到重来,日志格式和日志内容也不需要大幅度变动。
日志格式:日志默认使用json,既有利于人类阅读,又支持常见日志中间件清洗转换搜索统计分析。
日志清理:过期日志,比如24小时以前的日志,可自动清理,节省存储空间。
分析审计:对数据有交互式分析能力,将结果以可视化方式展示。
数据挖掘:适配未来和数仓对接,对于大量的历史日志,可进行数据挖掘。
通过本地日志文件存储日志
写入日志简单
查询日志困难
统计分析困难
异常报警困难
需要占用本地硬盘
高峰期时暂存硬盘
低峰期时同步至es
jraft切主时需要查询ip
此阶段为第一阶段,理解非常简单,
方便梳理流程和业务功能验证
难点是确定哪些情况需要写入日志
写入日志的字段必须满足后续的查询统计分析报警
无关字段避免写入
系统已经存在内存数据发送到消息队列,直接把日志发送到消息队列,充分利用已有资源。
日志直接发送到消息队列,不再写本地日志,减少了一个旁路,数据一致性更加有保障
日志直接发送到消息队列,不需要耗费应用服务器硬盘,也不需要启动清理日志程序
日志直接发送到消息队列,要时刻依赖网络,系统稳定性要求更高一些,避免网络中断,导致数据丢失
日志直接发送到消息队列,没有优先级之分,高峰期会更加频繁的发送到消息队列,浪费宝贵的网络IO
日志直接发送到消息队列,要保障下游及时消费,防止消息堆积,导致数据丢失
日志直接发送到消息队列,虽然不必清理本地硬盘,但要经常清理margin-db(因为日志量比较大)
日志直接发送到消息队列,需要改造liqDigest对象,也可以新增对象新增tag
查询搜索效率低下
缺少统计分析功能
缺少监控报警功能
通过logstash收集日志,对应用无侵入性
通过kibana查询日志,拥有浏览器即可操作,直观清晰
日志文件被删除了也并不可怕,因为日志已经持久化到es了
日志持久化到了elasticsearch,可被Prometheus轻易采集到,并对异常情况报警通知
不管将来继续使用jraft还是使用其他服务编排方式,使用elk意味着我们查询业务日志时不再需要关注哪个机器生成的日志了,刀耕火种黑麻麻的命令行一去不复返,查找问题的速度和工作体验感暴增
通过margin-db收集日志,对应用无侵入性
通过mysql客户端查询日志,拥有datagrid即可操作,直观清晰
消息队列的日志过期了也并不可怕,因为日志已经持久化到mysql了
日志持久化到了mysql,可被margin-validation定时任务轻易采集到,并对异常情况报警通知
不管将来继续使用jraft还是使用其他服务编排方式,使用margin-db后意味着我们查询业务日志时不再需要关注哪个机器生成的日志了,刀耕火种黑麻麻的命令行一去不复返,查找问题的速度和工作体验感暴增
应用程序编写复杂度变高,侵入性强,充斥着大量业务无关的代码
虽然是异步推送,但是总体看,还是要消耗宝贵的cpu内存网络资源,或者说跟核心应用争抢资源
字段(CN) | 字段(EN) | 示例 |
---|---|---|
强平流程日志id | liqFlowLogId | 123456 |
强平流程启动时间 | beginTime | 2022-03-02 18:00:00.000 |
强平流程总耗时 | duration | 纳秒,此时间为流程开始时间到流程彻底结束时间的差值 |
强平流程结束时间 | endTime | 该字段可省略,因为可通过强平流程启动时间和强平流程总耗时推断 |
账户Id | accountId | 12345678 |
保证金类型 | marginMode | 常规保证金RM 组合保证金PM 统一保证金UM |
强平模式 | liqMode | 常规强平=COMMON_LIQ, 人工接管=HANDLE_LIQ , 延迟爆仓=DELAY_LIQ |
强平触发原因 | cause | 行情价格反向波动事件 开仓平仓交割结束导致仓位变动事件 账户入金出金结束事件 杠杆变低结束事件 延时到期事件 |
强平流程执行前风险水位 | beforeLiqRiskLevel | MM_OVERFLOW_LEVEL |
强平流程执行前状态 | beforeLiqAccountStatus | OPTION_LIQ_SENT |
强平流程执行前chainName | beforeChainName | OPTION_LIQ_SENT,如果使用了literflow,填写该值 |
强平流程执行前运行的类名 | beforeClassName | OptionLiqCallBackCmp,如果使用了literflow,填写该值 |
强平流程执行前余额 | beforeMarginBalance | 1000.000 |
强平流程执行前净值 | beforeEquity | 1000.000 |
强平流程执行前初始保证金 | beforeIM | 0.0001 |
强平流程执行前维持保证金 | beforeMM | 0.0001 |
强平流程执行后风险水位 | afterLiqRiskLevel | MM_OVERFLOW_LEVEL |
强平流程执行前状态 | afterLiqAccountStatus | OPTION_LIQ_SENT |
强平流程执行后chainName | afterChainName | OPTION_LIQ_SENT,如果使用了literflow,填写该值 |
强平流程执行后运行的类名 | afterClassName | OptionLiqCallBackCmp,如果使用了literflow,填写该值 |
强平流程执行后余额 | afterMarginBalance | 1000.000 |
强平流程执行后净值 | afterEquity | 1000.000 |
强平流程执行后初始保证金 | afterIM | 0.0001 |
强平流程执行后维持保证金 | afterMM | 0.0001 |
返回码 | code | 0:执行成功,非0:执行失败 |
返回描述 | message | 比如异常详情 |
字段(CN) | 字段(EN) | 示例 |
---|---|---|
强平请求日志id | liqRequestLogId | 12345678910,相当于强平子流程id,和RequestId保持一致 |
强平请求的服务动作 | serviceName | ENTER_LIQ_PROCESS,相当于强平请求名称,相当于强平子流程名称,这个值在单次请求中是不会改变的 |
所属强平流程日志id | liqFlowLogId | 123456 |
强平请求开始时间 | beginTime | 2022-03-02 18:00:00.000000 |
强平请求总耗时 | duration | 纳秒,请注意,强平流程的耗时并非所有强平请求的耗时总和 因为中间每个强平请求之间需要等待回执时间, 这些时间不属于任何请求的时间,但属于强平流程的时间 |
强平请求结束时间 | endTime | 该字段可省略,因为可通过强平请求开始时间和强平请求总耗时推断 |
账户Id | accountId | 12345678 |
强平请求入参Json | requestBodyJson | {},回执参数或者从消息队列接收的消息 |
强平请求执行前步骤日志id | beforeLiqStepLogId | |
强平请求执行前步骤日志名称 | beforeLiqStepLogName | |
强平请求执行前风险水位 | beforeLiqRiskLevel | MM_OVERFLOW_LEVEL |
强平请求执行前强平账户当前状态 | beforeLiqAccountStatus | OPTION_LIQ_SENT |
强平请求执行前chainName | beforeChainName | OPTION_LIQ_SENT,如果使用了literflow,填写该值 |
强平请求执行前运行的类名 | beforeClassName | OptionLiqCallBackCmp,如果使用了literflow,填写该值 |
强平请求执行前余额 | beforeMarginBalance | 1000.000 |
强平请求执行前净值 | beforeEquity | 1000.000 |
强平请求执行前初始保证金 | beforeIM | 0.0001 |
强平请求执行前维持保证金 | beforeMM | 0.0001 |
强平请求执行前永续订单个数 | beforePerpOrderCount | 1 |
强平请求执行前永续仓位个数 | beforePerpPositionCount | 1 |
强平请求执行前期权订单个数 | beforeOptionOrderCount | 1 |
强平请求执行前期权仓位个数 | beforeOptionPositionCount | 1 |
强平请求出参Json | responseBodyJson | {},处理结果 |
强平请求执行后步骤日志id | afterLiqStepLogId | |
强平请求执行后步骤日志名称 | afterLiqStepLogName | |
强平请求执行后风险水位 | afterLiqRiskLevel | MM_OVERFLOW_LEVEL |
强平请求执行后强平账户当前状态 | afterLiqAccountStatus | OPTION_LIQ_SENT, |
强平请求执行后chainName | afterChainName | OPTION_LIQ_SENT,如果使用了literflow,填写该值 |
强平请求执行后运行的类名 | afterClassName | OptionLiqCallBackCmp,如果使用了literflow,填写该值 |
强平请求执行后余额 | afterMarginBalance | 1000.000 |
强平请求执行后净值 | afterEquity | 1000.000 |
强平请求执行后初始保证金 | afterIM | 0.0001 |
强平请求执行后维持保证金 | afterMM | 0.0001 |
强平请求执行后永续订单个数 | afterPerpOrderCount | 1 |
强平请求执行后永续仓位个数 | afterPerpPositionCount | 1 |
强平请求执行后期权订单个数 | afterOptionOrderCount | 1 |
强平请求执行后期权仓位个数 | afterOptionPositionCount | 1 |
返回码 | code | 0:执行成功,非0:执行失败 |
返回描述 | message | 比如异常详情 |
字段(CN) | 字段(EN) | 示例 |
---|---|---|
强平步骤日志id | liqStepLogId | 12345678910 |
强平步骤日志名称 | liqStepLogName | 权限判断步骤 延时爆仓步骤 初始化步骤 取消活动单步骤 安全降档步骤 有损降档部分减仓步骤 有损降档永续接管步骤 阶梯强平下平仓单步骤 阶梯强平转仓给做市商步骤 期权接管步骤 恢复步骤 |
所属强平流程日志id | liqFowLogId | 123456 |
强平步骤开始时间 | beginTime | 2022-03-02 18:00:00.000000 |
强平步骤总耗时 | duration | 纳秒,假如忽略literflow的耗时,强平流程的耗时基本上可等同所有步骤的耗时总和 |
强平步骤结束时间 | endTime | 该字段可省略,因为可通过强平步骤开始时间和强平步骤总耗时推断 |
账户Id | accountId | 12345678 |
强平步骤执行前强平请求id | beforeRequestId | 12345678 |
强平步骤执行前服务动作 | beforeServiceName | ENTER_LIQ_PROCESS |
强平步骤执行前风险水位 | beforeLiqRiskLevel | MM_OVERFLOW_LEVEL |
强平步骤执行前强平账户当前状态 | beforeLiqAccountStatus | OPTION_LIQ_SENT |
强平步骤执行前chainName | beforeChainName | OPTION_LIQ_SENT,如果使用了literflow,填写该值 |
强平步骤执行前运行的类名 | beforeClassName | OptionLiqCallBackCmp,如果使用了literflow,填写该值 |
强平步骤执行前余额 | beforeMarginBalance | 1000.000 |
强平步骤执行前净值 | beforeEquity | 1000.000 |
强平步骤执行前初始保证金 | beforeIM | 0.0001 |
强平步骤执行前维持保证金 | beforeMM | 0.0001 |
强平步骤执行前永续订单个数 | beforePerpOrderCount | 1 |
强平步骤执行前永续仓位个数 | beforePerpPositionCount | 1 |
强平步骤执行前期权订单个数 | beforeOptionOrderCount | 1 |
强平步骤执行前期权仓位个数 | beforeOptionPositionCount | 1 |
强平步骤执行后强平请求id | afterRequestId | 12345678 |
强平步骤执行后服务动作 | afterServiceName | ENTER_LIQ_PROCESS |
强平步骤执行后风险水位 | afterLiqRiskLevel | MM_OVERFLOW_LEVEL |
强平步骤执行后强平账户当前状态 | afterLiqAccountStatus | OPTION_LIQ_SENT, |
强平步骤执行后chainName | afterChainName | OPTION_LIQ_SENT,如果使用了literflow,填写该值 |
强平步骤执行后运行的类名 | afterClassName | OptionLiqCallBackCmp,如果使用了literflow,填写该值 |
强平步骤执行后余额 | afterMarginBalance | 1000.000 |
强平步骤执行后净值 | afterEquity | 1000.000 |
强平步骤执行后初始保证金 | afterIM | 0.0001 |
强平步骤执行后维持保证金 | afterMM | 0.0001 |
强平步骤执行后永续订单个数 | afterPerpOrderCount | 1 |
强平步骤执行后永续仓位个数 | afterPerpPositionCount | 1 |
强平步骤执行后期权订单个数 | afterOptionOrderCount | 1 |
强平步骤执行后期权仓位个数 | afterOptionPositionCount | 1 |
返回码 | code | 0:执行成功,非0:执行失败 |
返回描述 | message | 比如异常详情 |
字段(CN) | 字段(EN) | 示例 |
---|---|---|
强平过程中永续活动订单日志id | liqPerpOrderLogId | 12345678911 |
所属强平流程日志id | liqFowLogId | 123456 |
所属强平请求日志id | liqRequestLogId | 12345678 |
所属强平步骤日志id | liqStepLogId | 12345678910 |
账户Id | accountId | 12345678 |
永续活动订单id | orderId | 123456 |
方向 | side | buy/sell |
数量 | size | 0.01 |
挂单价格 | orderPrice | 45000.123 |
当前指数价 | indexPrice | 48000.123 |
该永续活动订单占用的初始保证金 | orderIM | 1000.000 |
字段(CN) | 字段(EN) | 示例 |
---|---|---|
强平过程中永续仓位日志id | liqPerpPositionLogId | 12345678912 |
所属强平流程日志id | liqFowLogId | 123456 |
所属强平请求日志id | liqRequestLogId | 12345678 |
所属强平步骤日志id | liqStepLogId | 12345678910 |
账户Id | accountId | 12345678 |
永续仓位id | poitionId | 123456 |
方向 | side | buy/side |
数量 | size | 0.01 |
仓位平均价 | avgPrice | 45000.134 |
当前指数价 | indexPrice | 48000.123 |
该永续仓位占用的初始保证金 | positionIM | 1000.000 |
该永续仓位占用的维持保证金 | positionMM | 1000.000 |
字段(CN) | 字段(EN) | 示例 |
---|---|---|
强平过程中期权活动订单日志id | liqOptionOrderLogId | 12345678911 |
所属强平流程日志id | liqFowLogId | 123456 |
所属强平请求日志id | liqRequestLogId | 12345678 |
所属强平步骤日志id | liqStepLogId | 12345678910 |
账户Id | accountId | 12345678 |
期权活动订单id | orderId | 123456 |
产品类型 | type | call/put |
方向 | side | buy/sell |
数量 | size | 0.01 |
挂单价格 | orderPrice | 1.123 |
当前指数价 | indexPrice | 1000 |
当前标记价 | markPrice | 1.456 |
该期权活动订单占用的初始保证金 | orderIM | 10.000 |
字段(CN) | 字段(EN) | 示例 |
---|---|---|
强平过程中期权仓位日志id | liqOptionPositionLogId | 12345678913 |
所属强平流程日志id | liqFowLogId | 123456 |
所属强平请求日志id | liqRequestLogId | 12345678 |
所属强平步骤日志id | liqStepLogId | 12345678910 |
账户Id | accountId | 12345678 |
期权仓位id | poitionId | 123456 |
产品类型 | type | call/put |
方向 | side | buy |
数量 | size | 0.01 |
仓位平均价 | avgPrice | 1.123 |
当前指数价 | indexPrice | 1000 |
当前标记价 | markPrice | 1.456 |
该期权仓位占用的初始保证金 | positionIM | 1000.000 |
该期权仓位占用的维持保证金 | positionMM | 1000.000 |
字段(CN) | 字段(EN) | 示例 |
---|---|---|
强平过程中RPC调用日志id | liqRpcInvokeLogId | 12345678911 |
强平过程中RPC调用日志名称 | liqRpcInvokeLogName | 可填写RPC中文名称 |
所属强平流程日志id | liqFowLogId | 123456 |
所属强平请求日志id | liqRequestLogId | 12345678 |
所属强平步骤日志id | liqStepLogId | 12345678910 |
RPC调用开始时间 | beginTime | 2022-03-02 18:00:00.000 |
RPC调用总耗时 | duration | 纳秒 |
RPC调用结束时间 | endTime | 该字段可省略,因为可通过RPC调用开始时间和RPC调用总耗时推断 |
账户Id | accountId | 12345678 |
rpc方法 | rpcMethod | com.xxx.xxx(),主要是永续,期权,资产相关接口,比如打钱 |
请求体json | requestBodyJson | {} |
返回码 | code | 0:执行成功,非0:执行失败 |
返回描述 | message | 比如异常详情 |
响应体json | responseBodyJson | {} |
字段(CN) | 字段(EN) | 示例 |
---|---|---|
强平过程中RPC被调用日志id | liqRpcInvokedLogId | 12345678911 |
强平过程中RPC被调用日志名称 | liqRpcInvokedLogName | 可填写RPC中文名称 |
所属强平流程日志id | liqFowLogId | 123456 |
所属强平请求日志id | liqRequestLogId | 12345678 |
所属强平步骤日志id | liqStepLogId | 12345678910 |
RPC被调用开始时间 | beginTime | 2022-03-02 18:00:00.000 |
RPC被调用总耗时 | duration | 纳秒 |
RPC被调用结束时间 | endTime | 该字段可省略,因为可通过RPC被调用开始时间和RPC被调用总耗时推断 |
账户Id | accountId | 12345678 |
rpc方法或ServiceAction | rpcMethod | com.xxx.xxx(),主要是CANCELED:期权取消活动单回执 LIQUIDATION:强平(期权交易回执),主要是仓位资产处理 PASS_THROUGH:透传(期权交易回执),主要是账户余额处理 TRADING_RESULT_LIQ_CONVERT:交易结果回执 PERP_LIQ_CANCEL_ORDER:永续取消开仓活动单回执 PERP_LIQ_POSITION_PART_LIQ_FILL:永续减仓降档成功回执 PERP_LIQ_POSITION_PART_LIQ_KILL:永续减仓降档失败回执 PERP_LIQ_POSITION_TAKE_OVER:永续仓位接管回执 |
请求体json | requestBodyJson | {} |
返回码 | code | 0:执行成功,非0:执行失败 |
返回描述 | message | 比如异常详情 |
响应体json | responseBodyJson | {} |
字段(CN) | 字段(EN) | 示例 |
---|---|---|
强平过程中消息队列发送日志id | liqMessageSendLogId | 12345678911 |
强平过程中消息队列发送日志名称 | liqMessageSendLogName | |
所属强平流程日志id | liqFowLogId | 123456 |
所属强平请求日志id | liqRequestLogId | 12345678 |
所属强平步骤日志id | liqStepLogId | 12345678910 |
发送时间 | sendTime | 2022-03-02 18:00:00.000 |
账户Id | accountId | 12345678 |
主题 | topic | AccountEvent |
消息体Json | bodyJson | {} |
字段(CN) | 字段(EN) | 示例 |
---|---|---|
强平过程中消息队列接收日志id | liqMessageRreceiveLogId | 12345678911 |
强平过程中消息队列接收日志名称 | liqMessageRreceiveLogName | |
所属强平流程日志id | liqFowLogId | 123456 |
所属强平请求日志id | liqRequestLogId | 12345678 |
所属强平步骤日志id | liqStepLogId | 12345678910 |
接收时间 | receiveTime | 2022-03-02 18:00:00.000 |
账户Id | accountId | 12345678 |
主题 | topic | AccountEvent |
分区 | partition | 0 |
偏移 | offset | 123456 |
消息体Json | bodyJson | {} |
字段(CN) | 字段(EN) | 示例 |
---|---|---|
强平过程中强平核心类方法调用日志id | liqMethodInvokeLogId | 12345678911 |
强平过程中强平核心类方法调用日志名称 | liqMethodInvokeLogName | |
所属强平流程日志id | liqFowLogId | 123456 |
所属强平请求日志id | liqRequestLogId | 12345678 |
所属强平步骤日志id | liqStepLogId | 12345678910 |
强平核心类方法执行开始时间 | beginTime | 2022-03-02 18:00:00.000 |
强平核心类方法总耗时 | duration | 纳秒 |
强平核心类方法执行结束时间 | endTime | 该字段可省略,因为可通过强平核心类方法执行开始时间和强平核心类方法总耗时推断 |
账户Id | accountId | 12345678 |
执行方法 | method | LiqStateMachineService#enterStateMachine |
入参Json | requestBodyJson | 如果没有参数,此字段为null, 如果只有1个参数,直接JsonUtil.toJson(XXX) 如果有多个参数,则{param1:XXX,param2:XXX}json格式表达 |
返回码 | code | 0:执行成功,非0:执行失败 |
返回描述 | message | 比如异常详情 |
出参Json | responseBodyJson | 如果没有参数,此字段为null, 如果只有1个参数,直接JsonUtil.toJson(XXX) |
字段(CN) | 字段(EN) | 示例 |
---|---|---|
强平流程统计统计id | id | 12345678911 |
统计维度 | dimension | 分钟:minute 小时:hour 每天:day 每周:week 每月:month 每年:year |
统计开始时间 | beginTime | 2022-03-02 00:00:00 |
统计结束时间 | endTime | 该字段可省略,因为可以从统计维度和统计开始时间推算出来 |
总次数 | totalCount | 分钟维度可通过定时任务统计, 其他维度可以以上一维度累加, 比如每小时,那么累加那一小时分钟维度的数据,累加60次即可, 同理天只需要累加24次,周只需要累加7次,月只需要累加当月天数 |
执行成功次数 | successCount | 必须使用统一的成功返回码,才能统计该字段 |
执行失败次数 | failCount | 必须使用统一的失败返回码,才能统计该字段 |
平均强平时间 | avgLiqTime | 单位为纳秒,统计方式和统计次数类似 |
最大强平时间 | maxLiqTime | 单位为纳秒,统计方式和统计次数类似 |
最小强平时间 | minLiqTime | 单位为纳秒,统计方式和统计次数类似 |
字段同上
字段同上
字段同上
字段同上
字段同上
字段同上
字段同上
字段同上
字段同上
字段同上
字段同上
字段同上
非强平主流程日志,主要是系统设置相关的日志,缺少它们,强平服务也能运转。
设置强平模式为常规模式/人工接管/延时爆仓接口日志
设置接管户接口日志
设置延时时长日志
人工接管接口日志
不影响强平流程,暂略
第一次进入状态机时,写入强平流程日志,主要写入这些字段
强平流程日志id
强平流程启动时间
账户Id
保证金类型
强平模式
强平流程执行前余额
强平流程执行前净值
强平流程执行前初始保证金
强平流程执行前维持保证金
强平流程执行前风险水位
//创建日志对象
LiqFlowLog liqFlowLog = new LiqFlowLog();
liqFlowLog.setLiqFlowLogId(new Snowflake(xxx).nextId());
liqFlowLog.setXXX(XXX);
liqFlowLog.setYYY(YYY);
//序列化成json写入对应的日志文件,方便es分析,方便prometheus统计
LiqLogConstant.LIQ_FLOW_LOG.info(new ObjectMapper().writeValueAsString(liqFlowLog));
流程结束时,更新强平流程日志,相比执行前日志,主要是新增了这些字段
强平流程日志id
强平流程总耗时
强平流程结束时间
账户Id
保证金类型
强平模式
强平流程执行后余额
强平流程执行后净值
强平流程执行后初始保证金
强平流程执行后维持保证金
强平流程执行后风险水位
返回码
异常详情
强平流程每个步骤执行前,写入强平步骤日志,主要写入这些字段
强平步骤日志id
所属强平流程日志id
强平步骤开始时间
账户Id
强平步骤执行前服务动作
强平步骤执行前余额
强平步骤执行前净值
强平步骤执行前初始保证金
强平步骤执行前维持保证金
强平步骤执行前强平账户当前状态
强平步骤执行前风险水位
当前chainName
当前运行的类名
强平流程步骤结束时,更新强平流程步骤日志,相比执行前日志,主要是新增了这些字段
强平步骤日志id
所属强平流程日志id
强平步骤总耗时
强平步骤结束时间
账户Id
强平步骤执行后服务动作
强平步骤执行后余额
强平步骤执行后净值
强平步骤执行后初始保证金
强平步骤执行后维持保证金
强平步骤执行后强平账户当前状态
强平步骤执行后风险水位
当前chainName
当前运行的类名
返回码
异常详情
报警阈值类型:
根据绝对值报警,比较给定值过高或过低即报警
根据相对值报警,根据环比,同比指标报警,根据历史数据及波动情况,来判断当前的波动是否为异常,从而避免过高的“底线”就会导致误报,过低的“底线”漏掉很多需要预警的情况
Tracing开发
功能上仿照springcoud的链路追踪方式,dashboard中自动还原强平流程图,
实现上仿照trace,span来进行流程跟踪,其中flowid充当traceid功能,stepid充当spanid的功能
分析日志,建立指标和flowid、stepid的关联关系
在报警发生时,通过指标查找到flowid和stepid,进而查找到所有log。
日志文件按照日期优先,大小第二的方式分割
程序异步批量写入日志后,日志由logstash准实时收集到es
保留24小时内的日志文件
删除24小时以前的日志文件
确保强平日志量不会撑满硬盘
每一个日志表对应的一个Logger,对应一个日志文件
对一些非主要环节的日志,在运行稳定后可进行关闭,节省IO
在收到关闭消息后,应用程序停止写入对应的日志文件
对一些不稳定的功能,或新上线的功能,可进行开启,便于定位问题排查问题
在收到开启消息后,应用程序源源不断的写入对应的日志文件
可关闭的日志,包括但不限于以下几类:
强平过程中永续活动订单日志表
强平过程中永续仓位日志表
强平过程中期权活动订单日志表
强平过程中期权仓位日志表
日志开闭方式:
通过Nacos配置更改通知日志开闭
通过运营系统或其他系统,向kafka发送开闭消息,应用程序监听到开闭消息进行开闭
日志开关开启时,应用程序写入对应的日志文件
日志开关关闭时,应用程序停止写入对应的日志文件
触发报警时自动尝试启动修复策略(自动尝试调用兜底方案)
启动修复策略前后发送通知
在容量估算前,先把强平服务的日志分为3个等级,并估算每种等级需要多少行日志
等级 | 日志类型 | 预估日志行数 | 预估日志行数算法 |
---|---|---|---|
必备 | 强平流程日志 强平步骤日志 |
10行 | 每一个强平流程会生成二行记录 一行是强平流程前状态, 另一行是强平流程后状态 每一个强平流程会包含平均4个强平步骤 每个步骤又会生成二行记录 一行是强平步骤执行前状态, 另一行是强平步骤执行后状态 2+4X2=10行 |
中等 | 强平过程中RPC调用日志 强平过程中RPC被调用日志 强平过程中消息队列发送日志 强平过程中消息队列接收日志 强平过程中核心类方法调用日志 |
40行 | 5种日志在每个步骤生成2行记录 4步骤x5种日志x2行=40 |
全量 | 强平过程中永续活动订单日志 强平过程中永续仓位日志 强平过程中期权活动订单日志 强平过程中期权仓位日志 |
80行 | 总共8种,每种以10个订单或仓位估算 8x10=80 |
启用不同等级和不同存储格式需要的存储空间:
Json格式存储,每行记录不超过200字节,如果csv格式存储,字段以逗号分割,每行记录存储空间比json格式减半,1G可以存储多一倍强平日志
存储等级 | json格式存储 | 1G可以存储的强平日志数量 |
---|---|---|
必备 | 10X200=2k | 1G/2k=50万个强平 |
必备+中等 | 10X200+40X200=10k | 1G/10k=10万个强平 |
必备+中等+全量 | 10X200+40X200+80X200=16k | 1G/26k=38000个强平 |
日志同步到es后,需要清理,假若每天清理一次,每次清理时把24小时前的日志清空,那么10G硬盘对付强平日志绰绰有余,因为即使全量存储,10G也可以存储38万个强平
为每种类型的日志定义专门的Logger,写入专门的日志文件,包括:
写入之前,在java程序中定义专门的日志对象,从审美和对称性角度看,面向对象比log.info随机定义占位符变量好看很多,比如:
在java对象中,重写toString方法
为每种类型的日志,打印日志文件,比如:
写入强平流程日志LiqLogConstant.LIQ_FLOW_LOG.info(liqFlowLog)
写入强平请求日志LiqLogConstant.LIQ_REQUEST_LOG.info(liqRequestLog)
写入强平步骤日志LiqLogConstant.LIQ_STEP_LOG.info(liqStepLog)
写入强平步骤执行中rpc调用日志LiqLogConstant.LIQ_RPC_INVOKE_LOG.info(liqRpcInvokeLog)
写入强平步骤执行中rpc被调用日志LiqLogConstant.LIQ_RPC_INVOKED_LOG.info(liqRpcInvokedLog)
写入强平步骤执行中消息队列发送日志LiqLogConstant.LIQ_MESSAGE_SEND_LOG.info(liqMessageSendLog)
写入强平步骤执行中消息队列接收日志LiqLogConstant.LIQ_MESSAGE_RECEIVE_LOG.info(liqMessageReceiveLog)
写入强平步骤执行中强平核心类方法调用日志LiqLogConstant.LIQ_METHOD_INVOKE_LOG.info(liqMethodInvokeLog)
写入非必要日志(运行中途可关闭),为每种类型的日志定义专门的Logger,写入专门的日志文件,包括:
任务 | 效果 | 时长 |
---|---|---|
写入强平流程日志 | 1日/人 | |
写入强平请求日志 | 2日/人 | |
写入强平步骤日志 | 2日/人 | |
写入强平过程中rpc调用日志 | 3日/人 | |
写入强平过程中rpc被调用日志 | 3日/人 | |
写入强平过程中消息队列发送日志 | 2日/人 | |
写入强平过程中消息队列接收日志 | 2日/人 | |
写入强平过程中强平核心类方法调用日志 | 3日/人 | |
配置开发测试预生产环境悟空监控和grafana监控 | 5日/人 | |
配置生产环境悟空监控和grafana监控 | 1日/人 | |
定时删除24小时以前日志 | 1日/人 | |
运行两周后,发现稳定则删除以前代码中的日志 | 1日/人 | |
代码评审 | 1日/人 | |
全程解答疑问 | 2日/人 | |
优化完善文档 | 2日/人 |
30人日,3人投入,为期2周
其中1人为负责人:编写文档,优化完善文档,解答疑问,检查任务进度
另外两人为开发:严格按照文档参与编码,第一周完成日志埋点,第二周进行metric配置
结对编程,两个开发每天编码完成后,下班前审查对方的完成质量
强平的关键日志数据有哪些?
能影响强平流程推进的数据都可认为关键日志数据,包括强平流程启动前的系统配置项。
编写单元测试需要的数据可认为是关键日志数据。
静态跟踪代码需要的数据可认为是关键日志数据。
出问题后让开发和运维从容面对说明存在完整的关键日志数据
出问题后让开发和运维手忙脚乱慌张不安说明缺少关键日志数据
日志埋点方案打算解决什么问题?
解决强平安稳中“强平流程状态不一致”,“强平流程停滞不推进”,“强平运维监控能力较弱”,“metric反查日志困难”等问题。
得到完整的关键的强平流程日志数据后,也为典型流程完善,单元单元测试编写,系分文档完善做好准备。
开展其他安稳工作,比如定期出强平安稳报表。
为什么发现问题和解决问题需要依赖日志?
强平的触发因素有很多,包括行情价格反向波动事件,开仓平仓交割结束导致仓位变动事件,账户入金出金结束事件,杠杆变低结束事件,延时到期事件。
影响强平的因素还包括保证金类型,风险类型,订单类型,仓位类型,成交方向等。
仅靠静态分析代码和现有文档很难确定上下文是否符合需求文档。很难定位排查问题。
最好的方式就是抓取完整的关键日志。
为什么不直接改造现有日志,而是重新日志埋点?
现有代码,现有日志,现有文档已经研读多次,能简单跟踪的强平流程也跟踪了,能简单画的图也画了,能发现的问题也提出来了
如果继续死磕,可能还是发现不了有价值的新问题,投入产出比不高
如果现有日志改造,只能从代码出发,从下而上,改造难度非常大,一不小心,就会脱离需求,掉进坑里面长时间爬不出来。
从代码库提交记录可以看出,现有代码日志已经改造多次,但无济于事,或者解决完这个问题,另外一个问题又冒出来,感觉就是问题永远解决不完
现有日志改动可能会影响开发环境,测试环境,生产环境,包括查询规则和已经配置好的监控报警
新的日志埋点方案,从需求出发,制订规范,把影响强平流程状态,影响强平推进的因素都考虑进来,更加容易发现新问题,解决不符合需求的问题。
新的日志埋点方案,不改动原有代码逻辑,原有日志方案还可以继续使用,可以动态关闭,甚至发现完问题不需要后可删除,影响面更小,试错成本低。
新的日志埋点不但会解决背景介绍列出的所有问题,还会更方便将来开展其他安稳工作。
新的日志埋点方案除了解决流程状态问题,怎么定期出安稳报告?
以测试环境为例:压力测试–>收集关键日志–>统计日志->监控报警
以生产环境为例:定期巡检–>收集关键日志–>统计日志->监控报警