use of javax.ws.rs.POST in project pinot by linkedin.
the class DetectionJobResource method tuneAlertFilter.
/**
*
* @param id anomaly function id
* @param startTime start time of anomalies to tune alert filter
* @param endTime end time of anomalies to tune alert filter
* @param autoTuneType the type of auto tune to invoke (default is "AUTOTUNE")
* @return HTTP response of request: string of alert filter
*/
@POST
@Path("/autotune/filter/{functionId}")
public Response tuneAlertFilter(@PathParam("functionId") long id, @QueryParam("startTime") long startTime, @QueryParam("endTime") long endTime, @QueryParam("autoTuneType") String autoTuneType) {
// get anomalies by function id, start time and end time
AnomalyFunctionDTO anomalyFunctionSpec = DAO_REGISTRY.getAnomalyFunctionDAO().findById(id);
AnomalyFunctionManager anomalyFunctionDAO = DAO_REGISTRY.getAnomalyFunctionDAO();
MergedAnomalyResultManager anomalyMergedResultDAO = DAO_REGISTRY.getMergedAnomalyResultDAO();
List<MergedAnomalyResultDTO> anomalyResultDTOS = anomalyMergedResultDAO.findByStartTimeInRangeAndFunctionId(startTime, endTime, id);
// create alert filter and evaluator
AlertFilter alertFilter = alertFilterFactory.fromSpec(anomalyFunctionSpec.getAlertFilter());
AlertFilterEvaluationUtil evaluator = new AlertFilterEvaluationUtil(alertFilter);
// create alert filter auto tune
AlertFilterAutoTune alertFilterAutotune = alertFilterAutotuneFactory.fromSpec(autoTuneType);
LOG.info("initiated alertFilterAutoTune of Type {}", alertFilterAutotune.getClass().toString());
try {
//evaluate current alert filter (calculate current precision and recall)
evaluator.updatePrecisionAndRecall(anomalyResultDTOS);
LOG.info("AlertFilter of Type {}, has been evaluated with precision: {}, recall: {}", alertFilter.getClass().toString(), evaluator.getPrecision(), evaluator.getRecall());
// get tuned alert filter
Map<String, String> tunedAlertFilter = alertFilterAutotune.tuneAlertFilter(anomalyResultDTOS, evaluator.getPrecision(), evaluator.getRecall());
LOG.info("tuned AlertFilter");
// otherwise do nothing and return alert filter
if (alertFilterAutotune.isUpdated()) {
anomalyFunctionSpec.setAlertFilter(tunedAlertFilter);
anomalyFunctionDAO.update(anomalyFunctionSpec);
LOG.info("Model has been updated");
} else {
LOG.info("Model hasn't been updated because tuned model cannot beat original model");
}
} catch (Exception e) {
LOG.warn("AutoTune throws exception due to: {}", e.getMessage());
}
return Response.ok(alertFilterAutotune.isUpdated()).build();
}
use of javax.ws.rs.POST in project pinot by linkedin.
the class OverrideConfigResource method createOverrideConfig.
@POST
@Path("/override-config/create")
public Response createOverrideConfig(@NotNull @QueryParam("startTime") long startTimeMillis, @NotNull @QueryParam("endTime") long endTimeMillis, @QueryParam("targetLevel") String targetLevelJson, @NotNull @QueryParam("targetEntity") String targetEntity, @QueryParam("overrideProperties") String overridePropertiesJson, @QueryParam("active") boolean active) {
Map<String, List<String>> targetLevel;
if (StringUtils.isEmpty(targetLevelJson)) {
targetLevel = Collections.emptyMap();
} else {
try {
targetLevel = OBJECT_MAPPER.readValue(targetLevelJson, HashMap.class);
} catch (IOException e) {
LOG.error("Invalid JSON string {}", targetLevelJson);
return Response.status(Response.Status.NOT_ACCEPTABLE).build();
}
}
if (StringUtils.isEmpty(targetEntity)) {
LOG.error("Received null for one of the mandatory params \"targetEntity\": {}", targetEntity);
return Response.status(Response.Status.NOT_ACCEPTABLE).build();
}
Map<String, String> overrideProperties;
if (StringUtils.isEmpty(overridePropertiesJson)) {
overrideProperties = Collections.emptyMap();
} else {
try {
overrideProperties = OBJECT_MAPPER.readValue(overridePropertiesJson, HashMap.class);
} catch (IOException e) {
LOG.error("Invalid JSON string {}", overridePropertiesJson);
return Response.status(Response.Status.NOT_ACCEPTABLE).build();
}
}
OverrideConfigDTO overrideConfigDTO = new OverrideConfigDTO();
overrideConfigDTO.setStartTime(startTimeMillis);
overrideConfigDTO.setEndTime(endTimeMillis);
overrideConfigDTO.setTargetLevel(targetLevel);
overrideConfigDTO.setTargetEntity(targetEntity);
overrideConfigDTO.setOverrideProperties(overrideProperties);
overrideConfigDTO.setActive(active);
OverrideConfigManager overrideConfigDAO = DAO_REGISTRY.getOverrideConfigDAO();
// Check if there exists any duplicate override config
List<OverrideConfigDTO> existingOverrideConfigDTOs = overrideConfigDAO.findAllConflictByTargetType(targetEntity, startTimeMillis, endTimeMillis);
for (OverrideConfigDTO existingOverrideConfig : existingOverrideConfigDTOs) {
if (existingOverrideConfig.equals(overrideConfigDTO)) {
LOG.error("Exists a duplicate override config: {}", existingOverrideConfig.toString());
return Response.status(Response.Status.NOT_ACCEPTABLE).build();
}
}
overrideConfigDAO.save(overrideConfigDTO);
return Response.ok().build();
}
use of javax.ws.rs.POST in project pinot by linkedin.
the class AnomalyFunctionResource method analyze.
@POST
@Path("/analyze")
@Consumes(MediaType.APPLICATION_JSON)
public Response analyze(AnomalyFunctionDTO anomalyFunctionSpec, @QueryParam("startTime") Long startTime, @QueryParam("endTime") Long endTime) throws Exception {
// TODO: replace this with Job/Task framework and job tracker page
BaseAnomalyFunction anomalyFunction = anomalyFunctionFactory.fromSpec(anomalyFunctionSpec);
List<Pair<Long, Long>> startEndTimeRanges = anomalyFunction.getDataRangeIntervals(startTime, endTime);
Map<DimensionKey, MetricTimeSeries> dimensionKeyMetricTimeSeriesMap = TimeSeriesUtil.getTimeSeriesForAnomalyDetection(anomalyFunctionSpec, startEndTimeRanges);
List<RawAnomalyResultDTO> anomalyResults = new ArrayList<>();
List<RawAnomalyResultDTO> results = new ArrayList<>();
List<String> collectionDimensions = DAO_REGISTRY.getDatasetConfigDAO().findByDataset(anomalyFunctionSpec.getCollection()).getDimensions();
for (Map.Entry<DimensionKey, MetricTimeSeries> entry : dimensionKeyMetricTimeSeriesMap.entrySet()) {
DimensionKey dimensionKey = entry.getKey();
DimensionMap dimensionMap = DimensionMap.fromDimensionKey(dimensionKey, collectionDimensions);
if (entry.getValue().getTimeWindowSet().size() < 2) {
LOG.warn("Insufficient data for {} to run anomaly detection function", dimensionMap);
continue;
}
try {
// Run algorithm
MetricTimeSeries metricTimeSeries = entry.getValue();
LOG.info("Analyzing anomaly function with dimensionKey: {}, windowStart: {}, windowEnd: {}", dimensionMap, startTime, endTime);
List<RawAnomalyResultDTO> resultsOfAnEntry = anomalyFunction.analyze(dimensionMap, metricTimeSeries, new DateTime(startTime), new DateTime(endTime), new ArrayList<>());
if (resultsOfAnEntry.size() != 0) {
results.addAll(resultsOfAnEntry);
}
LOG.info("{} has {} anomalies in window {} to {}", dimensionMap, resultsOfAnEntry.size(), new DateTime(startTime), new DateTime(endTime));
} catch (Exception e) {
LOG.error("Could not compute for {}", dimensionMap, e);
}
}
if (results.size() > 0) {
List<RawAnomalyResultDTO> validResults = new ArrayList<>();
for (RawAnomalyResultDTO anomaly : results) {
if (!anomaly.isDataMissing()) {
LOG.info("Found anomaly, sev [{}] start [{}] end [{}]", anomaly.getWeight(), new DateTime(anomaly.getStartTime()), new DateTime(anomaly.getEndTime()));
validResults.add(anomaly);
}
}
anomalyResults.addAll(validResults);
}
return Response.ok(anomalyResults).build();
}
use of javax.ws.rs.POST in project pinot by linkedin.
the class AnomalyResource method updateAnomalyMergedResultFeedback.
/**
* @param anomalyResultId : anomaly merged result id
* @param payload : Json payload containing feedback @see com.linkedin.thirdeye.constant.AnomalyFeedbackType
* eg. payload
* <p/>
* { "feedbackType": "NOT_ANOMALY", "comment": "this is not an anomaly" }
*/
@POST
@Path(value = "anomaly-merged-result/feedback/{anomaly_merged_result_id}")
public void updateAnomalyMergedResultFeedback(@PathParam("anomaly_merged_result_id") long anomalyResultId, String payload) {
try {
MergedAnomalyResultDTO result = anomalyMergedResultDAO.findById(anomalyResultId);
if (result == null) {
throw new IllegalArgumentException("AnomalyResult not found with id " + anomalyResultId);
}
AnomalyFeedbackDTO feedbackRequest = OBJECT_MAPPER.readValue(payload, AnomalyFeedbackDTO.class);
AnomalyFeedbackDTO feedback = result.getFeedback();
if (feedback == null) {
feedback = new AnomalyFeedbackDTO();
result.setFeedback(feedback);
}
if (feedbackRequest.getStatus() == null) {
feedback.setStatus(FeedbackStatus.NEW);
} else {
feedback.setStatus(feedbackRequest.getStatus());
}
feedback.setComment(feedbackRequest.getComment());
feedback.setFeedbackType(feedbackRequest.getFeedbackType());
anomalyMergedResultDAO.updateAnomalyFeedback(result);
} catch (IOException e) {
throw new IllegalArgumentException("Invalid payload " + payload, e);
}
}
use of javax.ws.rs.POST in project pinot by linkedin.
the class AnomalyResource method updateAnomalyResultFeedback.
@POST
@Path(value = "anomaly-result/feedback/{anomaly_result_id}")
public void updateAnomalyResultFeedback(@PathParam("anomaly_result_id") long anomalyResultId, String payload) {
try {
RawAnomalyResultDTO result = rawAnomalyResultDAO.findById(anomalyResultId);
if (result == null) {
throw new IllegalArgumentException("AnomalyResult not found with id " + anomalyResultId);
}
AnomalyFeedbackDTO feedbackRequest = OBJECT_MAPPER.readValue(payload, AnomalyFeedbackDTO.class);
AnomalyFeedbackDTO feedback = result.getFeedback();
if (feedback == null) {
feedback = new AnomalyFeedbackDTO();
result.setFeedback(feedback);
}
if (feedbackRequest.getStatus() == null) {
feedback.setStatus(FeedbackStatus.NEW);
} else {
feedback.setStatus(feedbackRequest.getStatus());
}
feedback.setComment(feedbackRequest.getComment());
feedback.setFeedbackType(feedbackRequest.getFeedbackType());
rawAnomalyResultDAO.update(result);
} catch (IOException e) {
throw new IllegalArgumentException("Invalid payload " + payload, e);
}
}
Aggregations