Springboot中如何记录好日志

Springboot中如何记录日志

日志体系整体介绍

日志一直在系统中占据这十分重要的地位,他是我们在系统发生故障时用来排查问题的利器,也是我们做操作审计的重要依据。那么如何记录好日志呢?选择什么框架来记录日志,是不是日志打越多越好,带着这些问题我们今天一起来讨论下springboot应用如何记录好日志。

在我们java工程中,日志框架一般分为两层,日志门面和日志实现。

日志门面

日志门面是一个抽象层,它定义了一组统一的日志接口给用户使用。隐藏了底层日志实现的细节,提供了一种与具体日志实现解耦的方式。常见的日志门面有SLF4J(Simple Logging Facade for Java)和Apache Commons Logging等。日志门面的作用包括:

  • 提供统一的日志接口,方便在应用程序中记录日志。
  • 实现日志级别的控制,可以在不同环境中灵活地调整日志输出级别。
  • 提供日志消息的格式化和输出控制。

日志实现

日志实现是一种具体的日志框架,常见的包括Logback、Log4j、Java Util Logging等。不同的日志实现可能提供不同的功能和性能特性。最基础的都提供了以下共功能:

  • 实现日志门面定义的接口,提供日志记录的功能,可以将日志消息输出到指定的目标,如控制台、文件、数据库等
  • 提供灵活的日志配置选项,如输出格式、目标、日志级别等

总结一下,日志门面提供了统一的接口,让应用程序使用,而日志实现则负责将日志消息输出到具体的目标。那么我们可以直接用日志实现来记录日志吗,当然是可以的,但是使用日志门面,有他的优点:

  • 日志和代码解耦,每个不同的日志实现记录日志的api是不一样的,定义的日志级别可能也有差别,那么如果我们直接使用日志实现比如log4j在代码里记录日志,就需要用到log4j的api。这样将来有一天如果需要切换到logback,则需要将所有log4j的代码替换成logback。但是使用日志门面,我们只需要切换配置文件就可以了。
  • 兼容性:使用日志门面可以兼容不同的日志实现,因为大多数日志门面都支持多种日志实现。这样可以在项目中使用不同的日志库,以满足不同的开发环境和需求。
  • 统一接口:使用日志门面提供的统一接口,有利于维护和各个类的日志处理方式统一,提高代码的可读性和可维护性。
    在这里插入图片描述

springboot如何配置Logback做日志框架

  1. \src\main\resources目录下添加logback.xml的配置文件,
  2. 配置日志的输出路径、输出格式等
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <!--定义日志文件的存储地址-->
    <property name="LOG_PATH" value="/home/app/logs" />

    <!-- 输出到控制台 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%logger{36}] - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 配置info级别日志的输出路径,滚动策略 -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/info/info-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <maxFileSize>50MB</maxFileSize>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%logger{36}] - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 配置error级别日志的输出路径,滚动策略 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/error/error-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <maxFileSize>50MB</maxFileSize>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%logger{36}] - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- 设置日志级别 -->
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="INFO_FILE" />
        <appender-ref ref="ERROR_FILE" />
    </root>
</configuration>

滚动策略

rollingPolicy 用于配置日志文件的滚动策略,决定何时创建新的日志文件或对现有日志文件进行归档。常见的日志滚动策略有以下几种:

  1. TimeBasedRollingPolicy:按时间滚动日志文件。该策略会根据指定的时间模式,如日期或时间间隔,创建新的日志文件。可配置属性有:

    • fileNamePattern:指定日志文件的命名模式。可以使用日期格式和/或通配符来表示日志文件的命名规则。例如,logs/app-%d{yyyy-MM-dd}.log 表示按日期切割日志文件,并以app-2022-01-01.log的格式命名。
    • maxHistory:指定保留的历史日志文件的数量。当滚动发生时,将保留最大数量的历史日志文件,较旧的日志文件将被删除。例如,7 表示最多保留 7 个历史日志文件。
    • cleanHistoryOnStart:指定在启动时是否清除历史日志文件。为 true,即在启动时删除所有历史日志文件,只保留当前日志文件。如果设置为 false,则会保留历史日志文件,但仍按照日期规则创建新的日志文件。
    • totalSizeCap:指定所有历史日志文件的总大小上限。当滚动发生时,如果历史日志文件的总大小超过了这个上限,较旧的日志文件将被删除,以保持总大小在限制范围内。可以使用B、 KB、 MB、 GB作为单位。
  2. SizeAndTimeBasedRollingPolicy:继承自TimeBasedRollingPolicy,支持按照文件大小滚动的特性,可以通过maxFileSize来配置:

    • maxFileSize:指定单个日志文件的最大大小。当日志文件达到或超过这个大小时,将触发滚动操作。可以使用可以使用B、 KB、 MB、 GB作为单位。
  3. FixedWindowRollingPolicy:按指定的固定窗口大小滚动日志文件。该策略会创建固定数量的日志文件,并在写满一个日志文件后,将日志写入下一个文件,循环使用这些日志文件。可以通过 minIndexmaxIndex 属性指定日志文件的索引范围。

    • minIndex:指定最小索引值。当滚动时,索引将从这个值开始递增。默认值为1。
    • maxIndex:指定最大索引值。当索引达到这个值时,最旧的日志文件将被删除。默认值为7。

过滤器

在Logback中,可以使用Filter来对日志事件进行筛选和过滤。常用的过滤器有:ThresholdFilterLevelFilter

  1. ThresholdFilter:基于日志级别进行过滤,只有达到或超过指定级别的日志事件才会被接受。以下是一个示例配置:

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
      <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>WARN</level>
      </filter>
    </appender>
    
  2. LevelFilter:LevelFilter也是基于日志级别进行过滤,可以根据指定的最低日志级别(level)来决定是否接受或拒绝日志事件,允许更细粒度地控制不同appender或logger的过滤行为。以下是一个示例配置:

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
      <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>WARN</level>
        <onMatch>DENY</onMatch>
        <onMismatch>ACCEPT</onMismatch>
      </filter>
    </appender>
    

    <onMatch>标签指定了满足过滤条件时的操作为DENY(拒绝),<onMismatch>标签指定了未满足过滤条件时的操作为ACCEPT(接受)。

springboot中如何通过日志切面将业务和日志进行解耦

在我们的应用中,经常需要记录每一次请求的参数、请求的结果、耗时以及请求异常时需要记录异常堆栈,用来在必要的时候排查问题。如果直接记录的话,存在日志和代码耦合,日志风格不统一,日志排查困难等问题,所以我们往往通过AOP的方式将日志和代码进行解耦,让程序员可以专注在业务的开发上。

@Aspect
@Component
@Slf4j
public class LogAspect {

    @Around(value = "execution(* com.pinellia.framework.controller.*.*(..))")
    public Object logRequest(ProceedingJoinPoint joinPoint) throws Throwable {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        String requestUrl = request.getRequestURL().toString();

        Object result = null;
        try {
            result = joinPoint.proceed();
        } catch (Throwable e) {
            log.error("Request url: {} failed...", requestUrl, e);
            throw e;
        } finally {
            stopWatch.stop();
            log.info("Request url: {}, params: {}, response: {}, cost: {}",
                    requestUrl, joinPoint.getArgs(), GsonUtil.toJson(result), stopWatch.getTotalTimeMillis());
        }

        return result;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/411919.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uni-app原生api的promise化以解决异步等待问题分析

相信各位在进行uni-app开发的时候会遇到各种关于异步回调问题&#xff0c;例如要传code给后端以换取session_key&#xff0c;在这之前需要先调用 uni.login&#xff0c;所以执行的顺序是必须同步等待的。在写这篇文章之前对于整体的流程概念需要做一个梳理&#xff0c;以便能更…

SpringCloud-Docker安装与详解

Docker 是一款强大的容器化平台&#xff0c;通过其轻量级的容器技术&#xff0c;使应用程序的开发、部署和管理变得更加便捷和高效。本文将深入探讨 Docker 的安装过程&#xff0c;并详细解析其基本概念、组件及常用命令&#xff0c;以帮助读者充分理解和熟练使用 Docker。企业…

【kubernetes】关于k8s集群中kubectl的陈述式资源管理

目录 一、k8s集群资源管理方式分类&#xff1a; &#xff08;1&#xff09;陈述式资源管理方式&#xff1a;增删查比较方便&#xff0c;但是改非常不方便 &#xff08;2&#xff09;声明式资源管理方式&#xff1a;yaml文件管理 二、陈述式资源管理方法&#xff1a; 三、ku…

linux查看服务器内核CUP版本相关命令

服务器参考 计算架构&#xff1a;x86-64产品系列&#xff1a;华为云耀云服务器操作系列&#xff1a;CentOS 7 执行uname -a查看服务器内核版本 Linux hecs-82210 3.10.0-1160.92.1.el7.x86_64 #1 SMP Tue Jun 20 11:48:01 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux执行hostn…

【Flink CDC(一)】实现mysql整表与增量读取

文章目录 一. 运行前准备1. 依赖1.1. Maven dependency1.2. SQL Client JAR&#xff08;推荐&#xff09; 2. 配置 MySQL 服务器&#xff08;必须&#xff09; 二. 功能说明1. 启动模式2. 全量阶段支持 checkpoint3. 关于无主键表Exactly-Once 处理 三. 实战1. 实现mysql整表与…

交叉编译qt到arm平台

使用pkg-config命令查看xxx包是否存在&#xff1a; pkg-config --print-errors xxx pkg-config的搜索路径可以通过环境变量PKG_CONFIG_PATH指定。需要在运行./configure 之前指定。 ./configure -release -qt-libjpeg -qt-libpng -qt-zlib -qt-pcre -xplatform linux-aarch64-…

一文读懂 Python 值传递和引用传递

文章目录 版本前言形参和实参值传递和引用传递Python 变量存储值语义和引用语义值语义引用语义 探讨 Python 值传递和引用传递不可变&#xff08;immutable&#xff09;类型可变&#xff08;mutable&#xff09;类型案例一案例二 拓展&#xff1a;不可变类型真的不可变&#xf…

华为---RSTP(三)---P/A机制及RSTP的生成树形成过程

目录 1. P/A机制简介 1.1 P/A机制的作用 1.2 P/A协商的前提条件 1.3 RSTP选举思路 2. P/A协商过程 3. 举例说明RSTP的生成树形成过程 3.1 示例环境要求 3.2 RSTP的生成树形成过程 3.2.1 SW和SW1之间链路上抓包分析 3.2.2 SW和SW2之间链路上抓包分析 3.2.3 SW1和SW2之…

LeetCode_Java_转变日期格式、种花问题(题目+思路+代码)

目录 1507. 转变日期格式 605.种花问题 1507. 转变日期格式 给你一个字符串 date &#xff0c;它的格式为 Day Month Year &#xff0c;其中&#xff1a; Day 是集合 {"1st", "2nd", "3rd", "4th", ..., "30th", "3…

【计算机图形学】Where2Act: From Pixels to Actions for Articulated 3D Objects

文章目录 1.论文做了件什么事儿2. 论文为什么要做这件事3. 介绍Introduction4. 相关工作预测语义表达推理几何和物体属性从被动观察中学习Affordance从交互中学习感知 5. 问题陈述6. 方法6.1 网络模块主干特征提取器可运动性评分模块运动建议模块运动评分模块 6.2 训练数据收集…

路由器端口映射如何配置?

在网络通信中&#xff0c;路由器是一个重要的设备&#xff0c;它负责将数据包从一个网络传输到另一个网络。路由器的端口映射配置是一种重要的设置&#xff0c;可以使外部网络中的计算机通过访问路由器上的特定端口与内部网络中的计算机进行通信。本文将介绍什么是路由器端口映…

k8s pv与pvc理解与实践

参考文章&#xff1a; https://blog.csdn.net/qq_41337034/article/details/117220475 一、 pv/pvc简述 Pv是指PersistentVolume&#xff0c;中文含义是持久化存储卷是对底层的共享存储的一种抽象&#xff0c;Pv由管理员进行配置和创建&#xff0c;只要包含存储能力&#xff…

【DL】深度学习之语音识别

目录 1 核心概念 2 安装依赖库 3 实践 语音信号处理&#xff08;Speech Signal Processing&#xff09;简称语音处理。 语音识别&#xff08;ASR&#xff09;和自然语言处理&#xff08;NLP&#xff09;&#xff1a;语音识别就是将语音信号转化成文字文本&#xff0c;简单实…

Redis 服务集群、哨兵、缓存及持久化的实现原理和应用场景

Redis 是一种高性能的键值存储系统&#xff0c;已经成为了许多企业和互联网公司的核心技术之一。本文将介绍 Redis 的服务集群、哨兵以及缓存实现原理和应用场景&#xff0c;以帮助读者更好地理解和使用 Redis。 引言&#xff1a; 随着互联网应用规模不断扩大&#xff0c;Redi…

Laravel04 eloquent

eloquent 1. eloquent2. 创建eloquent model 以及 取数据 1. eloquent 文档地址&#xff1a; https://learnku.com/docs/laravel/8.x/eloquent/9406 下面是我们&#xff0c;通过laravel的DB类从数据库中获取了post记录&#xff0c;那么有没有可能我们直接获取一个post对象&am…

[算法沉淀记录]排序算法 —— 快速排序

排序算法 —— 快速排序介绍 基本概念 快速排序&#xff08;Quicksort&#xff09;是一种排序算法&#xff0c;最早由东尼霍尔提出。在平均状况下&#xff0c;排序 n 个项目要 Ο(n log n) 次比较。在最坏状况下则需要 Ο(n2) 次比较&#xff0c;但这种状况并不常见。事实上&…

Arduino单片机基础介绍

&#xff08;本文为简单介绍&#xff0c;内容源于网络和AI&#xff09; Arduino单片机&#xff0c;自2005年诞生以来&#xff0c;已经成为全球爱好者和专业工程师们快速实现创意原型的重要工具。Arduino的普及不仅因其强大的功能和简易的操作&#xff0c;还在于其背后强大的社…

【数据结构】队列OJ题《用队列实现栈》(题库+解析+代码)

1.前言 通过前面队列的实现和详解大家对队列应该有一定熟悉了&#xff0c;现在上强度开始做题吧 队列详解&#xff1a;http://t.csdnimg.cn/dvTsW 2.OJ题目训练225. 用队列实现栈 题目分析 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0…

亿道丨三防平板丨手持平板丨加固平板丨助力地震救援

自土耳其发生7.8级大地震以来&#xff0c;一直都牵动着世人的心。2023年2月10日&#xff0c;据法新社最新消息&#xff0c;强震已造成土耳其和叙利亚两国超2万人遇难。报道称&#xff0c;相关官员和医护人员表示&#xff0c;地震造成土耳其17674人死亡&#xff0c;叙利亚则有33…

洛谷C++简单题小练习day22—小鱼记忆小程序!一题五解,高效学习

day22--小鱼记忆--2.26 习题概述 题目描述 小鱼最近被要求参加一个数字游戏&#xff0c;要求它把看到的一串数字 ai​&#xff08;长度不一定&#xff0c;以 0 结束&#xff09;&#xff0c;记住了然后反着念出来&#xff08;表示结束的数字 0 就不要念出来了&#xff09;。…