亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java怎么通過MySQL驅動攔截器實現執行sql耗時計算

發布時間:2023-03-20 16:03:41 來源:億速云 閱讀:150 作者:iii 欄目:開發技術

這篇文章主要介紹了java怎么通過MySQL驅動攔截器實現執行sql耗時計算的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇java怎么通過MySQL驅動攔截器實現執行sql耗時計算文章都會有所收獲,下面我們一起來看看吧。

背景

公司的一個需求,公司既有的鏈路追蹤日志組件要支持MySQL的sql執行時間打印,要實現鏈路追蹤常用的手段就是實現第三方框架或工具提供的攔截器接口或者是過濾器接口,對于MySQL也不例外,實際上就是實現了MySQL驅動的攔截器接口而已。

具體實現

MySQL的渠道有不同的版本,不同版本的攔截器接口是不同的,所以要針對你所使用的不同版本的MySQL驅動去實現響應的攔截器,接下來分別介紹下MySQL渠道5,6,8版本的實現方式。

MySQL5

這里以MySQL渠道5.1.18版本為例實現,實現StatementInterceptorV2接口,主要實現邏輯在preProcesspostProcess方法,這兩個方法是sql執行前后要執行的方法,我所使用的框架是logback,這里使用MDC來記錄sql執行前的一個時間戳,代碼在postProcess方法MDC.put("sql_exec_time", start);,自己也可以使用ThreadLocal等來實現,然后在postProcess方法中使用MDC.get("sql_exec_time")將記錄的sql執行前的時間取出來,最后再用當前時間戳減去sql執行前的時間,就算出了sql執行的時間。

import static net.logstash.logback.marker.Markers.append;

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.ResultSetInternalMethods;
import com.mysql.jdbc.Statement;
import com.mysql.jdbc.StatementInterceptorV2;
import com.redick.util.LogUtil;
import java.sql.SQLException;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;

/**
 * @author Redick01
 */
@Slf4j
public class Mysql5StatementInterceptor implements StatementInterceptorV2 {

    @Override
    public void init(Connection connection, Properties properties) throws SQLException {

    }

    @Override
    public ResultSetInternalMethods preProcess(String s, Statement statement, Connection connection)
            throws SQLException {
        String start = String.valueOf(System.currentTimeMillis());
        MDC.put("sql_exec_time", start);
        log.info(LogUtil.customizeMarker(LogUtil.kLOG_KEY_TRACE_TAG, "sql_exec_before"), "開始執行sql");
        return null;
    }

    @Override
    public boolean executeTopLevelOnly() {
        return false;
    }

    @Override
    public void destroy() {

    }

    @Override
    public ResultSetInternalMethods postProcess(String s, Statement statement,
            ResultSetInternalMethods resultSetInternalMethods, Connection connection, int i,
            boolean b, boolean b1, SQLException e) throws SQLException {
        long start = Long.parseLong(MDC.get("sql_exec_time"));
        long end = System.currentTimeMillis();
        log.info(LogUtil.customizeMarker(LogUtil.kLOG_KEY_TRACE_TAG, "sql_exec_after")
                .and(append(LogUtil.kLOG_KEY_SQL_EXEC_DURATION, end - start)), "結束執行sql");
        return null;
    }
}

MySQL6

MySQL6和MySQL5基本一樣,只是接口不是同一個,直接放代碼

import static net.logstash.logback.marker.Markers.append;

import com.mysql.cj.api.MysqlConnection;
import com.mysql.cj.api.jdbc.Statement;
import com.mysql.cj.api.jdbc.interceptors.StatementInterceptor;
import com.mysql.cj.api.log.Log;
import com.mysql.cj.api.mysqla.result.Resultset;
import com.redick.util.LogUtil;
import java.sql.SQLException;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;

/**
 * @author Redick01
 */
@Slf4j
public class Mysql6StatementInterceptor implements StatementInterceptor {

    @Override
    public StatementInterceptor init(MysqlConnection mysqlConnection, Properties properties,
            Log log) {
        return null;
    }

    @Override
    public <T extends Resultset> T preProcess(String s, Statement statement) throws SQLException {
        String start = String.valueOf(System.currentTimeMillis());
        MDC.put("sql_exec_time", start);
        log.info(LogUtil.customizeMarker(LogUtil.kLOG_KEY_TRACE_TAG, "sql_exec_before"), "開始執行sql");
        return null;
    }

    @Override
    public boolean executeTopLevelOnly() {
        return false;
    }

    @Override
    public void destroy() {

    }

    @Override
    public <T extends Resultset> T postProcess(String s, Statement statement, T t, int i, boolean b,
            boolean b1, Exception e) throws SQLException {
        long start = Long.parseLong(MDC.get("sql_exec_time"));
        long end = System.currentTimeMillis();
        log.info(LogUtil.customizeMarker(LogUtil.kLOG_KEY_TRACE_TAG, "sql_exec_after")
                .and(append(LogUtil.kLOG_KEY_SQL_EXEC_DURATION, end - start)), "結束執行sql");
        return null;
    }
}

MySQL8

MySQL8和MySQL5/6的攔截器接口又不一樣了,MySQL8的攔截器接口是com.mysql.cj.interceptors.QueryInterceptor,統計sql執行時間的方式還是一樣的,代碼如下:

import static net.logstash.logback.marker.Markers.append;

import com.mysql.cj.MysqlConnection;
import com.mysql.cj.Query;
import com.mysql.cj.interceptors.QueryInterceptor;
import com.mysql.cj.log.Log;
import com.mysql.cj.protocol.Resultset;
import com.mysql.cj.protocol.ServerSession;
import com.redick.util.LogUtil;
import java.util.Properties;
import java.util.function.Supplier;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;

/**
 * @author Redick01
 */
@Slf4j
public class Mysql8QueryInterceptor implements QueryInterceptor {

    @Override
    public QueryInterceptor init(MysqlConnection mysqlConnection, Properties properties, Log log) {
        return null;
    }

    @Override
    public <T extends Resultset> T preProcess(Supplier<String> supplier, Query query) {
        String start = String.valueOf(System.currentTimeMillis());
        MDC.put("sql_exec_time", start);
        log.info(LogUtil.customizeMarker(LogUtil.kLOG_KEY_TRACE_TAG, "sql_exec_before"), "開始執行sql");
        return null;
    }

    @Override
    public boolean executeTopLevelOnly() {
        return false;
    }

    @Override
    public void destroy() {

    }

    @Override
    public <T extends Resultset> T postProcess(Supplier<String> supplier, Query query, T t,
            ServerSession serverSession) {
        long start = Long.parseLong(MDC.get("sql_exec_time"));
        long end = System.currentTimeMillis();
        log.info(LogUtil.customizeMarker(LogUtil.kLOG_KEY_TRACE_TAG, "sql_exec_after")
                .and(append(LogUtil.kLOG_KEY_SQL_EXEC_DURATION, end - start)), "結束執行sql");
        return null;
    }
}

使用方法

MySQL5和6的使用方式一樣,在數據庫鏈接的url中增加如下statementInterceptors參數,例如:

 url: jdbc:mysql://127.0.0.1:3316/log-helper?useUnicode=true&characterEncoding=UTF8&statementInterceptors=com.redick.support.mysql.Mysql5StatementInterceptor&serverTimezone=CST

MySQL8則是在url中增加queryInterceptors參數,例如:

url: jdbc:mysql://127.0.0.1:3316/log-helper?useUnicode=true&characterEncoding=UTF8&queryInterceptors=com.redick.support.mysql.Mysql8QueryInterceptor&serverTimezone=CST

測試結果

sql執行前日志

{"@timestamp":"2023-02-28T17:16:29.234+08:00","@version":"0.0.1","message":"開始執行sql","logger_name":"com.redick.support.mysql.Mysql5StatementInterceptor","thread_name":"http-nio-3321-exec-4","level":"INFO","level_value":20000,"traceId":"9ed930dc-4cc6-4719-bf33-9fcb618fd65b","spanId":"1","request_type":"getName","parentId":"0","trace_tag":"sql_exec_before"}

sql執行后日志,sql_duration標識執行sql耗時3ms

{"@timestamp":"2023-02-28T17:16:29.237+08:00","@version":"0.0.1","message":"結束執行sql","logger_name":"com.redick.support.mysql.Mysql5StatementInterceptor","thread_name":"http-nio-3321-exec-4","level":"INFO","level_value":20000,"traceId":"9ed930dc-4cc6-4719-bf33-9fcb618fd65b","spanId":"1","request_type":"getName","parentId":"0","trace_tag":"sql_exec_after","sql_duration":3}

關于“java怎么通過MySQL驅動攔截器實現執行sql耗時計算”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“java怎么通過MySQL驅動攔截器實現執行sql耗時計算”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

玛沁县| 荣成市| 达州市| 安多县| 崇州市| 嘉祥县| 镇原县| 集安市| 贞丰县| 临夏市| 友谊县| 镇康县| 积石山| 鄯善县| 富裕县| 浦北县| 普安县| 平昌县| 通海县| 鹤庆县| 崇阳县| 峨眉山市| 册亨县| 嘉义市| 青海省| 旬邑县| 临沂市| 泰顺县| 论坛| 南澳县| 青岛市| 民和| 乌拉特中旗| 扎赉特旗| 西青区| 惠水县| 二连浩特市| 扎囊县| 赣榆县| 望城县| 澄迈县|