写点什么

写一个无配置格式统一的日志

  • 2020-02-11
  • 本文字数:3515 字

    阅读完需:约 12 分钟

写一个无配置格式统一的日志

背景

大量项目在使用 logback 记日志,有部分项目使用日志混乱,格式不统一,多数人搞不懂配置文件,导致配置错误,现在需要开发一套统一的、少配置的日志组件,使用方便

设计思路

  • 尽量采用 0 配置,无 logback.xml

  • 日志格式统一,方便后续日志分析系统

  • 只有两个日志级别,一个是正常日志,一个是异常日志

  • 提供 log4j、jcl、logback、commons-log 等桥接方案及版本兼容方案

  • 提子线程、json 格式化输出、map 格式化、数组格式化、请求响应参数(供耗时)等便捷日志输出方法

  • 支持 redis、db、http 自动开关配置****

  • 新增日志类型(logger)

  • api 采用流式结构,类似 StringBuffer

  • 概要设计

    零配置


  • 调研代码


上面代码等价于下面的 xml


                    %d{MMddHHmmss.SSS} [%thread] %-5level %logger{36} - %msg%n
复制代码


由此可以随意把配置文件中的内容以代码形式编写,理论已经可以实现 0 配置。

输出路径

约定固定将日志输出到,相对路径 log/xxx.yyyy-MM-dd-HH.log,其中 xxx 为 logger 的 name

日志格式

格式固定:MMddHHmmss.SSS||id||【交易名★子步骤】||context ||[level][线程号]例:150000.311||N-XrUTQzIc1531897200311||【CiTeeFilter★ci拦截器】||ci拦截器 请求的完整参数为:{"merchantId":["0012444"],"userId":["13112341232"]} ||[INFO][http-8091-7]
复制代码


固定格式的核心代码,拦截到日志请求,按照格式拼装,主要方法为继承 ThrowableProxyConverter 和 MessageConverter 来实现对日志的拦截,并修改为想要的格式,其中使用的例如 id 等放到本地变量内,核心是对 MDC 的使用

基础 logger

所有日志都默认输出到这里 logger name:service 系统初始化时,定义这个 Logger 和 appender,即这个 Logger 为 root log

自定义的 logger

提供 addLogger 方法,参数 packageName 包名,例如:com.test 必输参数 如果 name 未设置时,name 默认为包名最后一个.后面的字符 name 名字,决定日志文件的名字 非必输 path 日志路径 非必输 additivity 是否输出到 root log 内

特殊的 log

提供特殊组件的 log 配置,例如: redis 默认 ERROR http 默认 ERROR db 连接池 默认 ERROR kafka 默认 ERROR schedul 默认 ERROR spring 默认 ERROR

异常、换行日志处理

提供 exception 异常栈格式打印 提供带换行的格式化打印 代码思路:继承 ThrowableProxyConverter,获取异常栈,在每行的前面插入固定格式文本

普通日志 api(VirgoLog)

方法方法描述
setUniqKey(id)设置当前线程id,线程开始时设置即可,后面无需设置
updateStep(trade, step)更新当前id的步骤信息
log(msg, param)记录普通日志,msg替换规则,普通替换为{},如果想替换为业务日志api中的格式,使用``替换
logErr(msg, e)记录异常日志
log( trade, step, msg, param)记录普通日志,此方法会自动更新id、trade、step,不建议使用
logErr(trade, step, msg, e)记录异常日志
log(cid, trade, step, msg, param)记录普通日志,此方法会自动更新id、trade、step,不建议使用
logErr(cid, trade, step, msg, e)记录异常日志
debug(msg, param)记录debug级别日志,不建议使用

业务日志 api(VirgoLog)

平时记日志时,如果某个类没有时间 toString 方法,会无法正确打印出数据,此时提供替换方法,直接将 object 替换为 json 打印,核心代码思路为


MessageFormatter 是处理{}替换的类,重新写个类,稍加改动即支持{}也支持`` ,并判断替换为 json 还是 toString


api 如下


方法方法描述
begin(msg)记录开始
end(msg)记录完成,会打印本线程内上一个begin到现在的耗时
logJson(json, format)记录json格式化日志,format表示是否换行
logMap(map, format)记录map格式化日志
logCollection(list, format)记录集合格式化日志
logArray(array, format)记录数组格式化日志
logObjct(obj, format)记录Object格式化日志

系统 api(LoggerHelper)

方法方法描述
getLogger()获取logger,用于记日志
getLogger(name)通过name获取logger
addLogger()参考自定义Logger,如果logger已经创建,则不再创建,一般不使用,除非想自定义日志名等
consoleOpen()打开控制台日志,系统启动时默认配置控制台日志
commonOpen(name, level)默认的组件都是error级别,这个方法可以变更日志级别,例如redis http等

特殊的格式化

map:即转化为 json,然后再格式化


collection:同上


array:也同上


object:同上

问题

1、密码脱敏、加解密有必要单独提取方法吗


2、提供父线程打印开关

maven 依赖

                    com.cdc.ecliptic            virgo            1.5_1.6-SNAPSHOT
复制代码

demo

public static void main(String[] args) throws InterruptedException {
// 启动 VirgoLancher.start("hahaha", "com.cdc.virgo", "D:/test/hahah.log"); LoggerHelper.commonOpen("hahaha", LogLevel.DEBUG); Logger logger1 = LoggerFactory.getLogger("druid");// VirgoLancher.commonStart("abc", "com.cdc.virgo"); // 打开控制台 LoggerHelper.consoleOpen(); // 设置cid VirgoLog.setUniqKey(null); // 设置步骤名和交易名 VirgoLog.updateStep("adfa", "saf"); // 获取Logger VirgoLog logger = VirgoLog.getLogger();
// 打开debug级别(只有在开发阶段可以打开)// logger.changeLevel(LogLevel.DEBUG); // 记录换行 logger.log("a");
logger1.info("dddddddddd"); logger1.error("dddddddddd");
// logger1.info("sfdasfaf" +// "\nafafdasfd" +// "\nasfdasf"); logger.log("sfdasfaf" + "\nafafdasfd" + "\nasfdasf");
// logger1.info("b"); // 正常日志// logger.log("我只有一行"); Map map = new HashMap(); map.put("asdf", "1"); map.put("asdf2", "2"); map.put("asdf3", "13"); map.put("asdf4", "14"); map.put("asdf5", "15"); map.put("asdf6", "16");// // 异常日志也支持格式化// logger.logErr("我错了:{},你没错:~~", new Exception("asdfsaflk"), "啊", map);// logger.log("----------------------------------------------");// // {}替换普通对象,调用toString() ~~把对象转换为json并且格式化输出 ``把对象转换为json不格式化输出 logger.log("你好{},你是谁~~``,sd~xx {}", map, map, map, "tttt"); VirgoLog.updateStep("saf2");// // 把对象转换为json输出// logger.logJson(map, false);// // 更新步骤名和交易名// VirgoLog.updateStep("bbbbb", "ccccc");// // 耗时日志打印 logger.begin("处理内容"); logger.begin("处理第二个"); logger.begin("处理第三个"); Thread.sleep(3000L); logger.end(); Thread.sleep(1000L); logger.end(); VirgoLog.updateStep("saf3"); logger.end();// // 记录debug日志,一般调试用// logger.logDebug("jajajajaja");
// List l = new ArrayList();// B b = new B();// try {// b.b();// } catch (Exception e) {// logger.logErr("woqu", e);// }
复制代码


本文转载自宜信技术学院网站。


原文链接:http://college.creditease.cn/detail/206


2020-02-11 20:191011

评论

发布
暂无评论
发现更多内容

使用 NineData 高效编写 SQL

NineData

数据库 sql 数据库开发 数据管理工具 NineData

一个词语总结2022,你的是什么? | 2022 年度总结

陈言必行

2022年终总结

ShardingSphere分库分表schema名称导致NPE问题排查记录

小小怪下士

Java 程序员 后端

行业分析| 交通综合执法对讲系统

anyRTC开发者

指挥调度 快对讲 语音对讲 视频对讲 综合执法

云图说 | Workflow:流水线工具,助您高效完成AI开发

华为云开发者联盟

人工智能 华为云 AI开发 企业号 1 月 PK 榜

React源码分析6-hooks源码

flyzz177

React

React源码分析5-commit

flyzz177

React

Java高手速成 | 高质量代码编写最佳实践

TiAmo

编程好习惯 设计原则 Java’

一文总结ACE代码框架

OpenHarmony开发者

OpenHarmony

带你认识数仓的增量备份核心设计

华为云开发者联盟

数据库 后端 华为云 数仓 企业号 1 月 PK 榜

Git操作不规范,战友提刀来相见!

王中阳Go

golang git 深度思考 高效工作 学习方法

《金融电子化》:隐私计算赋能银行助贷业务自主风控 | 华夏银行×洞见科技

洞见科技

隐私计算 风控

信用卡APP评测系列:科技赋能信用卡APP创新升级,助力客户体验提升

易观分析

金融 信用卡

微服务的版本号要怎么设计?

江南一点雨

微服务 语义化

甩掉容量规划炸弹:用 AHPA 实现 Kubernetes 智能弹性伸缩

阿里巴巴中间件

阿里云 Kubernetes 云原生 AHPA

赞赞赞!融云收获行业媒体「组团打 Call」

融云 RongCloud

Serverless 奇点已来,下一个十年将驶向何方?

Serverless Devs

ISV生态合作伙伴体系多领域赋能,开拓市场赛道

元年技术洞察

数据中台 数据 数字化转型 ISV 方舟平台

ClickHouse 挺快,esProc SPL 更快

陈橘又青

重磅发布丨从云原生到 Serverless,先行一步看见更大的技术想象力

Serverless Devs

公共服务 智慧政务数据可视化大屏一体化系统

2D3D前端可视化开发

数据可视化 数字政务 智慧政务 数字政府 可视化大屏

一次JVM GC长暂停的排查过程

京东科技开发者

Java 后端 JVM 虚拟机 企业号 1 月 PK 榜

二维码的秘密

古时的风筝

二维码 二维码生成

视频实时自然美颜, 无惧素颜上镜

HarmonyOS SDK

HMS Core

为什么网络I/O会被阻塞

华为云开发者联盟

后端 开发 华为云 企业号 1 月 PK 榜

React源码分析7-state计算流程和优先级

flyzz177

React

LogicFlow安装与准备工作

小鑫同学

前端 vite Vue 3 Vue3 Typescript

Postgresql分析慢sql

查拉图斯特拉说

数据库 postgresql db PgSQL PG库

如何把 高并发限流 实现的那叫一个优雅!

风铃架构日知录

Java 程序员 高并发 IT 限流

一次关于 MySQL 主从模式采用 GTID 的实践记录

风铃架构日知录

Java MySQL IT 主从复制 MySQL 数据库

关于 Serverless 应用架构对企业价值的一些思考

Serverless Devs

写一个无配置格式统一的日志_文化 & 方法_刘鹏飞_InfoQ精选文章