• springboot实战(五)之sql&业务日志输出,重要


    目录

    环境:

    一、mybatis-plus之sql分析日志输出

    1.配置

     2.验证

    3.高级输出方式

    二、业务日志输出到文件

    1.添加log4j2依赖

    2.排除logback依赖

    3.新增log4j2的配置文件

    4.添加配置

    5.启动测试

    6.给日志请求加个id

    6.1、过滤器filter实现

    6.2、测试

    6.3、request_id检索方式

    7.结束


    环境:

    jdk:1.8

    springboot版本:2.7.15

    mybatis-plus版本:3.5.3.2

    一、mybatis-plus之sql分析日志输出

    为了生产中更快的分析问题以及解决问题,sql输出是非常有必要的,这里第一步是将sql输出到控制台便于调试时分析问题,优化sql

    1.配置

    日志输出操作很简单,在application.yml中配置:

    1. mybatis-plus:
    2. configuration:
    3. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

     2.验证

    使用测试类进行测试,注意,本地调试可以使用这种方式打开日志,如果线上日志输出到文件,要用下面的高级输出方式

    3.高级输出方式

    使用数据库操作分析框架p6spy组件,进行sql分析,但是该组件比较消耗性能,生产环境中不建议使用,但是如果想玩玩的话,大家可以试试。

    p6spy快速配置:p6spy快速配置

    二、业务日志输出到文件

    为什么要进行日志输出呢?

    因为生产环境想要知道程序是否是按照我们的意愿正常运行的,通过日志输出是最直观最有效的方式。

    日志文件输出我们一般常用日志输出框架有两种:一种是log4j2、另一种是logback。而springboot中默认使用的是logback框架,考虑到性能原因大多数生产环境使用日志框架为log4j2,所以这里也以log4j2框架进行整合和练习。

    1.添加log4j2依赖

    1. org.springframework.boot
    2. spring-boot-starter-log4j2
    3. com.fasterxml.jackson.dataformat
    4. jackson-dataformat-yaml

    为何用jackson-dataformat-yaml包?问就是可读性好~,log4j2官方采用的是.xml,.json或者.jsn这种方式来做配置,我们既然使用了springboot那当然要用yml文件来配置了,而这个包就是为了程序启动时辨认log4j2-*.yml文件的。

    2.排除logback依赖

    1. org.springframework.boot
    2. spring-boot-starter-logging
    3. *
    4. *

    3.新增log4j2的配置文件

    1. Configuration:
    2. #Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出
    3. #日志级别以及优先级排序: ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
    4. status: info
    5. # 定义全局变量
    6. Properties:
    7. Property:
    8. #日志存放路径
    9. - name: log.path
    10. value: /Users/liuph/dev/space/log/iterge_pre
    11. #定义日志输出目的地,内容和格式等
    12. Appenders:
    13. # 控制台日志
    14. Console:
    15. name: console
    16. target: SYSTEM_OUT
    17. #输出日志的格式
    18. PatternLayout:
    19. Pattern: "[%X{request_id}] %-d{yyyy-MM-dd HH:mm:ss} - [%p] [%C{1}:%L %M] %m%n"
    20. ThresholdFilter:
    21. level: info
    22. onMatch: ACCEPT
    23. onMismatch: DENY
    24. # 文件日志
    25. RollingFile:
    26. - name: iterge_pre
    27. #日志存储路径
    28. fileName: "${log.path}/info.log"
    29. #历史日志封存路径 其中%d{yyyy-MM-dd}表示了日志的时间单位是天
    30. filePattern: "${log.path}/iterge_pre_%d{yyyy-MM-dd}.log"
    31. PatternLayout:
    32. Pattern: "[%X{request_id}] %-d{yyyy-MM-dd HH:mm:ss} - [%p] [%C{1}:%L %M] %m%n"
    33. #归档设置
    34. Policies:
    35. #按时间间隔归档
    36. TimeBasedTriggeringPolicy:
    37. #时间间隔 单位由filePattern的%d日期格式指定, 此处配置代表每一天归档一次
    38. interval: 1
    39. #是否对interval取模,决定了下一次触发的时间点
    40. modulate: true
    41. #按照日志文件的大小: size表示当前日志文件的最大size,支持单位:KB/MB/GB
    42. #SizeBasedTriggeringPolicy:
    43. #size: 50MB
    44. ThresholdFilter:
    45. level: info
    46. onMatch: ACCEPT
    47. onMismatch: DENY
    48. Loggers:
    49. Root:
    50. level: info
    51. #关联的Appender, 只有定义了logger并引入的appender,appender才会生效
    52. AppenderRef:
    53. - ref: console
    54. - ref: iterge_pre

    4.添加配置

    在配置文件中添加需要生效的log4j2的配置信息,我这里生效的配置文件是application-dev.yml,所以我在application-dev.yml中加入以下配置代码:

    1. #这里配置日志生效文件,用于多环境部署时切换(通常部署会有三个环境:线上、测试、开发)
    2. logging:
    3. config: classpath:log4j2/log4j2-dev.yml

    项目配置文件目录:

    5.启动测试

    如上图:日志打印格式已经按照我们配置的打印了,这里大家可能问这个“[]”是什么含义?接着往下看。

    6.给日志请求加个id

    为什么给日志请求加个id?这里当然是为了方便了,举个例子:当你在线上查询问题时,一段代码你你可能加了10个日志输出点,而线上业务日志又有很多的情况下,你难道要一行一行的检索日志来看吗?这时候当然请求id检索更香啊!

    6.1、过滤器filter实现

    新建过滤器LogTraceFilter,代码中的“request_id”要和log4j2的配置文件中设置的一致!!!

    (这里通过拦截器实现也是可以的)

    1. @WebFilter(filterName = "LogTraceFilter", urlPatterns = "/*")
    2. @Component
    3. public class LogTraceFilter implements Filter {
    4. @Override
    5. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    6. MDC.put("request_id", UUID.randomUUID().toString().replace("-", ""));
    7. filterChain.doFilter(servletRequest, servletResponse);
    8. MDC.remove("request_id");
    9. }
    10. }

    6.2、测试

    controller代码:

    1. @GetMapping("/test/get")
    2. public User getUser(Integer id){
    3. log.info("请求入参:{}",id);
    4. User user = userMapper.selectById(id);
    5. log.info("请求结果:{}",user.getName());
    6. log.info("你看,这样很明显知道我们是一次请求的log吧!");
    7. return user;
    8. }

    运行结果: 

    由此可以看出同一个请求的日志id都是相同的。

    6.3、request_id检索方式

    7.结束

  • 相关阅读:
    PyQt5页面跳转问题及解决方式
    js算法之旅:枚举
    un7.28:如何将项目打包到Linux虚拟机中并成功运行(上)?
    【POJ】1050.To the Max (最大子矩阵和)
    七 R语言|箱须图、饼图的绘制
    Java8 parallerStream导致Spring项目启动线程阻塞(死锁)
    机器学习第10天:集成学习
    密码学算法都是怎样实现的? 都有哪些实现方式?
    linux系统宝塔服务器temp文件夹里总是被上传病毒php脚本
    嵌入式分享合集49
  • 原文地址:https://blog.csdn.net/it_erge/article/details/132670246