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

springboot中的日志實(shí)現(xiàn)方式

 更新時(shí)間:2025年12月26日 09:35:07   作者:kkkkkkkkl24  
文章主要介紹了如何通過(guò)觀測(cè)來(lái)提升系統(tǒng)的性能和穩(wěn)定性,包括事件記錄、系統(tǒng)運(yùn)行狀態(tài)的數(shù)字化、服務(wù)之間的全鏈路剖面等,同時(shí),文章還分享了日志記錄、異常機(jī)制和日志進(jìn)階的相關(guān)知識(shí)

很多人寫(xiě)代碼,只管業(yè)務(wù)邏輯,不知道系統(tǒng)在跑的時(shí)候:

  • 哪個(gè)接口慢?
  • 哪個(gè)服務(wù) QPS 高?
  • 哪個(gè)下游抖了?
  • 哪條鏈路撐不住了?
  • 哪個(gè)線程池快爆了?
  • 哪次 GC 卡頓導(dǎo)致 RT 抖動(dòng)?

這些其實(shí)都可以通過(guò)觀測(cè)發(fā)現(xiàn),所以我想通過(guò)一系列的文章分享下“觀測(cè)”的實(shí)現(xiàn)。

一:觀測(cè)

1.1 “事件記錄”

你可以理解為:

“發(fā)生了什么”

比如:訂單創(chuàng)建、用戶登錄、異常、重試、降級(jí)等等。

  • 如果沒(méi)有 traceId,日志是碎片;
  • 如果有 traceId,日志就是“故事”。

1.2 “系統(tǒng)運(yùn)行狀態(tài)的數(shù)字化”

你可以理解為:

“系統(tǒng)現(xiàn)在的健康狀況是什么”

比如:

  • QPS:有沒(méi)有被壓?
  • RT:變慢了嗎?
  • P99:高峰壓力如何?
  • JVM 堆:是否泄漏?
  • 線程池:是否被打滿?

1.3 “服務(wù)之間的全鏈路剖面”

你可以理解為:

“系統(tǒng)調(diào)用鏈長(zhǎng)什么樣”

比如:一次下單 → 走了哪些服務(wù)、哪些接口、哪些耗時(shí)?

二:日志

2.1依賴

<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>7.3</version>
</dependency>

2.2配置

在resources文件夾下,添加logback-spring.xml文件,配置如下,

<configuration>
    <appender name="JSON_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>具體文件路徑</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>具體文件路徑.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>打印日志在控制臺(tái)(可以刪除,減小開(kāi)銷)
        <appender-ref ref="JSON_FILE"/>輸出日志到文件
    </root>
</configuration>

三:異常機(jī)制

3.1統(tǒng)一相應(yīng)結(jié)構(gòu)

@Data
public class ApiResponse<T> {
    private Integer code;
    private String message;
    private T data;

    public static <T> ApiResponse<T> success(T data) {
        ApiResponse<T> resp = new ApiResponse<>();
        resp.setCode(0);
        resp.setMessage("OK");
        resp.setData(data);
        return resp;
    }

    public static ApiResponse<?> fail(Integer code, String message) {
        ApiResponse<?> resp = new ApiResponse<>();
        resp.setCode(code);
        resp.setMessage(message);
        return resp;
    }
}

3.2錯(cuò)誤碼枚舉

@Getter
public enum ErrorCode {
    SYSTEM_ERROR(10001, "系統(tǒng)異常,請(qǐng)稍后再試"),
    BAD_REQUEST(10002, "請(qǐng)求參數(shù)錯(cuò)誤"),
    NOT_FOUND(10003, "資源不存在"),
    BUSINESS_ERROR(20001, "業(yè)務(wù)異常");

    private final int code;
    private final String msg;

    ErrorCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
}

3.3業(yè)務(wù)異常類

@Getter
public class BizException extends RuntimeException {

    private final int code;

    public BizException(ErrorCode errorCode) {
        super(errorCode.getMsg());
        this.code = errorCode.getCode();
    }
}

3.4全局異常處理器(核心)

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 處理業(yè)務(wù)異常
     */
    @ExceptionHandler(BizException.class)
    public ApiResponse<?> handleBizException(BizException e) {
        log.warn("Business exception: {}", e.getMessage(), e);
        return ApiResponse.fail(e.getCode(), e.getMessage());
    }

    /**
     * 處理系統(tǒng)異常
     */
    @ExceptionHandler(Exception.class)
    public ApiResponse<?> handleException(Exception e) {
        log.error("System exception:", e);
        return ApiResponse.fail(
                ErrorCode.SYSTEM_ERROR.getCode(),
                ErrorCode.SYSTEM_ERROR.getMsg()
        );
    }
}

四:日志進(jìn)階

4.1加強(qiáng)日志

<configuration>

    <!-- JSON 文件輸出,按日期滾動(dòng) -->
    <appender name="JSON_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>你的文件名</file>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>你的文件名.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>

         <!-- 核心:使用 Composite Encoder,讓我們能添加 MDC -->
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <!-- 時(shí)間戳 -->
                <timestamp />

                <!-- 日志等級(jí) -->
                <logLevel />

                <!-- 線程名 -->
                <threadName />

                <!-- 日志位置 -->
                <callerData />

                <!-- 日志內(nèi)容 -->
                <message />

                <!-- 核心:輸出 MDC,如 traceId -->
                <mdc />

                <!-- 記錄 logger 名字 -->
                <loggerName />
            </providers>
        </encoder>
    </appender>

    <!-- 控制臺(tái)輸出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="JSON_FILE" />
    </root>
</configuration>

4.2TraceId 工具類

//追蹤id
public class TraceUtil {

    private static final String TRACE_ID = "traceId";

    public static String initTrace() {
        String traceId = UUID.randomUUID().toString().replace("-", "");
        MDC.put(TRACE_ID, traceId);
        return traceId;
    }

    public static void setTrace(String traceId) {
        MDC.put(TRACE_ID, traceId);
    }

    public static void clear() {
        MDC.remove(TRACE_ID);
    }

    public static String getTrace() {
        return MDC.get(TRACE_ID);
    }
}

4.3Filter

@Component
public class TraceIdFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
                                    throws ServletException, IOException {

        // 如果 header 已經(jīng)有 traceId,如網(wǎng)關(guān)或 NGINX 傳遞
        String traceId = request.getHeader("traceId");

        if (traceId == null || traceId.isEmpty()) {
            traceId = TraceUtil.initTrace();
        } else {
            TraceUtil.setTrace(traceId);
        }

        try {
            filterChain.doFilter(request, response);
        } finally {
            TraceUtil.clear();
        }
    }
}

4.4線程池追蹤

@Configuration
public class ThreadPoolConfig {

    @Bean("commonExecutor")
    public ThreadPoolTaskExecutor commonExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        executor.setCorePoolSize(8);
        executor.setMaxPoolSize(16);
        executor.setQueueCapacity(200);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("common-exec-");

        // 拒絕策略 
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());

        // 任務(wù)裝飾器(增強(qiáng):日志、鏈路追蹤、異常等)
        executor.setTaskDecorator(runnable -> () -> {
            try {
                runnable.run();
            } catch (Exception e) {
                System.err.println("Execute error: " + e.getMessage());
                throw e;
            }
        });

        executor.initialize();
        return executor;
    }
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • MySQL三種常用存儲(chǔ)引擎InnoDB、MyISAM、Memory深度解析

    MySQL三種常用存儲(chǔ)引擎InnoDB、MyISAM、Memory深度解析

    在線教程千萬(wàn)篇,為什么你的 SQL 還是慢?因?yàn)闆](méi)理解存儲(chǔ)引擎的底層機(jī)制,本文將帶你從源碼角度徹底搞懂 InnoDB 行鎖、聚簇索引,并給出生產(chǎn)環(huán)境的最優(yōu)選型,需要的朋友可以參考下
    2026-05-05
  • MySQL腳本批量自動(dòng)插入數(shù)據(jù)及數(shù)據(jù)可按條件插入實(shí)現(xiàn)

    MySQL腳本批量自動(dòng)插入數(shù)據(jù)及數(shù)據(jù)可按條件插入實(shí)現(xiàn)

    在初始化數(shù)據(jù)庫(kù)或者導(dǎo)入一些數(shù)據(jù)時(shí),常常會(huì)用到批量的操作,本文主要介紹了MySQL腳本批量自動(dòng)插入數(shù)據(jù)及數(shù)據(jù)可按條件插入實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • MySQL中EXPLAIN語(yǔ)句及用法實(shí)例

    MySQL中EXPLAIN語(yǔ)句及用法實(shí)例

    我們常常用到explain這個(gè)命令來(lái)查看一個(gè)這些SQL語(yǔ)句的執(zhí)行計(jì)劃,查看該SQL語(yǔ)句有沒(méi)有使用上了索引,下面這篇文章主要給大家介紹了關(guān)于MySQL中EXPLAIN語(yǔ)句及用法的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • mysql查詢本周內(nèi)每天統(tǒng)計(jì)量按天展示的示例代碼

    mysql查詢本周內(nèi)每天統(tǒng)計(jì)量按天展示的示例代碼

    本文主要介紹了mysql查詢本周內(nèi)每天統(tǒng)計(jì)量按天展示的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • 從原理到實(shí)踐詳解MySQL大批量數(shù)據(jù)導(dǎo)入的性能優(yōu)化指南

    從原理到實(shí)踐詳解MySQL大批量數(shù)據(jù)導(dǎo)入的性能優(yōu)化指南

    在日常運(yùn)維或數(shù)據(jù)遷移場(chǎng)景中,MySQL大批量數(shù)據(jù)導(dǎo)入慢的問(wèn)題經(jīng)常困擾著開(kāi)發(fā)者和運(yùn)維人員,本文將為大家詳細(xì)介紹三大核心優(yōu)化方案,幫你把數(shù)據(jù)導(dǎo)入效率提升10倍以上
    2025-12-12
  • 詳解mysql數(shù)據(jù)庫(kù)增刪改操作

    詳解mysql數(shù)據(jù)庫(kù)增刪改操作

    這篇文章主要介紹了mysql數(shù)據(jù)庫(kù)增刪改操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Mysql CPU占用高的問(wèn)題解決方法小結(jié)

    Mysql CPU占用高的問(wèn)題解決方法小結(jié)

    最近發(fā)現(xiàn)php網(wǎng)站發(fā)布信息比較慢,而且同網(wǎng)站目錄下的asp經(jīng)常登錄后立即就重新登錄,立即考慮到服務(wù)器資源占用問(wèn)題,所以進(jìn)服務(wù)器看到原來(lái)mysql占用率較高 25-60%左右,偶爾能跑到100%,所有導(dǎo)致上述問(wèn)題的發(fā)生
    2012-06-06
  • MySQL事務(wù)與鎖實(shí)例教程詳解

    MySQL事務(wù)與鎖實(shí)例教程詳解

    事務(wù)是指滿足ACID特性的的一組操作,可以通過(guò)Commit提交事務(wù),也可以也可以通過(guò)Rollback進(jìn)行回滾。會(huì)存在中間態(tài)和一致性狀態(tài),也是真正在數(shù)據(jù)庫(kù)表中存在的狀態(tài)
    2022-11-11
  • mysql間隙鎖的具體使用

    mysql間隙鎖的具體使用

    MySQL中有多種鎖類型,本文主要介紹了mysql間隙鎖的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-02-02
  • MySQL校對(duì)規(guī)則(COLLATION)的具體使用

    MySQL校對(duì)規(guī)則(COLLATION)的具體使用

    本文主要介紹了MySQL校對(duì)規(guī)則(COLLATION)的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08

最新評(píng)論

错那县| 拜泉县| 乐东| 汉中市| 高淳县| 桂东县| 荣昌县| 桑日县| 冷水江市| 博乐市| 天镇县| 宝应县| 长乐市| 新昌县| 东乌珠穆沁旗| 电白县| 德兴市| 辰溪县| 鄂托克旗| 新竹市| 三穗县| 西林县| 濮阳县| 兴和县| 离岛区| 巩留县| 芜湖县| 满城县| 西林县| 山西省| 电白县| 绥滨县| 汕尾市| 布尔津县| 于都县| 巴林右旗| 蒲江县| 沽源县| 扬中市| 兴山县| 新疆|