fly coding 监控(二):实现SQL监控

此前,已改造完基础监控工厂。此篇,将基于此前的功能,实现SQL语句的监控日志记录。

开发思路

为实现对系统执行SQL进行监控,主要记录"执行时长"、"转换类"、"是否执行成功"、"执行器"、"执行Sql脚本"、"执行参数"、"返回结果"等数据。在后期系统上线运行过程中,进行实时监控,便于优化产品性能。

设计数据库

yml配置

yml 复制代码
   # sql监控配置
    sql:
      # 是否监控
      is-monitor: true
      # 是否输出到控制台
      is-output-console: true
      # 是否保存用户代理信息
      is-save-user-agent: true
      # 是否保存异常信息
      is-save-throwable: true
      # 是否保存请求客户端信息
      is-save-request-client: true
      # 是否保存sql语句
      is-save-sql: true
      # 是否保存返回结果集
      is-save-return-results: true
      # 是否保存执行参数
      is-save-execute-params: true

此上配置参数,用于动态配置是否开启指定记录项。

PO定义

java 复制代码
package com.flycoding.monitor.entity;

import com.flycoding.dblibrary.annotation.create.Column;
import com.flycoding.dblibrary.annotation.create.PrimaryAuto;
import com.flycoding.dblibrary.annotation.create.Table;
import com.flycoding.dblibrary.enums.ColumnType;
import com.flycoding.dblibrary.enums.OrderByType;
import com.flycoding.drivenlibrary.engine.annotation.function.FunctionConfig;
import com.flycoding.drivenlibrary.engine.annotation.function.config.popup.PopupConfig;
import com.flycoding.drivenlibrary.engine.annotation.function.config.table.TableConfig;
import com.flycoding.drivenlibrary.engine.annotation.function.form.FormConfig;
import com.flycoding.drivenlibrary.engine.annotation.function.form.FormFieldConfig;
import com.flycoding.drivenlibrary.engine.annotation.function.form.field.DictConfig;
import com.flycoding.drivenlibrary.engine.annotation.function.form.field.FieldConfig;
import com.flycoding.drivenlibrary.engine.config.constants.dictionary.ConfigDictionaryConstants.EnableCodeDictionary;
import com.flycoding.drivenlibrary.engine.constants.DefaultFieldConstants;
import com.flycoding.drivenlibrary.engine.constants.FieldConfigConstants;
import com.flycoding.drivenlibrary.engine.constants.SqlConstants;
import com.flycoding.drivenlibrary.engine.constants.config.DrivenElementConstants;
import com.flycoding.monitor.entity.base.BaseMonitorPO;
import com.flycoding.monitor.entity.base.BaseRequestMonitorPO;

/**
 * 监控SQL语句
 *
 * @author 赵屈犇
 * @version 1.0
 * @date 创建时间: 2020/10/8 20:35
 */
@Table(tableName = MonitorSqlPO.TABLE_NAME)
@FunctionConfig(funcName = "SQL执行监控", funcCode = "Sy_Monitor_Sql", tableConfig = @TableConfig(tableName = MonitorSqlPO.TABLE_NAME,
                                                                                              columns = {
                                                                                                  @Column(columnName = DefaultFieldConstants.CREATE_TIME, isInsertUse = false, isSelectUse = false, orderBy = OrderByType.DESC)
                                                                                              }), formConfig = @FormConfig(keyCode = "id", isCreateTableAddBtn = false, popupConfig = @PopupConfig(popupWidth = 850, popupHeight = 550)))
public class MonitorSqlPO extends BaseRequestMonitorPO {

    public static final String TABLE_NAME = "Sys_Monitor_Sql";

    @PrimaryAuto(columnName = "id", comment = "主键ID")
    @FormFieldConfig(fieldCode = "id", fieldName = "SqlID", isPageVisibility = false, isTableEnable = false, fieldParentName = MONITOR_BASIC_MESSAGE_NAME)
    private Integer id;
    /**
     * 转换类别名
     */
    @FormFieldConfig(fieldCode = "convert_class_name", fieldName = "转换类别名", fieldParentName = MONITOR_BASIC_MESSAGE_NAME)
    @Column(columnName = "convert_class_name", columnType = ColumnType.VARCHAR, length = SqlConstants.DB_NAME_SIZE)
    private String convertClassName;
    /**
     * 执行时长
     */
    @FormFieldConfig(fieldCode = "executor_duration", fieldName = "执行时长(毫秒)", fieldParentName = MONITOR_BASIC_MESSAGE_NAME)
    @Column(columnName = "executor_duration", columnType = ColumnType.INTEGER, length = 20)
    private Long executorDuration;
    /**
     * 执行是否成功
     */
    @FormFieldConfig(fieldCode = "is_executor_success", fieldName = "是否执行成功", elementCode = DrivenElementConstants.RADIO_ELEMENT,
            pageDefaultValue = EnableCodeDictionary.YES, fieldParentName = MONITOR_BASIC_MESSAGE_NAME,
            dict = @DictConfig(dictCode = EnableCodeDictionary.DICTIONARY_CODE))
    @Column(columnName = "is_executor_success", columnType = ColumnType.VARCHAR, length = SqlConstants.DICTIONARY_VALUE_SIZE)
    private String isExecutorSuccess;
    /**
     * 数据库执行器包名
     */
    @FormFieldConfig(fieldCode = "executor_class_name", fieldName = "执行器名称", fieldParentName = MONITOR_BASIC_MESSAGE_NAME)
    @Column(columnName = "executor_class_name", columnType = ColumnType.VARCHAR, length = SqlConstants.DB_NAME_SIZE)
    private String executorClassName;
    /**
     * 执行Sql语句
     */
    @Column(columnName = "execute_sql", columnType = ColumnType.LONG_TEXT, comment = "执行SQL")
    @FormFieldConfig(fieldCode = "execute_sql", fieldName = "执行SQL", config = @FieldConfig(appendCss = FieldConfigConstants.CSS_HALF_SCREEN_COL),
            elementCode = DrivenElementConstants.BIG_INPUT_ELEMENT, isTableEnable = false, fieldParentName = BaseMonitorPO.DETAIL_BASIC_MESSAGE_NAME)
    private String executeSql;
    /**
     * 执行参数
     */
    @Column(columnName = "execute_params", columnType = ColumnType.LONG_TEXT, comment = "执行参数")
    @FormFieldConfig(fieldCode = "execute_params", fieldName = "执行参数", config = @FieldConfig(appendCss = FieldConfigConstants.CSS_HALF_SCREEN_COL),
            elementCode = DrivenElementConstants.BIG_INPUT_ELEMENT, isTableEnable = false, fieldParentName = BaseMonitorPO.DETAIL_BASIC_MESSAGE_NAME)
    private String executeParams;
    /**
     * 返回结果
     */
    @Column(columnName = "return_results", columnType = ColumnType.LONG_TEXT, comment = "返回结果")
    @FormFieldConfig(fieldCode = "return_results", fieldName = "返回结果", config = @FieldConfig(appendCss = FieldConfigConstants.CSS_HALF_SCREEN_COL),
            elementCode = DrivenElementConstants.BIG_INPUT_ELEMENT, isTableEnable = false, fieldParentName = BaseMonitorPO.DETAIL_BASIC_MESSAGE_NAME)
    private String returnResults;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getConvertClassName() {
        return convertClassName;
    }

    public void setConvertClassName(String convertClassName) {
        this.convertClassName = convertClassName;
    }

    public Long getExecutorDuration() {
        return executorDuration;
    }

    public void setExecutorDuration(Long executorDuration) {
        this.executorDuration = executorDuration;
    }

    public String getIsExecutorSuccess() {
        return isExecutorSuccess;
    }

    public void setIsExecutorSuccess(String isExecutorSuccess) {
        this.isExecutorSuccess = isExecutorSuccess;
    }

    public String getExecutorClassName() {
        return executorClassName;
    }

    public void setExecutorClassName(String executorClassName) {
        this.executorClassName = executorClassName;
    }

    public String getExecuteSql() {
        return executeSql;
    }

    public void setExecuteSql(String executeSql) {
        this.executeSql = executeSql;
    }

    public String getExecuteParams() {
        return executeParams;
    }

    public void setExecuteParams(String executeParams) {
        this.executeParams = executeParams;
    }

    public String getReturnResults() {
        return returnResults;
    }

    public void setReturnResults(String returnResults) {
        this.returnResults = returnResults;
    }
}

监控工厂实现

java 复制代码
package com.flycoding.monitor.factory;

import com.flycoding.biz.manage.constants.ManageDictionaryConstants;
import com.flycoding.monitor.entity.MonitorSqlPO;
import com.flycoding.monitor.entity.base.BaseMonitorPO;
import com.flycoding.monitor.factory.base.BaseMonitorFactory;
import com.flycoding.drivenlibrary.engine.config.DrivenEngineConfig;
import com.flycoding.drivenlibrary.engine.config.constants.DrivenConstants;
import com.flycoding.drivenlibrary.engine.config.factory.ClassAliasFactory;
import com.flycoding.utillibrary.BasicUtils;
import com.flycoding.utillibrary.date.TimeUtils;
import com.flycoding.utillibrary.date.enums.DateStyle;
import com.flycoding.utillibrary.java.JSONUtils;
import com.flycoding.utillibrary.java.ThrowableUtil;
import com.flycoding.utillibrary.strings.StringUtils;

/**
 * 监控SQL的工厂类
 *
 * @author 赵屈犇
 * @version 1.0
 * @date 创建时间: 2020/10/8 20:50
 */
public class MonitorSqlFactory extends BaseMonitorFactory<MonitorSqlFactory> {

    /**
     * 查询结果
     */
    private Object results;
    /**
     * 请求参数
     */
    private Object[] params;
    /**
     * 是否执行成功
     */
    private boolean isSuccess;
    /**
     * 转换的class
     */
    private Class convertClass;
    /**
     * 执行sql  执行器扩展类
     */
    private String sql, executorClassName;
    /**
     * 执行结果集  sql   执行参数
     */
    private boolean isReturnResults, isSaveSql, isExecuteParams;

    public static MonitorSqlFactory builder() {
        return new MonitorSqlFactory();
    }

    private MonitorSqlFactory() {
        super();
        isSaveSql = DrivenEngineConfig.getConfigValue(prefix + DrivenConstants.MonitorConstants.IS_SAVE_SQL, true);
        isReturnResults = DrivenEngineConfig.getConfigValue(prefix + DrivenConstants.MonitorConstants.IS_SAVE_RETURN_RESULTS, true);
        isExecuteParams = DrivenEngineConfig.getConfigValue(prefix + DrivenConstants.MonitorConstants.IS_SAVE_EXECUTE_PARAMS, true);
    }

    /**
     * sql语句
     *
     * @param sql
     * @return
     */
    public MonitorSqlFactory sql(String sql) {
        if (isMonitor && isSaveSql) {
            this.sql = sql;
        }
        return this;
    }

    /**
     * 执行结果
     *
     * @param results
     * @return
     */
    public MonitorSqlFactory results(Object results) {
        if (isMonitor && isReturnResults) {
            this.results = results;
        }
        return this;
    }

    /**
     * 请求参数
     *
     * @param params
     * @return
     */
    public MonitorSqlFactory params(Object[] params) {
        if (isMonitor && isExecuteParams) {
            this.params = params;
        }
        return this;
    }

    /**
     * 是否执行成功
     *
     * @param isSuccess
     * @return
     */
    public MonitorSqlFactory success(boolean isSuccess) {
        this.isSuccess = isSuccess;
        return this;
    }

    /**
     * 转换class类
     *
     * @param convertClass
     * @return
     */
    public MonitorSqlFactory convertClass(Class convertClass) {
        this.convertClass = convertClass;
        return this;
    }

    /**
     * 执行器class
     *
     * @param executorClassName
     * @return
     */
    public MonitorSqlFactory executorClassName(String executorClassName) {
        this.executorClassName = executorClassName;
        return this;
    }

    @Override
    protected BaseMonitorPO getMonitorInfo(long duration, MonitorFileFactory monitorFileFactory) throws Exception {
        MonitorSqlPO monitorInfo = new MonitorSqlPO();
        // 执行器类全名
        if (StringUtils.isNotEmpty(executorClassName)) {
            monitorInfo.setExecutorClassName(executorClassName);
        }
        // 是否执行成功
        monitorInfo.setIsExecutorSuccess(BasicUtils.getEnableCode(isSuccess));
        // 转换类
        monitorInfo.setConvertClassName(ClassAliasFactory.getClassName(convertClass));
        // 存储sql语句
        if (isSaveSql) {
            monitorInfo.setExecuteSql(sql);
        }
        // 存储请求参数
        if (isExecuteParams) {
            monitorInfo.setExecuteParams(JSONUtils.toJSON(params));
        }
        // 存储返回结果
        if (isReturnResults) {
            monitorInfo.setReturnResults(JSONUtils.toJSON(results));
        }
        if (isOutputConsole) {
            StringBuffer content = new StringBuffer("====================").append(TimeUtils.getNowTimeString(DateStyle.YYYY_MM_DD_HH_MM_SS_SSS.getValue()))
                    .append("===============").append("\nSQL语句:\n")
                    .append(sql).append("\n执行参数:\n").append(JSONUtils.toJSON(params))
                    .append("\n执行结果:\n").append(JSONUtils.toJSON(results));
            if (throwable != null) {
                content.append("\n错误信息:\n").append(ThrowableUtil.throwableConvertString(throwable));
            }
            content.append("\n==========================执行时长:").append(duration).append("==========================");
            if (isSuccess) {
                System.out.println(content);
            } else {
                System.err.println(content);
            }
        }
        // 设置执行时长
        monitorInfo.setExecutorDuration(duration);
        return monitorInfo;
    }

    @Override
    protected String getMonitorConfigKey() {
        return "sql";
    }

    @Override
    protected String getMonitorChannelCode() {
        return ManageDictionaryConstants.ChannelDictionary.MONITOR_SQL;
    }

}

此工厂,实现了sql记录功能。

相关推荐
wclass-zhengge7 分钟前
数据结构篇(绪论)
java·数据结构·算法
何事驚慌8 分钟前
2024/10/5 数据结构打卡
java·数据结构·算法
结衣结衣.8 分钟前
C++ 类和对象的初步介绍
java·开发语言·数据结构·c++·笔记·学习·算法
TJKFYY10 分钟前
Java.数据结构.HashSet
java·开发语言·数据结构
kylinxjd12 分钟前
spring boot发送邮件
java·spring boot·后端·发送email邮件
OLDERHARD20 分钟前
Java - MyBatis(上)
java·oracle·mybatis
杨荧21 分钟前
【JAVA开源】基于Vue和SpringBoot的旅游管理系统
java·vue.js·spring boot·spring cloud·开源·旅游
zaim12 小时前
计算机的错误计算(一百一十四)
java·c++·python·rust·go·c·多项式
2401_857439693 小时前
Spring Boot新闻推荐系统:用户体验优化
spring boot·后端·ux
hong_zc4 小时前
算法【Java】—— 二叉树的深搜
java·算法