如何让日志记录变得丝滑

2023-11-23 12:08
文章标签 日志 记录 变得 丝滑

本文主要是介绍如何让日志记录变得丝滑,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

操作日志在每一个系统中都普遍存在,系统中都有一套自己记录日志的API与之想配套。而对于不同的系统日志又不近相同。大体可以分为两类:

  • 系统日志

    主要用于开发者问题排查和一些信息打印方便调试和问题排查的日志。打印在日志文件中

  • 业务日志

    有一定的业务规则,给业务人员进行查看的日志。这一类日志要求简单易懂(可能还设计一些日志的模板,不同类型的业务需要不同的模板)。打印在日志文件同时也需要进行数据库的持久化以便运营人员和关联人员的查看等等。

不管是系统日志还是业务日志,主要的作用就是用来记录操作的信息给需要的人进行查看。今天就来说一下在工作中如何优雅的记录日志。

Tips:主要讲解业务日志如何记录

业务日志记录流程图.png

1. 业务日志如何优雅的记录

针对不同的业务需要记录不同的内容,同时不同业务也有相同的东西。所以需要分析出共性和差异内容。基于自己的工作来看一下如何设计。

1.1 日志需要记录哪些东西

  • 操作人(操作用户一般记录ID和名称)
  • 操作人终端IP地址(可以用于风控和一些智能推荐)
  • 操作终端相关信息(可选根据不同公司和业务需求)
  • 操作时间(这个比较重要)
  • 操作类型(删除、查询、更新等等--根据需求进行个性化设计)

上面这些都是通用的,绝大多数业务都可以用的到。也基本上相同。但是对于业务操作日志最重要的是把业务的内容记录下来。这里就是我们通常说的业务模板

  • 业务模板

    业务模板需要根据不同的业务进行定制,在定制过程中可能还需要进行动态加载等等。例如:**123用户2021-09-16 10:00 订单创建,订单号:NO.88888888**在订单信息中可能还包含了用户信息时间以及订单信息等等。这种是比较复杂的业务模板

日志模板格式其实还可以自定义如下格式:文件中一行作为一条记录,用分隔符进行分割。在读取的时候回按一行进行读取然后进行分隔符分割,每一个位置固定是一个约定好的内容。(这种格式之前在做游戏服务器日志记录的时候就是采用这种)。

优点:就是格式固定解析起来方便,也便于后续的数据处理以及表格的呈现。

缺点:不能直观的表达内容。需要处理加工后才能知道表达什么。

1.2 静态实现方式

1.2.1 Canal监听数据库操作日志

Canal 是一款基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费的开源组件,通过采用监听数据库 Binlog 的方式,这样可以从底层知道是哪些数据做了修改,然后根据更改的数据记录操作日志。

优点:对代码没有侵入和业务逻辑完全分离。

缺点:只能记录操作数据库的操作,并且记录的字段只能是表中包含的字段,例如我想记录一下操作人的IP地址就没办法。

1.2.2 Java框架日志记录文件中

log.info("用户登录")
log.info("用户{},ip地址{}登出“,userId,ip)
复制代码

Tips:常用的日志Java日志工具:

  • log4j
  • log4j2
  • logback

这种记录有几个问题:

问题1: 用户ID和ip地址如何获取?

借助 SLF4J 中的 MDC 工具类,把操作人放在日志中,然后在日志中统一打印出来。首先在用户的拦截器中把用户的标识 Put 到 MDC 中:

public class UserInterceptor implements AsyncHandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {//获取到用户标识String userId = getUserId(request);//把用户 ID 放到 MDC 上下文中MDC.put("userId", userId);MDC.put("ip", request.getRemoteAddr());return AsyncHandlerInterceptor.super.preHandle(request, response, handler);}private String getUserId(HttpServletRequest request) {// 通过 SSO 或者Cookie 或者 Auth信息获取到 当前登陆的用户信息return null;}
}
复制代码

其次,把 userId,ip格式化到日志中,使用 %X{userId} ,%X{ip}可以取到 MDC 中用户标识。

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level  %X{userId}  %X{ip} %logger{50} - %msg%n</pattern>
复制代码

问题2: 如何生成可读性的日志

针对每一个业务在代码中写成对应的日志模板。写到日志文件中。然后通过日志收集工具将日志收集到Elasticsearch或者数据库当中。

1.3 动态日志实现方式

为了解决上面的问题,一般采用AOP的方式记录操作日志和业务逻辑的解耦。下面来看一下:

@Service
public class UserServiceImpl {@Log(template = "新增用户-名称为:${#user.name}  用户地址:${#user.address}, " + "年龄:${#user.age}, 用户的信息:${@userServiceImpl.getUserInfo(#user)}")public boolean addUser(User user){StringBuilder sb = new StringBuilder();Random random = new Random();for(int i = 0; i < 30000; ++i){sb.append(random.nextInt());}return true;}public String getUserInfo(User use){return use.toString();}}
复制代码

这里记录日志实现的是一个静态,通过AOP的方式来实现的。那么如何实现动态模板,就会涉及到让变量通过占位符的方式解析模板,从而达到通过注解记录操作日志的目的。模板解析的方式有很多种。Java使用者用的最多的框架就是Spring, 这里实现我们也使用SpEL(Spring Expression Language,Spring表达式语言)来实现。

需要实现的功能设想,已最常用的用户在电商网站购买商品创建购买订单为例子:

业务日志模板: 用户[xxx]在[xxxx时间]购买了[xxxx商品],用户的所使用的终端为[xxxxx,ip地址为],操作类型:[xxxx]

1.4 模块介绍

动态日志功能模块.png

主要分为三大功能:

  1. 日志AOP拦截模块

    主要用于处理用户的日志拦截的切入点

  2. 日志解析模块

    提供了对动态模板的解析,生成最终业务需要的模板具体实例数据

  3. 日志存储模块

    存储主要是为了提供给后续使用这个查询

1.5 代码实现模块

从代码的实现上来说主要分成一下几个步骤:

  • AOP拦截逻辑
  • 日志解析逻辑
    • 模板解析
    • 日志上下文实现
    • 公共字段处理逻辑
    • 自定义函数的处理逻辑(调用某个类的方法)
  • 日志持久化逻辑
    • 默认持久化(现在是Java日志持久化到本地文件)
    • 持久化的方式(文件还是数据库),同步还是异步模式
  • 项目如何进行集成(Spring start开发)

项目实现.png

主要使用了Spring的AOP和Spel来实现动态日志记录功能。直接可以使用Spel表达式来。

项目github地址:github.com/mxsm/mxsm-l…

这篇关于如何让日志记录变得丝滑的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/417835

相关文章

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

Python UV安装、升级、卸载详细步骤记录

《PythonUV安装、升级、卸载详细步骤记录》:本文主要介绍PythonUV安装、升级、卸载的详细步骤,uv是Astral推出的下一代Python包与项目管理器,主打单一可执行文件、极致性能... 目录安装检查升级设置自动补全卸载UV 命令总结 官方文档详见:https://docs.astral.sh/

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

统一返回JsonResult踩坑的记录

《统一返回JsonResult踩坑的记录》:本文主要介绍统一返回JsonResult踩坑的记录,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录统一返回jsonResult踩坑定义了一个统一返回类在使用时,JsonResult没有get/set方法时响应总结统一返回

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

java对接海康摄像头的完整步骤记录

《java对接海康摄像头的完整步骤记录》在Java中调用海康威视摄像头通常需要使用海康威视提供的SDK,下面这篇文章主要给大家介绍了关于java对接海康摄像头的完整步骤,文中通过代码介绍的非常详细,需... 目录一、开发环境准备二、实现Java调用设备接口(一)加载动态链接库(二)结构体、接口重定义1.类型

Golang 日志处理和正则处理的操作方法

《Golang日志处理和正则处理的操作方法》:本文主要介绍Golang日志处理和正则处理的操作方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录1、logx日志处理1.1、logx简介1.2、日志初始化与配置1.3、常用方法1.4、配合defer

Apache 高级配置实战之从连接保持到日志分析的完整指南

《Apache高级配置实战之从连接保持到日志分析的完整指南》本文带你从连接保持优化开始,一路走到访问控制和日志管理,最后用AWStats来分析网站数据,对Apache配置日志分析相关知识感兴趣的朋友... 目录Apache 高级配置实战:从连接保持到日志分析的完整指南前言 一、Apache 连接保持 - 性

apache的commons-pool2原理与使用实践记录

《apache的commons-pool2原理与使用实践记录》ApacheCommonsPool2是一个高效的对象池化框架,通过复用昂贵资源(如数据库连接、线程、网络连接)优化系统性能,这篇文章主... 目录一、核心原理与组件二、使用步骤详解(以数据库连接池为例)三、高级配置与优化四、典型应用场景五、注意事

Nacos日志与Raft的数据清理指南

《Nacos日志与Raft的数据清理指南》随着运行时间的增长,Nacos的日志文件(logs/)和Raft持久化数据(data/protocol/raft/)可能会占用大量磁盘空间,影响系统稳定性,本... 目录引言1. Nacos 日志文件(logs/ 目录)清理1.1 日志文件的作用1.2 是否可以删除