日志的配置

日志设计分析

  • 此项目总共分为四种日志:性能日志(performance.log),业务日志(business.log),错误输出日志(error.log),控制台输出日志
  • 业务日志包括:基本的业务日志(logBusiness),用户操作日志(logUserOperation),业务错误日志(logBusinessError在配置文件里面有专门的配置到单独输出日志文件中),API调用日志(logAPICall),文件操作日志(logFileOperation),记录聊天日志(logChat)
  • 性能监控修饰器分析
 // 性能日志记录器,Slf4j依赖,getLogger获取在logback中的性能输出配置
 //private为了控制访问权限,避免被外部类修改了日志配置,应该在xml文件中统一管理而不是能被外部类修改
 //static共享变量节省空间,日志对象本身是无状态的只负责日志输出,不存储实际数据,可以避免多个logger对象创建浪费空间
 //final保证不可改变,避免错误的重新对记录器赋值,比如赋值到了业务日志,输出错乱
    private static final Logger PERFORMANCE_LOGGER = LoggerFactory.getLogger("com.yizhaoqi.smartpai.performance");


    /**
     * 记录性能日志
     */
    public static void logPerformance(String operation, long duration, String details) {
        try {
            MDC.put(OPERATION, operation);
            PERFORMANCE_LOGGER.info("[性能] [{}] 耗时:{}ms {}", operation, duration, details);
        } finally {
            MDC.clear();
        }
    }

    /**
     * 性能监控装饰器
     */
    public static class PerformanceMonitor {
        private final String operation;
        private final long startTime;
        
        public PerformanceMonitor(String operation) {
            this.operation = operation;
            this.startTime = System.currentTimeMillis();
        }
        
        public void end() {
            end("");
        }
        
        public void end(String details) {
            long duration = System.currentTimeMillis() - startTime;
            logPerformance(operation, duration, details);
        }
    }
    
    /**
     * 创建性能监控器,这是一个静态方法工厂,不直接使用该类的构造方法,第一可读性增强,直接new对象不知道作用
     * 封装对象创建的细节,内部修改不影响外部代码,灵活性扩展性更好,实现开放封闭原则,如果修改对象创建的规则,那么所有new的对象都要进行修改
     * 这个类里面的构造方法目前是public,如果我们对象创建有设置的逻辑不希望被绕开通过构造方法创建,就可以换成private编程单例模式
     */
    public static PerformanceMonitor startPerformanceMonitor(String operation) {
        return new PerformanceMonitor(operation);
    }

logback-spring.xml中的配置

日志级别

  • trace->debug->info->warn->error->fatal最高致命错误

控制台日志输出

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> //这里class绑定为控制台输出
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> //这个encoder是编码器,根据pattern格式编码成对应格式的日志
            <!-- 格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

按照每天生成日志

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        //切割之后的日志名字要按照时间归档
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志文件输出的文件名 -->
            <FileNamePattern>${LOG_HOME}/smartpai.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!-- 日志文件保留天数 -->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!-- 格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志文件最大的大小 -->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>100MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

错误日志单独输出

<!-- 错误日志单独输出 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        //设置过滤器,只有ERROR级别能接受,否则拒绝,精确匹配
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME}/error.%d{yyyy-MM-dd}.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

业务逻辑输出

    //同样是按照天数进行分割输出到business开头文件中,保存30天
    <appender name="BUSINESS_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME}/business.%d{yyyy-MM-dd}.log</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

性能日志输出

<!-- 性能日志单独输出 -->
    <appender name="PERFORMANCE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME}/performance.%d{yyyy-MM-dd}.log</FileNamePattern>
            <MaxHistory>7</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

精细化级别控制

    <!-- 项目包日志级别配置,全局控制级别,additivity表示关闭日志向上传递,避免根目录重复输出 -->
    <logger name="com.yizhaoqi.smartpai" level="INFO" additivity="false">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
        <appender-ref ref="ERROR_FILE"/>
        <appender-ref ref="BUSINESS_FILE"/>
    </logger>

    <!-- 业务日志记录器 两个业务输出日志-->
    <logger name="com.yizhaoqi.smartpai.business" level="INFO" additivity="false">
        <appender-ref ref="BUSINESS_FILE"/>
        <appender-ref ref="CONSOLE"/>
    </logger>

    <!-- 性能日志记录器 针对性能日志配置-->
    <logger name="com.yizhaoqi.smartpai.performance" level="INFO" additivity="false">
        <appender-ref ref="PERFORMANCE_FILE"/>
    </logger>

//对于第三方的日志进行级别设置,避免对业务日志淹没
    <!-- Spring框架日志级别 -->
    <logger name="org.springframework" level="WARN"/>
    <logger name="org.springframework.web" level="INFO"/>
    <logger name="org.springframework.security" level="INFO"/>
    <logger name="org.springframework.boot" level="INFO"/>

    <!-- 数据库相关日志 -->
    <logger name="org.hibernate" level="WARN"/>
    <logger name="org.hibernate.SQL" level="INFO"/>
    <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>

    <!-- 第三方库日志级别 -->
    <logger name="io.minio" level="WARN"/>
    <logger name="org.apache.kafka" level="WARN"/>
    <logger name="org.elasticsearch" level="WARN"/>
    <logger name="co.elastic" level="WARN"/>
    <logger name="org.apache.tika" level="WARN"/>
    <logger name="io.netty" level="WARN"/>
    <logger name="reactor.netty" level="WARN"/>

//配置开发环境选择
    <!-- 开发环境配置 -->
    <springProfile name="dev">
        <logger name="com.yizhaoqi.smartpai" level="DEBUG"/>
        <logger name="org.springframework.web" level="DEBUG"/>
        <logger name="org.springframework.security" level="DEBUG"/>
    </springProfile>

    <!-- 生产环境配置 -->
    <springProfile name="prod">
        <logger name="com.yizhaoqi.smartpai" level="INFO"/>
        <logger name="org.springframework" level="WARN"/>
        <logger name="root" level="WARN"/>
    </springProfile>

//最后根目录设置级别兜底
    <!-- 根日志级别 -->
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
        <appender-ref ref="ERROR_FILE"/>
    </root>
posted @ 2025-12-27 23:26  Huangyien  阅读(3)  评论(0)    收藏  举报