package com.linkedin.thirdeye.tools;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FetchAutoTuneResult {
private static final Logger LOG = LoggerFactory.getLogger(FetchAutoTuneResult.class);
private static final String CSVSUFFIX = ".csv";
private static final Integer DEFAULT_NEXPECTEDANOMALIES = 10;
private static final String AUTOTUNE = "AUTOTUNE";
private static final String INITTUNE = "INITTUNE";
/**
* Tool to fetch auto tune results using auto tune endpoint based on collection;
* evaluate alert filter using evaluation endpoint
* @param args
* args[0]: Mode of AutoTune, default value is: AUTOTUNE, (If initiate auto tuning, use INITTUNE)
* args[1]: Start time of merged anomaly in ISO time format
* args[2]: End time of merged anomaly in ISO time format
* args[3]: Path to Persistence File
* args[4]: Collection Name
* args[6]: File directory (read and write file)
* args[7]: Holiday periods to remove from dataset. Holiday starts in ISO time format: start1,start2,...
* args[8]: Holiday periods to remove from dataset. Holiday ends in format: end1,end2,...
* @throws Exception
*/
public static void main(String[] args) throws Exception{
if(args.length < 8){
LOG.error("Error: Insufficient number of arguments", new IllegalArgumentException());
return;
}
String AUTOTUNE_MODE = args[0];
String STARTTIME = args[1];
String ENDTIME = args[2];
String path2PersistenceFile = args[3];
String Collection = args[4];
String DIR_TO_FILE = args[5];
String holidayStarts = args[6];
String holidayEnds = args[7];
AutoTuneAlertFilterTool executor = new AutoTuneAlertFilterTool(new File(path2PersistenceFile));
List<Long> functionIds = executor.getAllFunctionIdsByCollection(Collection);
if(AUTOTUNE_MODE.equals(AUTOTUNE)){
reTuneAndEvalToCSVByCollection(executor, functionIds, STARTTIME, ENDTIME, holidayStarts, holidayEnds, DIR_TO_FILE + Collection + CSVSUFFIX);
} else if (AUTOTUNE_MODE.equals(INITTUNE)){
initFilterAndEvalToCSVByCollection(executor, functionIds, STARTTIME, ENDTIME, holidayStarts, holidayEnds, DIR_TO_FILE + Collection + CSVSUFFIX);
} else {
System.out.println("Error! no such autotune mode!");
}
}
/**
* Tool to retune alert filter
* @param executor AutoTuneAlertFilterTool class
* @param functionIds a list of functionIds to retune
* @param STARTTIME start time to tune in ISO format
* @param ENDTIME end time to tune in ISO format
* @param holidayStarts holidays anomalies can be removed: the list of holiday starts
* @param holidayEnds holidays anomalies can be removed: the list of holiday starts
* @param fileName the file name to write to
* @throws Exception
*/
public static void reTuneAndEvalToCSVByCollection(AutoTuneAlertFilterTool executor, List<Long> functionIds,
String STARTTIME, String ENDTIME, String holidayStarts, String holidayEnds, String fileName)
throws Exception {
Map<String, String> outputMap = new HashMap<>();
for(Long functionId : functionIds){
StringBuilder outputVal = new StringBuilder();
// evaluate current alert filter
String origEvals = executor.evalAnomalyFunctionAlertFilterToEvalNode(functionId, STARTTIME, ENDTIME, holidayStarts, holidayEnds).toCSVString();
Long autotuneId = Long.valueOf(executor.getTunedAlertFilterByFunctionId(functionId, STARTTIME, ENDTIME, AUTOTUNE, holidayStarts, holidayEnds));
boolean isUpdated = autotuneId != -1;
String tunedEvals = "";
if(isUpdated){
// after tuning, evaluate tuned results by autotuneId
tunedEvals = executor.evalAutoTunedAlertFilterToEvalNode(autotuneId, STARTTIME, ENDTIME, holidayStarts, holidayEnds).toCSVString();
}
outputVal.append(origEvals)
.append(isUpdated)
.append(",")
.append(tunedEvals);
outputMap.put(String.valueOf(functionId), outputVal.toString());
}
// write to file
String header = "FunctionId" + "," + AutoTuneAlertFilterTool.EvaluationNode.getCSVSchema() + "," + "isModelUpdated" + "," +AutoTuneAlertFilterTool.EvaluationNode.getCSVSchema();
executor.writeMapToCSV(outputMap, fileName, header);
LOG.info("Write evaluations to file: {}", fileName);
}
/**
* Tool to initiate alert filter
* @param executor AutoTuneAlertFilterTool class
* @param functionIds a list of functionIds to retune
* @param STARTTIME start time to tune in ISO format
* @param ENDTIME end time to tune in ISO format
* @param holidayStarts holidays anomalies can be removed: the list of holiday starts
* @param holidayEnds holidays anomalies can be removed: the list of holiday starts
* @param fileName the file name to write to
* @throws Exception
*/
public static void initFilterAndEvalToCSVByCollection(AutoTuneAlertFilterTool executor, List<Long> functionIds,
String STARTTIME, String ENDTIME, String holidayStarts, String holidayEnds, String fileName) throws Exception {
Map<String, String> outputMap = new HashMap<>();
for (Long functionId : functionIds) {
StringBuilder outputVal = new StringBuilder();
// evaluate current alert filter
String origEvals =
executor.evalAnomalyFunctionAlertFilterToEvalNode(functionId, STARTTIME, ENDTIME, holidayStarts, holidayEnds).toCSVString();
long autotuneId = Long.valueOf(
executor.getInitAutoTuneByFunctionId(functionId, STARTTIME, ENDTIME, AUTOTUNE, DEFAULT_NEXPECTEDANOMALIES,
holidayStarts, holidayEnds));
boolean isUpdated = autotuneId != -1;
String tunedEvals = "";
if (isUpdated) {
// after tuning, evaluate tuned results by autotuneId
tunedEvals =
executor.evalAutoTunedAlertFilterToEvalNode(autotuneId, STARTTIME, ENDTIME, holidayStarts, holidayEnds).toCSVString();
}
outputVal.append(origEvals).append(isUpdated).append(",").append(tunedEvals);
outputMap.put(String.valueOf(functionId), outputVal.toString());
}
// write to file
String header = "FunctionId" + "," + AutoTuneAlertFilterTool.EvaluationNode.getCSVSchema() + "," + "isModelUpdated" + "," +AutoTuneAlertFilterTool.EvaluationNode.getCSVSchema();
executor.writeMapToCSV(outputMap, fileName, header);
LOG.info("Write evaluations to file: {}", fileName);
}
}