如何让日志记录变得丝滑

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

相关文章

SpringBoot日志级别与日志分组详解

《SpringBoot日志级别与日志分组详解》文章介绍了日志级别(ALL至OFF)及其作用,说明SpringBoot默认日志级别为INFO,可通过application.properties调整全局或... 目录日志级别1、级别内容2、调整日志级别调整默认日志级别调整指定类的日志级别项目开发过程中,利用日志

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

java -jar example.jar 产生的日志输出到指定文件的方法

《java-jarexample.jar产生的日志输出到指定文件的方法》这篇文章给大家介绍java-jarexample.jar产生的日志输出到指定文件的方法,本文给大家介绍的非常详细,对大家的... 目录怎么让 Java -jar example.jar 产生的日志输出到指定文件一、方法1:使用重定向1、

c++日志库log4cplus快速入门小结

《c++日志库log4cplus快速入门小结》文章浏览阅读1.1w次,点赞9次,收藏44次。本文介绍Log4cplus,一种适用于C++的线程安全日志记录API,提供灵活的日志管理和配置控制。文章涵盖... 目录简介日志等级配置文件使用关于初始化使用示例总结参考资料简介log4j 用于Java,log4c

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

nginx配置错误日志的实现步骤

《nginx配置错误日志的实现步骤》配置nginx代理过程中,如果出现错误,需要看日志,可以把nginx日志配置出来,以便快速定位日志问题,下面就来介绍一下nginx配置错误日志的实现步骤,感兴趣的可... 目录前言nginx配置错误日志总结前言在配置nginx代理过程中,如果出现错误,需要看日志,可以把

基于Spring Boot 的小区人脸识别与出入记录管理系统功能

《基于SpringBoot的小区人脸识别与出入记录管理系统功能》文章介绍基于SpringBoot框架与百度AI人脸识别API的小区出入管理系统,实现自动识别、记录及查询功能,涵盖技术选型、数据模型... 目录系统功能概述技术栈选择核心依赖配置数据模型设计出入记录实体类出入记录查询表单出入记录 VO 类(用于

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)

《java中pdf模版填充表单踩坑实战记录(itextPdf、openPdf、pdfbox)》:本文主要介绍java中pdf模版填充表单踩坑的相关资料,OpenPDF、iText、PDFBox是三... 目录准备Pdf模版方法1:itextpdf7填充表单(1)加入依赖(2)代码(3)遇到的问题方法2:pd

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499