規(guī)則監(jiān)控針對的是對知識包調(diào)用的監(jiān)控。在URule Pro當(dāng)中,規(guī)則是放在知識包是調(diào)用的,所以規(guī)則監(jiān)控也就是對知識包的監(jiān)控。
點開每個項目的知識包節(jié)點,可以看到已定義的知識包的操作列里都有一個用于配置監(jiān)控信息的按鈕,如下圖所示:
點擊該按鈕,即可打開針對當(dāng)前知識包的監(jiān)控配置窗口,如下圖所示:
勾選“啟用對當(dāng)前知識包的調(diào)用監(jiān)控”選項,即可開始配置具體的要監(jiān)控的信息。
勾選“啟用對當(dāng)前知識包的調(diào)用監(jiān)控”選項后,就可以看到具體可配置的監(jiān)控選項,如下圖所示:
整個監(jiān)控的選項分為三個部分,分別是監(jiān)控內(nèi)容、輸入數(shù)據(jù)以及輸出數(shù)據(jù)。
監(jiān)控內(nèi)容部分主要是對系統(tǒng)日志部分內(nèi)容進行的監(jiān)控,這部分內(nèi)容依賴于當(dāng)前知識包中規(guī)則是否開啟“允許調(diào)試信息輸出”屬性以及運行項目中有沒有將urule.debug屬性配置為true, 只有這兩個都開啟了,那么監(jiān)控內(nèi)容部分配置才有意義,否則監(jiān)控到的內(nèi)容皆為空。
之前我們對規(guī)則中“允許調(diào)試信息輸出”屬性以及運行項目中urule.debug屬性有過介紹,要求在生產(chǎn)環(huán)境中一定要把urule.debug屬性設(shè)置為false,這樣所有的調(diào)試信息都將不再產(chǎn)生,就不會對性能產(chǎn)生影響。
第二部分和第三部分中會把當(dāng)前知識包中用到的所有變量及參數(shù)都羅列出來,我們需要做的就是根據(jù)需要進行勾選,這樣在監(jiān)控運行時會所勾選的輸入以及輸出信息都記錄下來,給我們自定義的監(jiān)控實現(xiàn)類使用。
配置好監(jiān)控內(nèi)容后,接下來還需要編寫具體的監(jiān)控數(shù)據(jù)處理實現(xiàn)類,該類編寫完成后需要配置到Spring上下文中,使其成為一個標(biāo)準(zhǔn)的Spring Bean,這樣引擎才能發(fā)現(xiàn)并使用它,該類接口源碼如下:
package com.bstek.urule.runtime.monitor;
/**
* @author Jacky.gao
* @since 2018年12月17日
*/
public interface InvokeMonitor {
void doMonitor(MonitorData data);
}
這里可能有人會有疑問,知識包監(jiān)控為什么還要編寫接口實現(xiàn)類呢?這是因為對于URule Pro來說,他要做的工作就是把要監(jiān)控的數(shù)據(jù)準(zhǔn)備好,然后交給用戶去處理,因為URule Pro本身并不知道該如何處理這些要監(jiān)控的數(shù)據(jù),所以需要用戶編寫實現(xiàn)類來決定如何處理這些監(jiān)控數(shù)據(jù)。
對于接口實現(xiàn)類來說,可以把這些監(jiān)控數(shù)據(jù)存儲到傳統(tǒng)的數(shù)據(jù)庫中,也可以存儲到key-value數(shù)據(jù)庫中,可以直接存,也可以開啟獨立線程異步去存。
在這個接口中,需要實現(xiàn)的方法只有一個,參數(shù)也只有一個,在這個MonitorData參數(shù)里,已經(jīng)把上述知識包監(jiān)控配置里要求監(jiān)控的內(nèi)容都準(zhǔn)備好了,我們直接調(diào)用即可,MonitorData源碼如下:
package com.bstek.urule.runtime.monitor;
import java.util.Date;
import java.util.List;
import com.bstek.urule.model.rete.RuleData;
import com.bstek.urule.runtime.log.FlowNodeLog;
import com.bstek.urule.runtime.log.Log;
import com.bstek.urule.runtime.log.MatchedRuleLog;
/**
* @author Jacky.gao
* @since 2018年12月18日
*/
public interface MonitorData {
/**
* @return 返回當(dāng)前監(jiān)控的知識包名稱信息:項目名稱/知識包ID
*/
String getPackageInfo();
/**
* @return 返回規(guī)則運行總的耗時,單位為毫秒
*/
long getTotalDuration();
/**
* @return 返回當(dāng)前知識包版本,如果當(dāng)前知識包沒有發(fā)布版本,則該值為空
*/
String getVersion();
/**
* @return 返回當(dāng)前知識包版本備注信息,如果當(dāng)前知識包沒有發(fā)布版本,則該值為空
*/
String getVersionComment();
/**
* @return 返回當(dāng)前知識包版本創(chuàng)建日期,如果當(dāng)前知識包沒有發(fā)布版本,則該值為空
*/
Date getVersionCreateDate();
/**
* @return 返回當(dāng)前知識包版本創(chuàng)建人,如果當(dāng)前知識包沒有發(fā)布版本,則該值為空
*/
String getVersionCreateUser();
/**
* @return 返回所有匹配的規(guī)則對象信息
*/
List<MatchedRuleLog> getMatchedRuleList();
/**
* @return 返回所有不匹配的規(guī)則對象信息
*/
List<RuleData> getNotMatchRuleList();
/**
* @return 返回所有觸發(fā)了的規(guī)則流節(jié)點信息(如果當(dāng)前有規(guī)則流的話)
*/
List<FlowNodeLog> getFiredFlowNodeList();
/**
* @return 返回當(dāng)前執(zhí)行的知識包中監(jiān)控是否允許顯示日志信息
*/
boolean isShowLog();
/**
* @return 返回當(dāng)前執(zhí)行的知識包中是否允許顯示所有匹配的規(guī)則信息
*/
boolean isShowMatchedRuleList();
/**
* @return 返回當(dāng)前執(zhí)行的知識包中是否要顯示不匹配的規(guī)則信息
*/
boolean isShowNotMatchRuleList();
/**
* @return 返回當(dāng)前執(zhí)行的知識包中是否顯示觸發(fā)的規(guī)則節(jié)點信息(如果當(dāng)前有規(guī)則流的話)
*/
boolean isShowFiredFlowNodeList();
/**
* @return 返回所有輸入日志信息(如果當(dāng)前配置的日志信息輸出的話)
*/
List<Log> getLogs();
/**
* @return 返回指定的輸入信息
*/
List<IOData> getInputData();
/**
* @return 返回規(guī)則計算后指定的輸出信息
*/
List<IOData> getOutputData();
}
可以看到,在MonitorData接口中,可以獲取到當(dāng)前知識包監(jiān)控配置的所有信息,這樣在記錄這個信息時可以先判斷系統(tǒng)是否配置了要監(jiān)控這項信息,以防獲取到的信息為空情況發(fā)生。下面的這個實現(xiàn)類在輸出要監(jiān)控的信息時就加了判斷:
package test;
import com.bstek.urule.runtime.monitor.InvokeMonitor;
import com.bstek.urule.runtime.monitor.MonitorData;
/**
* @author Jacky.gao
* @since 2018年12月17日
*/
public class TestInvokeMonitor implements InvokeMonitor {
public void doMonitor(MonitorData data) {
if(data.isShowLog()) {
System.out.println("日志:"+data.getLogs());
}
if(data.isShowFiredFlowNodeList()) {
System.out.println("觸發(fā)的規(guī)則節(jié)點列表:"+data.getFiredFlowNodeList());
}
if(data.isShowMatchedRuleList()) {
System.out.println("匹配的規(guī)則列表:"+data.getMatchedRuleList());
}
if(data.isShowNotMatchRuleList()) {
System.out.println("不匹配的規(guī)則列表:"+data.getNotMatchRuleList());
}
System.out.println("耗時:"+data.getTotalDuration());
System.out.println("packageInfo:"+data.getPackageInfo());
System.out.println("輸入數(shù)據(jù):"+data.getInputData());
System.out.println("輸出數(shù)據(jù):"+data.getOutputData());
}
}
需要注意的是,如果我們使用URule Pro的方式為客戶端服務(wù)器模式,同時又想對知識包調(diào)用進行監(jiān)控,那么InvokeMonitor的實現(xiàn)類則必須配置在知識包實際運行的客戶端,原因很簡單,因為知識包是在客戶端運行,
要監(jiān)控知識包,必須要保證當(dāng)前知識包運行環(huán)境里能檢測到InvokeMonitor的實現(xiàn)類,所以需要這么配置。
更多建議: