教程 | Datavines 自定義數(shù)據(jù)質(zhì)量檢查規(guī)則(Metric)

Metric 是 Datavines 中一個(gè)核心概念,一個(gè) Metric 表示一個(gè)數(shù)據(jù)質(zhì)量檢查規(guī)則,比如空值檢查和表行數(shù)檢查都是一個(gè)規(guī)則。Metric 采用插件化設(shè)計(jì),用戶可以根據(jù)自己的需求來(lái)實(shí)現(xiàn)一個(gè) Metric 。下面我們來(lái)詳細(xì)講解一下如何自定義Metric。

第一步

我們先了解下幾個(gè)接口和抽象類,它們是實(shí)現(xiàn)自定義 Metric 的關(guān)鍵。

SqlMetric 接口

SqlMetric接口中定義了規(guī)則的各種屬性和操作的接口。

@SPI
public interface SqlMetric {
    // 中文名
    String getName();
    // 英文名
    String getZhName();
    // 根據(jù)系統(tǒng)的語(yǔ)言進(jìn)行名字返回
    default String getNameByLanguage(boolean isEn) {
        return isEn ? getName() : getZhName();
    }
    // 規(guī)則屬于哪個(gè)維度,比如準(zhǔn)確性、唯一性等等
    MetricDimension getDimension();
    // 規(guī)則的類型,包括單表檢查、單表自定義檢查
    MetricType getType();
    // 規(guī)則的級(jí)別,比如表級(jí)別、列級(jí)別
    default MetricLevel getLevel() {
        return MetricLevel.NONE;
    }
    // 是否支持錯(cuò)誤數(shù)據(jù)輸出
    boolean isInvalidateItemsCanOutput();

    /**
     * 獲取不符合規(guī)則的數(shù)據(jù)的SQL語(yǔ)句
     * @return ExecuteSql
     */
    ExecuteSql getInvalidateItems(String uniqueKey);

    /**
     * 計(jì)算實(shí)際值的SQL語(yǔ)句
     * @return ExecuteSql
     */
    ExecuteSql getActualValue(String uniqueKey);

    /**
     * 實(shí)際值的字段名
     */
    default String getActualName() {
        return "actual_value";
    }
    // 實(shí)際值的類型,比如數(shù)字,百分比或者列表
    default String getActualValueType() {
        return MetricActualValueType.COUNT.getDescription();
    }
    // 對(duì)參數(shù)進(jìn)行檢查并輸出檢查結(jié)果
    CheckResult validateConfig(Map<String,Object> config);
    //規(guī)則所需要的參數(shù)
    Map<String, ConfigItem> getConfigMap();
    //構(gòu)造規(guī)則前需要做的檢查
    void prepare(Map<String,String> config);

    default String getIssue() {
        return "";
    }
    // 適合哪些字段類型
    List<DataVinesDataType> suitableType();
    // 是否支持多選,比如表行數(shù)檢查支持多張表
    default boolean supportMultiple() {
        return false;
    }
    // 對(duì)規(guī)則參數(shù)的重新構(gòu)造,配合表行數(shù)多張表檢查
    default List<Map<String,Object>> getMetricParameter(Map<String,Object> metricParameter) {
        return Collections.singletonList(metricParameter);
    }
}

BaseSingleTable 抽象類

BaseSingleTable是實(shí)現(xiàn)了 SqlMetric 接口的抽象類,實(shí)現(xiàn)了表級(jí)別檢查規(guī)則中所需要參數(shù)的添加、錯(cuò)誤數(shù)據(jù)SQL語(yǔ)句構(gòu)造和實(shí)際值計(jì)算SQL語(yǔ)句構(gòu)造和對(duì)過濾條件的處理等。

  • 這里定義了獲取不符合規(guī)則的數(shù)據(jù)的基礎(chǔ)SQL語(yǔ)句,判斷類型的規(guī)則比如正則表達(dá)式檢查和枚舉值檢查,只需要在基礎(chǔ)SQL語(yǔ)句后面添加過濾條件即可。
    protected StringBuilder invalidateItemsSql = new StringBuilder("select * from ${table}");
  • 實(shí)際值計(jì)算SQL語(yǔ)句默認(rèn)是計(jì)算不符合規(guī)則數(shù)據(jù)的行數(shù)
String actualValueSql = "select count(1) as actual_value_"+ uniqueKey +" from ${invalidate_items_table}"; 
  • 計(jì)算平均值、匯總值等統(tǒng)計(jì)類型的規(guī)則需要重新實(shí)現(xiàn)getActualValue()中的ExecuteSql
public abstract class BaseSingleTable implements SqlMetric {
    // 這里定義了獲取不符合規(guī)則的數(shù)據(jù)的基礎(chǔ) SQL 語(yǔ)句,判斷類的規(guī)則比如正則表達(dá)式和枚舉值檢查,只需要在基礎(chǔ)SQL后面添加過濾條件即可。
    protected StringBuilder invalidateItemsSql = new StringBuilder("select * from ${table}");

    protected List<String> filters = new ArrayList<>();

    protected HashMap<String,ConfigItem> configMap = new HashMap<>();

    protected Set<String> requiredOptions = new HashSet<>();

    public BaseSingleTable() {
        configMap.put("table",new ConfigItem("table", "表名", "table"));
        configMap.put("filter",new ConfigItem("filter", "過濾條件", "filter"));

        requiredOptions.add("table");
    }

    @Override
    public ExecuteSql getInvalidateItems(String uniqueKey) {
        ExecuteSql executeSql = new ExecuteSql();
        executeSql.setResultTable("invalidate_items_" + uniqueKey);
        executeSql.setSql(invalidateItemsSql.toString());
        executeSql.setErrorOutput(isInvalidateItemsCanOutput());
        return executeSql;
    }

    @Override
    public ExecuteSql getActualValue(String uniqueKey) {
        ExecuteSql executeSql = new ExecuteSql();
        executeSql.setResultTable("invalidate_count_" + uniqueKey);
        String actualValueSql = "select count(1) as actual_value_"+ uniqueKey +" from ${invalidate_items_table}";
        executeSql.setSql(actualValueSql);
        executeSql.setErrorOutput(false);
        return executeSql;
    }

    @Override
    public CheckResult validateConfig(Map<String, Object> config) {
        return ConfigChecker.checkConfig(config, requiredOptions);
    }

    @Override
    public void prepare(Map<String, String> config) {
        if (config.containsKey("filter")) {
            filters.add(config.get("filter"));
        }

        addFiltersIntoInvalidateItemsSql();
    }

    private void addFiltersIntoInvalidateItemsSql() {
        if (filters.size() > 0) {
            invalidateItemsSql.append(" where ").append(String.join(" and ", filters));
        }
    }

    @Override
    public MetricLevel getLevel() {
        return MetricLevel.TABLE;
    }
}

BaseSingleTableColumn 抽象類

BaseSingleTableColumn是列級(jí)別的抽象實(shí)現(xiàn)類,主要是添加列級(jí)別規(guī)則的通用參數(shù)。

public abstract class BaseSingleTableColumn extends BaseSingleTable {

    public BaseSingleTableColumn() {
        super();
        configMap.put("column",new ConfigItem("column", "列名", "column"));
        requiredOptions.add("column");
    }

    @Override
    public Map<String, ConfigItem> getConfigMap() {
        return configMap;
    }

    @Override
    public MetricLevel getLevel() {
        return MetricLevel.COLUMN;
    }

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

第二步

了解完上面的三個(gè)基礎(chǔ)類以后,自定義一個(gè)Metric就變得格外簡(jiǎn)單了。

以 枚舉值檢查 規(guī)則為例來(lái)講解

  • 判斷要實(shí)現(xiàn)的規(guī)則的級(jí)別,因?yàn)槊杜e值檢查是列級(jí)別,所以繼承 BaseSingleTableColumn 即可。
  • 在構(gòu)造函數(shù)中的configMap添加enum_list參數(shù)用于返回給前端進(jìn)行展示,在requiredOptions添加enum_list用于參數(shù)的檢查。
  • 實(shí)現(xiàn)英文名、中文名、規(guī)則維度、規(guī)則類型這些基礎(chǔ)的屬性。
  • 因?yàn)槊杜e值檢查規(guī)則是為了找出在枚舉值列表中的數(shù)據(jù),所以只需要在fileters這個(gè)數(shù)組里面加入(${column} in ( ${enum_list} ))prepare()方法會(huì)自動(dòng)進(jìn)行不符合規(guī)則的SQL語(yǔ)句構(gòu)造。
  • 實(shí)現(xiàn)suitableType()方法添加規(guī)則適用的字段類型。
public class ColumnInEnums extends BaseSingleTableColumn {

    public ColumnInEnums(){
        super();
        configMap.put("enum_list",new ConfigItem("enum_list", "枚舉值列表", "enum_list"));
        requiredOptions.add("enum_list");
    }

    @Override
    public String getName() {
        return "column_in_enums";
    }

    @Override
    public String getZhName() {
        return "枚舉值檢查";
    }

    @Override
    public MetricDimension getDimension() {
        return MetricDimension.EFFECTIVENESS;
    }

    @Override
    public MetricType getType() {
        return MetricType.SINGLE_TABLE;
    }

    @Override
    public boolean isInvalidateItemsCanOutput() {
        return true;
    }

    @Override
    public void prepare(Map<String, String> config) {
        if (config.containsKey("enum_list") && config.containsKey("column")) {
            filters.add(" (${column} in ( ${enum_list} )) ");
        }
        super.prepare(config);
    }

    @Override
    public List<DataVinesDataType> suitableType() {
        return Arrays.asList(DataVinesDataType.NUMERIC_TYPE, DataVinesDataType.STRING_TYPE, DataVinesDataType.DATE_TIME_TYPE);
    }
}

第三步

非常重要的一步

  • 在 resources 目錄下創(chuàng)建META-INF/plugins目錄。
  • 在 plugins 目錄下創(chuàng)建文件并且命名為io.datavines.metric.api.SqlMetric。
  • 在文件中添加column_in_enums=io.datavines.metric.plugin.ColumnInEnums

第四步

打包成jar放到 datavines 目錄下的libs目錄下即可。

收工!自定義 Metric 就這樣輕松搞定了。

加入我們

Datavines 的目標(biāo)是成為更好的數(shù)據(jù)可觀測(cè)性領(lǐng)域的開源項(xiàng)目,為更多的用戶去解決元數(shù)據(jù)管理和數(shù)據(jù)質(zhì)量管理中遇到的問題。在此我們真誠(chéng)歡迎更多的貢獻(xiàn)者參與到社區(qū)建設(shè)中來(lái),和我們一起成長(zhǎng),攜手共建更好的社區(qū)。

關(guān)于Datavane

Datavane是一個(gè)專注于大數(shù)據(jù)領(lǐng)域的開源組織(社區(qū)),由一群大數(shù)據(jù)領(lǐng)域優(yōu)秀的開源項(xiàng)目作者共同創(chuàng)建,旨在幫助開源項(xiàng)目作者更好的建設(shè)項(xiàng)目、為大眾提供高質(zhì)量的開源軟件,宗旨是:只為做一個(gè)好軟件。目前已經(jīng)聚集了一批優(yōu)質(zhì)的開源項(xiàng)目,涉及到數(shù)據(jù)集成、大數(shù)據(jù)組件管理、數(shù)據(jù)質(zhì)量等。

Datavane 社區(qū)中,所有的項(xiàng)目都是開源開放的,代碼質(zhì)量和架構(gòu)設(shè)計(jì)優(yōu)質(zhì)的潛力項(xiàng)目。社區(qū)保持開放中立、協(xié)作創(chuàng)造、堅(jiān)持精品,鼓勵(lì)所有的開發(fā)者、用戶和貢獻(xiàn)者積極參與我們的社區(qū)、共同合作,創(chuàng)新創(chuàng)造,建設(shè)一個(gè)更加強(qiáng)大的開源社區(qū)。

Github: https://github.com/datavane

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容