Metric 是 Datavines 中一個核心概念冷尉,一個 Metric 表示一個數(shù)據(jù)質量檢查規(guī)則漱挎,比如空值檢查和表行數(shù)檢查都是一個規(guī)則。Metric 采用插件化設計雀哨,用戶可以根據(jù)自己的需求來實現(xiàn)一個 Metric 磕谅。下面我們來詳細講解一下如何自定義Metric
。
第一步
我們先了解下幾個接口和抽象類雾棺,它們是實現(xiàn)自定義 Metric 的關鍵膊夹。
SqlMetric 接口
SqlMetric
接口中定義了規(guī)則的各種屬性和操作的接口。
@SPI
public interface SqlMetric {
// 中文名
String getName();
// 英文名
String getZhName();
// 根據(jù)系統(tǒng)的語言進行名字返回
default String getNameByLanguage(boolean isEn) {
return isEn ? getName() : getZhName();
}
// 規(guī)則屬于哪個維度垢村,比如準確性割疾、唯一性等等
MetricDimension getDimension();
// 規(guī)則的類型,包括單表檢查嘉栓、單表自定義檢查
MetricType getType();
// 規(guī)則的級別宏榕,比如表級別、列級別
default MetricLevel getLevel() {
return MetricLevel.NONE;
}
// 是否支持錯誤數(shù)據(jù)輸出
boolean isInvalidateItemsCanOutput();
/**
* 獲取不符合規(guī)則的數(shù)據(jù)的SQL語句
* @return ExecuteSql
*/
ExecuteSql getInvalidateItems(String uniqueKey);
/**
* 計算實際值的SQL語句
* @return ExecuteSql
*/
ExecuteSql getActualValue(String uniqueKey);
/**
* 實際值的字段名
*/
default String getActualName() {
return "actual_value";
}
// 實際值的類型侵佃,比如數(shù)字麻昼,百分比或者列表
default String getActualValueType() {
return MetricActualValueType.COUNT.getDescription();
}
// 對參數(shù)進行檢查并輸出檢查結果
CheckResult validateConfig(Map<String,Object> config);
//規(guī)則所需要的參數(shù)
Map<String, ConfigItem> getConfigMap();
//構造規(guī)則前需要做的檢查
void prepare(Map<String,String> config);
default String getIssue() {
return "";
}
// 適合哪些字段類型
List<DataVinesDataType> suitableType();
// 是否支持多選,比如表行數(shù)檢查支持多張表
default boolean supportMultiple() {
return false;
}
// 對規(guī)則參數(shù)的重新構造馋辈,配合表行數(shù)多張表檢查
default List<Map<String,Object>> getMetricParameter(Map<String,Object> metricParameter) {
return Collections.singletonList(metricParameter);
}
}
BaseSingleTable 抽象類
BaseSingleTable
是實現(xiàn)了 SqlMetric 接口的抽象類抚芦,實現(xiàn)了表級別檢查規(guī)則中所需要參數(shù)的添加、錯誤數(shù)據(jù)SQL語句構造和實際值計算SQL語句構造和對過濾條件的處理等。
- 這里定義了獲取不符合規(guī)則的數(shù)據(jù)的基礎SQL語句叉抡,判斷類型的規(guī)則比如正則表達式檢查和枚舉值檢查尔崔,只需要在基礎SQL語句后面添加過濾條件即可。
protected StringBuilder invalidateItemsSql = new StringBuilder("select * from ${table}");
- 實際值計算SQL語句默認是計算不符合規(guī)則數(shù)據(jù)的行數(shù)
String actualValueSql = "select count(1) as actual_value_"+ uniqueKey +" from ${invalidate_items_table}";
- 計算平均值褥民、匯總值等統(tǒng)計類型的規(guī)則需要重新實現(xiàn)
getActualValue()
中的ExecuteSql
季春。
public abstract class BaseSingleTable implements SqlMetric {
// 這里定義了獲取不符合規(guī)則的數(shù)據(jù)的基礎 SQL 語句,判斷類的規(guī)則比如正則表達式和枚舉值檢查消返,只需要在基礎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
是列級別的抽象實現(xiàn)類,主要是添加列級別規(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;
}
}
第二步
了解完上面的三個基礎類以后宇攻,自定義一個Metric
就變得格外簡單了。
以 枚舉值檢查 規(guī)則為例來講解
- 判斷要實現(xiàn)的規(guī)則的級別倡勇,因為枚舉值檢查是列級別逞刷,所以繼承 BaseSingleTableColumn 即可。
- 在構造函數(shù)中的
configMap
添加enum_list
參數(shù)用于返回給前端進行展示译隘,在requiredOptions
添加enum_list
用于參數(shù)的檢查亲桥。 - 實現(xiàn)英文名、中文名固耘、規(guī)則維度题篷、規(guī)則類型這些基礎的屬性。
- 因為枚舉值檢查規(guī)則是為了找出在枚舉值列表中的數(shù)據(jù)厅目,所以只需要在
fileters
這個數(shù)組里面加入(${column} in ( ${enum_list} ))
番枚,prepare()
方法會自動進行不符合規(guī)則的SQL語句構造。 - 實現(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 的目標是成為更好的數(shù)據(jù)可觀測性領域的開源項目洋丐,為更多的用戶去解決元數(shù)據(jù)管理和數(shù)據(jù)質量管理中遇到的問題。在此我們真誠歡迎更多的貢獻者參與到社區(qū)建設中來挥等,和我們一起成長友绝,攜手共建更好的社區(qū)。
- 項目地址: https://github.com/datavane/datavines
- 問題和建議: https://github.com/datavane/datavines/issues
- 貢獻代碼: https://github.com/datavane/datavines/pulls
關于Datavane
Datavane
是一個專注于大數(shù)據(jù)領域的開源組織(社區(qū))肝劲,由一群大數(shù)據(jù)領域優(yōu)秀的開源項目作者共同創(chuàng)建迁客,旨在幫助開源項目作者更好的建設項目郭宝、為大眾提供高質量的開源軟件,宗旨是:只為做一個好軟件掷漱。目前已經(jīng)聚集了一批優(yōu)質的開源項目粘室,涉及到數(shù)據(jù)集成、大數(shù)據(jù)組件管理卜范、數(shù)據(jù)質量等育特。
在 Datavane
社區(qū)中,所有的項目都是開源開放的先朦,代碼質量和架構設計優(yōu)質的潛力項目。社區(qū)保持開放中立犬缨、協(xié)作創(chuàng)造喳魏、堅持精品,鼓勵所有的開發(fā)者怀薛、用戶和貢獻者積極參與我們的社區(qū)刺彩、共同合作,創(chuàng)新創(chuàng)造枝恋,建設一個更加強大的開源社區(qū)创倔。
Github: https://github.com/datavane