最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot實(shí)現(xiàn)日志系統(tǒng)的完整指南

 更新時(shí)間:2025年12月09日 08:48:52   作者:悟空碼字  
沒(méi)有日志系統(tǒng),那就好比程序生病了,你問(wèn)他哪不舒服,他只會(huì)回答我掛了,下面我們就來(lái)看看如何使用SpringBoot實(shí)現(xiàn)日志系統(tǒng),讓我們給SpringBoot程序配個(gè)貼心小秘書(shū)吧

日志系統(tǒng)是什么

想象一下,你的程序是個(gè)有點(diǎn)健忘的程序員同事(沒(méi)錯(cuò),就是那個(gè)總說(shuō)“我本地是好的”的家伙)。日志系統(tǒng)就是給他配的貼身小秘書(shū),每天拿著小本本記錄:

  • 幾點(diǎn)幾分干了啥(時(shí)間戳)
  • 心里想什么(調(diào)試信息)
  • 今天工作順利嗎(INFO信息)
  • 出問(wèn)題了(ERROR信息)
  • 救火啊要炸了(FATAL信息)

沒(méi)有日志系統(tǒng)?那就好比程序生病了,你問(wèn)他“哪不舒服?”,他只會(huì)回答“我掛了”。有了日志,他就能詳細(xì)告訴你:“昨天下午3點(diǎn),我在處理用戶訂單時(shí),因?yàn)閿?shù)據(jù)庫(kù)連接斷了,導(dǎo)致...”

好了,廢話不多說(shuō),讓我們給SpringBoot程序配個(gè)“貼心小秘書(shū)”!

第1步:SpringBoot的“天生麗質(zhì)”

SpringBoot這家伙很貼心,已經(jīng)內(nèi)置了日志系統(tǒng)!就像你買手機(jī),相機(jī)APP已經(jīng)預(yù)裝好了。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LogDemoController {
    
    // 創(chuàng)建日志記錄器,就像給這個(gè)類配了個(gè)專屬記者
    private static final Logger logger = LoggerFactory.getLogger(LogDemoController.class);
    
    @GetMapping("/hello")
    public String sayHello() {
        // 不同的日志級(jí)別,就像不同的說(shuō)話語(yǔ)氣
        logger.trace("這是最詳細(xì)的跟蹤信息 - 連我呼吸都要記錄");
        logger.debug("調(diào)試信息 - 我在想:用戶到底點(diǎn)了啥按鈕?");
        logger.info("普通信息 - 用戶訪問(wèn)了hello接口,一切正常");
        logger.warn("警告信息 - 內(nèi)存有點(diǎn)高,像吃了太多內(nèi)存的胖子");
        logger.error("錯(cuò)誤信息 - 數(shù)據(jù)庫(kù)連接失?。】靵?lái)人?。?);
        
        // 還可以帶參數(shù),像填空一樣
        String userName = "碼農(nóng)小張";
        int userId = 123;
        logger.info("用戶 {} (ID: {}) 登錄成功", userName, userId);
        
        return "Hello World! 快去控制臺(tái)看日志吧!";
    }
    
    @GetMapping("/oops")
    public String makeMistake() {
        try {
            // 故意制造一個(gè)錯(cuò)誤
            int result = 10 / 0;
            return "這行代碼永遠(yuǎn)執(zhí)行不到";
        } catch (Exception e) {
            // 記錄異常信息,參數(shù)e會(huì)自動(dòng)打印堆棧
            logger.error("數(shù)學(xué)老師沒(méi)教好,除零錯(cuò)誤了!", e);
            return "哎呀,出錯(cuò)了!詳情請(qǐng)看日志";
        }
    }
}

第2步:配置文件 - 給秘書(shū)定規(guī)矩

application.yml(或application.properties)中配置。這是告訴小秘書(shū):“哪些話要記,哪些話不用記,記在哪里...”

# application.yml - 日志系統(tǒng)的“規(guī)章制度”

# 第一部分:全局日志級(jí)別設(shè)置
logging:
  level:
    root: INFO  # 根日志級(jí)別:INFO及以上才記錄
    com.example.demo: DEBUG  # 我們自己的包可以詳細(xì)點(diǎn)
    org.springframework.web: WARN  # Spring的web包,只記錄警告及以上
    
  # 第二部分:輸出到哪里(控制臺(tái)和文件都記)
  file:
    name: logs/myapp.log  # 日志文件路徑
    max-size: 10MB  # 單個(gè)文件最大10MB,超過(guò)就切分
    max-history: 30  # 保留最近30天的日志
    
  # 第三部分:日志格式 - 給小秘書(shū)的"記錄模板"
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
    file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
    
  # 第四部分:按包或類單獨(dú)設(shè)置(精細(xì)化管理)
  group:
    web: org.springframework.web, org.springframework.security
    app: com.example.demo.controller, com.example.demo.service
    
  level:
    web: INFO
    app: DEBUG

# 如果你想用logback的詳細(xì)配置(高級(jí)玩法)
# 在resources目錄下創(chuàng)建logback-spring.xml

第3步:高級(jí)玩法 - 自定義日志配置

resources目錄下創(chuàng)建logback-spring.xml,這是給小秘書(shū)的詳細(xì)工作手冊(cè)

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
    
    <!-- 控制臺(tái)輸出 - 給開(kāi)發(fā)人員看的 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 彩色日志,讓控制臺(tái)不再單調(diào)! -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    
    <!-- 按天滾動(dòng)的文件輸出 - 給運(yùn)維人員看的 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/application.log</file>
        <!-- 每天一個(gè)文件,最多保存30天 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/application.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy 
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    
    <!-- 錯(cuò)誤日志單獨(dú)文件 - 重要的事情說(shuō)三遍,重要的錯(cuò)誤單獨(dú)記 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/error.log</file>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/error.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>90</maxHistory>  <!-- 錯(cuò)誤日志保留更久 -->
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    
    <!-- 不同環(huán)境的配置 -->
    <springProfile name="dev">
        <root level="INFO">
            <appender-ref ref="CONSOLE"/>
        </root>
        <logger name="com.example" level="DEBUG" additivity="false">
            <appender-ref ref="CONSOLE"/>
        </logger>
    </springProfile>
    
    <springProfile name="prod">
        <root level="WARN">
            <appender-ref ref="FILE"/>
            <appender-ref ref="ERROR_FILE"/>
        </root>
        <logger name="com.example" level="INFO" additivity="false">
            <appender-ref ref="FILE"/>
            <appender-ref ref="ERROR_FILE"/>
        </logger>
    </springProfile>
    
</configuration>

第4步:AOP實(shí)現(xiàn)方法日志 - 自動(dòng)記錄每個(gè)方法

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MethodLogAspect {
    
    private static final Logger logger = LoggerFactory.getLogger(MethodLogAspect.class);
    
    /**
     * 自動(dòng)記錄Controller層每個(gè)方法的執(zhí)行情況
     * 就像給每個(gè)方法配了個(gè)貼身觀察員
     */
    @Around("execution(* com.example.demo.controller..*.*(..))")
    public Object logControllerMethods(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().toShortString();
        Object[] args = joinPoint.getArgs();
        
        long startTime = System.currentTimeMillis();
        logger.info("方法開(kāi)始執(zhí)行: {},參數(shù): {}", methodName, args);
        
        try {
            Object result = joinPoint.proceed();
            long executionTime = System.currentTimeMillis() - startTime;
            
            logger.info("方法執(zhí)行成功: {},耗時(shí): {}ms,返回值: {}", 
                       methodName, executionTime, result);
            return result;
            
        } catch (Exception e) {
            long executionTime = System.currentTimeMillis() - startTime;
            logger.error("方法執(zhí)行失敗: {},耗時(shí): {}ms,異常: {}", 
                        methodName, executionTime, e.getMessage(), e);
            throw e;
        }
    }
}

第5步:日志工具類 - 讓日志更智能

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StopWatch;

/**
 * 日志工具類 - 給日志加點(diǎn)"智能"
 */
public class LogUtil {
    
    /**
     * 性能監(jiān)控 - 記錄代碼塊執(zhí)行時(shí)間
     */
    public static <T> T monitorPerformance(Logger logger, String taskName, 
                                          Supplier<T> task) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        logger.info("開(kāi)始執(zhí)行: {}", taskName);
        
        try {
            T result = task.get();
            stopWatch.stop();
            
            logger.info("執(zhí)行完成: {},耗時(shí): {}ms", 
                       taskName, stopWatch.getTotalTimeMillis());
            return result;
            
        } catch (Exception e) {
            stopWatch.stop();
            logger.error("執(zhí)行失敗: {},耗時(shí): {}ms,錯(cuò)誤: {}", 
                        taskName, stopWatch.getTotalTimeMillis(), e.getMessage(), e);
            throw e;
        }
    }
    
    /**
     * 業(yè)務(wù)日志 - 記錄關(guān)鍵業(yè)務(wù)操作
     */
    public static void businessLog(Logger logger, String operation, 
                                  String userId, Object... details) {
        // 這里可以擴(kuò)展,比如記錄到數(shù)據(jù)庫(kù)或發(fā)送到消息隊(duì)列
        logger.info("業(yè)務(wù)操作 - 用戶: {}, 操作: {}, 詳情: {}", 
                   userId, operation, details);
    }
    
    // 使用示例
    public void exampleUsage() {
        Logger logger = LoggerFactory.getLogger(this.getClass());
        
        // 監(jiān)控性能
        String result = monitorPerformance(logger, "計(jì)算用戶報(bào)表", () -> {
            // 模擬耗時(shí)操作
            Thread.sleep(1000);
            return "報(bào)表數(shù)據(jù)";
        });
        
        // 記錄業(yè)務(wù)日志
        businessLog(logger, "用戶登錄", "user123", "IP: 192.168.1.1", "設(shè)備: Chrome");
    }
}

第6步:與ELK等日志系統(tǒng)集成(高級(jí)玩法)

# application-prod.yml - 生產(chǎn)環(huán)境配置
logging:
  # 輸出JSON格式,方便ELK采集
  pattern:
    console: '{"timestamp":"%d{yyyy-MM-dd HH:mm:ss.SSS}", "level":"%level", "thread":"%thread", "logger":"%logger", "message":"%msg", "exception":"%ex"}'
  
  # Logstash收集配置(如果需要)
  logstash:
    enabled: true
    host: localhost
    port: 5000

總結(jié):日志系統(tǒng)的"生存指南"

經(jīng)過(guò)這一番折騰,我們的SpringBoot程序終于有了一個(gè)稱職的貼身秘書(shū)。讓我們總結(jié)一下日志系統(tǒng)的幾個(gè)關(guān)鍵點(diǎn):

為什么要用日志系統(tǒng)

  • 故障排查:程序說(shuō)“我掛了” → 日志說(shuō)“3點(diǎn)15分?jǐn)?shù)據(jù)庫(kù)連接超時(shí)”
  • 性能分析:用戶說(shuō)“好卡” → 日志說(shuō)“這個(gè)接口平均響應(yīng)2.3秒”
  • 行為追蹤:老板說(shuō)“誰(shuí)干的” → 日志說(shuō)“用戶admin在10點(diǎn)修改了配置”
  • 數(shù)據(jù)統(tǒng)計(jì):產(chǎn)品說(shuō)“有多少人用” → 日志說(shuō)“今天有15234次訪問(wèn)”

最佳實(shí)踐

  • 級(jí)別要分明:DEBUG用于開(kāi)發(fā),INFO用于日常,ERROR用于異常
  • 信息要詳細(xì):時(shí)間、線程、級(jí)別、類名、消息、異常,一個(gè)都不能少
  • 性能要注意:日志IO是性能殺手,異步日志是個(gè)好選擇
  • 安全要牢記:密碼、token等敏感信息別往日志里寫

常見(jiàn)坑點(diǎn)

  • 日志太多:把DEBUG級(jí)別放到生產(chǎn)環(huán)境,日志文件瞬間爆炸
  • 日志太少:出問(wèn)題時(shí),日志里只有“出錯(cuò)了”,沒(méi)有“為啥錯(cuò)”
  • 格式混亂:今天用JSON,明天用文本,后天ELK不認(rèn)了
  • 忘記歸檔:日志文件把磁盤寫滿了,程序真掛了

最后

給你的日志系統(tǒng)起個(gè)名字吧!比如叫“小日志”、“程序記錄儀”、“代碼攝像頭”。畢竟,它要陪你度過(guò)無(wú)數(shù)個(gè)排查BUG的不眠之夜,是你在茫茫代碼海洋中的燈塔,是你在程序崩潰時(shí)的救命稻草。

現(xiàn)在,去給你的SpringBoot程序配個(gè)“貼心小秘書(shū)”吧!當(dāng)程序再次崩潰時(shí),至少有人(日志)能告訴你:“親,這次是因?yàn)?..”

到此這篇關(guān)于SpringBoot實(shí)現(xiàn)日志系統(tǒng)的完整指南的文章就介紹到這了,更多相關(guān)SpringBoot日志系統(tǒng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java基于swing實(shí)現(xiàn)的彈球游戲代碼

    Java基于swing實(shí)現(xiàn)的彈球游戲代碼

    這篇文章主要介紹了Java基于swing實(shí)現(xiàn)的彈球游戲代碼,包含了窗體界面設(shè)計(jì)與游戲的邏輯功能處理,具有不錯(cuò)的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-11-11
  • java前后端加密解密crypto-js的實(shí)現(xiàn)

    java前后端加密解密crypto-js的實(shí)現(xiàn)

    這篇文章主要介紹了java前后端加密解密crypto-js的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • eclipse中自動(dòng)生成javadoc文檔的方法

    eclipse中自動(dòng)生成javadoc文檔的方法

    這篇文章主要介紹了eclipse中自動(dòng)生成javadoc文檔的方法,是實(shí)用eclipse開(kāi)發(fā)Java程序時(shí)非常實(shí)用的技巧,對(duì)于進(jìn)行Java項(xiàng)目開(kāi)發(fā)具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-12-12
  • java設(shè)置日期返回格式的4種方式小結(jié)

    java設(shè)置日期返回格式的4種方式小結(jié)

    這篇文章主要為大家詳細(xì)介紹了java設(shè)置日期返回格式的4種方式,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-12-12
  • JAVA學(xué)習(xí)進(jìn)階篇之時(shí)間與日期相關(guān)類

    JAVA學(xué)習(xí)進(jìn)階篇之時(shí)間與日期相關(guān)類

    在日常的開(kāi)發(fā)工作當(dāng)中,我們經(jīng)常需要用到日期相關(guān)的類,下面這篇文章主要給大家介紹了關(guān)于JAVA學(xué)習(xí)進(jìn)階篇之時(shí)間與日期相關(guān)類的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • JAVA開(kāi)發(fā)環(huán)境搭建教程

    JAVA開(kāi)發(fā)環(huán)境搭建教程

    這篇文章主要為大家詳細(xì)介紹了JAVA開(kāi)發(fā)環(huán)境搭建教程,配置JAVA開(kāi)發(fā)環(huán)境,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • ArrayList和LinkedList區(qū)別及使用場(chǎng)景代碼解析

    ArrayList和LinkedList區(qū)別及使用場(chǎng)景代碼解析

    這篇文章主要介紹了ArrayList和LinkedList區(qū)別及使用場(chǎng)景代碼解析,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • 最新評(píng)論

    册亨县| 丹寨县| 碌曲县| 温州市| 河北区| 顺义区| 宽城| 浦城县| 图木舒克市| 石楼县| 临猗县| 德兴市| 霍林郭勒市| 大荔县| 桦甸市| 明水县| 义马市| 巩义市| 垫江县| 宣恩县| 奉新县| 涿鹿县| 婺源县| 喀什市| 左贡县| 高碑店市| 措美县| 闽清县| 沾益县| 虹口区| 昂仁县| 永德县| 马山县| 南康市| 峨边| 临泉县| 尼玛县| 汝阳县| 海宁市| 临澧县| 措勤县|