use of org.opensearch.ad.model.ADTask.DETECTOR_ID_FIELD in project anomaly-detection by opensearch-project.
the class ADDataMigrator method checkIfRealtimeTaskExistsAndBackfill.
private void checkIfRealtimeTaskExistsAndBackfill(AnomalyDetectorJob job, AnomalyDetectorFunction createRealtimeTaskFunction, ConcurrentLinkedQueue<AnomalyDetectorJob> detectorJobs, boolean migrateAll) {
String jobId = job.getName();
BoolQueryBuilder query = new BoolQueryBuilder();
query.filter(new TermQueryBuilder(DETECTOR_ID_FIELD, jobId));
if (job.isEnabled()) {
query.filter(new TermQueryBuilder(IS_LATEST_FIELD, true));
}
query.filter(new TermsQueryBuilder(TASK_TYPE_FIELD, taskTypeToString(ADTaskType.REALTIME_TASK_TYPES)));
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(query).size(1);
SearchRequest searchRequest = new SearchRequest(DETECTION_STATE_INDEX).source(searchSourceBuilder);
client.search(searchRequest, ActionListener.wrap(r -> {
if (r != null && r.getHits().getTotalHits().value > 0) {
// Backfill next realtime job
backfillRealtimeTask(detectorJobs, migrateAll);
return;
}
createRealtimeTaskFunction.execute();
}, e -> {
if (e instanceof ResourceNotFoundException) {
createRealtimeTaskFunction.execute();
}
logger.error("Failed to search tasks of detector " + jobId);
}));
}
use of org.opensearch.ad.model.ADTask.DETECTOR_ID_FIELD in project anomaly-detection by opensearch-project.
the class ADTaskManager method deleteADTasks.
/**
* Delete AD tasks docs.
* [Important!] Make sure listener returns in function
*
* @param detectorId detector id
* @param function AD function
* @param listener action listener
*/
public void deleteADTasks(String detectorId, AnomalyDetectorFunction function, ActionListener<DeleteResponse> listener) {
DeleteByQueryRequest request = new DeleteByQueryRequest(DETECTION_STATE_INDEX);
BoolQueryBuilder query = new BoolQueryBuilder();
query.filter(new TermQueryBuilder(DETECTOR_ID_FIELD, detectorId));
request.setQuery(query);
client.execute(DeleteByQueryAction.INSTANCE, request, ActionListener.wrap(r -> {
if (r.getBulkFailures() == null || r.getBulkFailures().size() == 0) {
logger.info("AD tasks deleted for detector {}", detectorId);
deleteADResultOfDetector(detectorId);
function.execute();
} else {
listener.onFailure(new OpenSearchStatusException("Failed to delete all AD tasks", RestStatus.INTERNAL_SERVER_ERROR));
}
}, e -> {
logger.info("Failed to delete AD tasks for " + detectorId, e);
if (e instanceof IndexNotFoundException) {
deleteADResultOfDetector(detectorId);
function.execute();
} else {
listener.onFailure(e);
}
}));
}
use of org.opensearch.ad.model.ADTask.DETECTOR_ID_FIELD in project anomaly-detection by opensearch-project.
the class ADTaskManager method getAndExecuteOnLatestADTasks.
/**
* Get latest AD tasks and execute consumer function.
* If resetTaskState is true, will collect latest task's profile data from all data nodes. If no data
* node running the latest task, will reset the task state as STOPPED; otherwise, check if there is
* any stale running entities(entity exists in coordinating node cache but no task running on worker
* node) and clean up.
* [Important!] Make sure listener returns in function
*
* @param detectorId detector id
* @param parentTaskId parent task id
* @param entity entity value
* @param adTaskTypes AD task types
* @param function consumer function
* @param transportService transport service
* @param resetTaskState reset task state or not
* @param size return how many AD tasks
* @param listener action listener
* @param <T> response type of action listener
*/
public <T> void getAndExecuteOnLatestADTasks(String detectorId, String parentTaskId, Entity entity, List<ADTaskType> adTaskTypes, Consumer<List<ADTask>> function, TransportService transportService, boolean resetTaskState, int size, ActionListener<T> listener) {
BoolQueryBuilder query = new BoolQueryBuilder();
query.filter(new TermQueryBuilder(DETECTOR_ID_FIELD, detectorId));
query.filter(new TermQueryBuilder(IS_LATEST_FIELD, true));
if (parentTaskId != null) {
query.filter(new TermQueryBuilder(PARENT_TASK_ID_FIELD, parentTaskId));
}
if (adTaskTypes != null && adTaskTypes.size() > 0) {
query.filter(new TermsQueryBuilder(TASK_TYPE_FIELD, taskTypeToString(adTaskTypes)));
}
if (entity != null && !isNullOrEmpty(entity.getAttributes())) {
String path = "entity";
String entityKeyFieldName = path + ".name";
String entityValueFieldName = path + ".value";
for (Map.Entry<String, String> attribute : entity.getAttributes().entrySet()) {
BoolQueryBuilder entityBoolQuery = new BoolQueryBuilder();
TermQueryBuilder entityKeyFilterQuery = QueryBuilders.termQuery(entityKeyFieldName, attribute.getKey());
TermQueryBuilder entityValueFilterQuery = QueryBuilders.termQuery(entityValueFieldName, attribute.getValue());
entityBoolQuery.filter(entityKeyFilterQuery).filter(entityValueFilterQuery);
NestedQueryBuilder nestedQueryBuilder = new NestedQueryBuilder(path, entityBoolQuery, ScoreMode.None);
query.filter(nestedQueryBuilder);
}
}
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(query).sort(EXECUTION_START_TIME_FIELD, SortOrder.DESC).size(size);
SearchRequest searchRequest = new SearchRequest();
searchRequest.source(sourceBuilder);
searchRequest.indices(DETECTION_STATE_INDEX);
client.search(searchRequest, ActionListener.wrap(r -> {
// https://github.com/opendistro-for-elasticsearch/anomaly-detection/pull/359#discussion_r558653132
// getTotalHits will be null when we track_total_hits is false in the query request.
// Add more checking here to cover some unknown cases.
List<ADTask> adTasks = new ArrayList<>();
if (r == null || r.getHits().getTotalHits() == null || r.getHits().getTotalHits().value == 0) {
// don't throw exception here as consumer functions need to handle missing task
// in different way.
function.accept(adTasks);
return;
}
Iterator<SearchHit> iterator = r.getHits().iterator();
while (iterator.hasNext()) {
SearchHit searchHit = iterator.next();
try (XContentParser parser = createXContentParserFromRegistry(xContentRegistry, searchHit.getSourceRef())) {
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser);
ADTask adTask = ADTask.parse(parser, searchHit.getId());
adTasks.add(adTask);
} catch (Exception e) {
String message = "Failed to parse AD task for detector " + detectorId + ", task id " + searchHit.getId();
logger.error(message, e);
listener.onFailure(new OpenSearchStatusException(message, RestStatus.INTERNAL_SERVER_ERROR));
}
}
if (resetTaskState) {
resetLatestDetectorTaskState(adTasks, function, transportService, listener);
} else {
function.accept(adTasks);
}
}, e -> {
if (e instanceof IndexNotFoundException) {
function.accept(new ArrayList<>());
} else {
logger.error("Failed to search AD task for detector " + detectorId, e);
listener.onFailure(e);
}
}));
}
use of org.opensearch.ad.model.ADTask.DETECTOR_ID_FIELD in project anomaly-detection by opensearch-project.
the class ADTaskManager method deleteADResultOfDetector.
private void deleteADResultOfDetector(String detectorId) {
if (!deleteADResultWhenDeleteDetector) {
logger.info("Won't delete ad result for {} as delete AD result setting is disabled", detectorId);
return;
}
logger.info("Start to delete AD results of detector {}", detectorId);
DeleteByQueryRequest deleteADResultsRequest = new DeleteByQueryRequest(ALL_AD_RESULTS_INDEX_PATTERN);
deleteADResultsRequest.setQuery(new TermQueryBuilder(DETECTOR_ID_FIELD, detectorId));
client.execute(DeleteByQueryAction.INSTANCE, deleteADResultsRequest, ActionListener.wrap(response -> {
logger.debug("Successfully deleted AD results of detector " + detectorId);
}, exception -> {
logger.error("Failed to delete AD results of detector " + detectorId, exception);
adTaskCacheManager.addDeletedDetector(detectorId);
}));
}
use of org.opensearch.ad.model.ADTask.DETECTOR_ID_FIELD in project anomaly-detection by opensearch-project.
the class ADTaskManager method updateLatestFlagOfOldTasksAndCreateNewTask.
private void updateLatestFlagOfOldTasksAndCreateNewTask(AnomalyDetector detector, DetectionDateRange detectionDateRange, User user, ActionListener<AnomalyDetectorJobResponse> listener) {
UpdateByQueryRequest updateByQueryRequest = new UpdateByQueryRequest();
updateByQueryRequest.indices(DETECTION_STATE_INDEX);
BoolQueryBuilder query = new BoolQueryBuilder();
query.filter(new TermQueryBuilder(DETECTOR_ID_FIELD, detector.getDetectorId()));
query.filter(new TermQueryBuilder(IS_LATEST_FIELD, true));
// make sure we reset all latest task as false when user switch from single entity to HC, vice versa.
query.filter(new TermsQueryBuilder(TASK_TYPE_FIELD, taskTypeToString(getADTaskTypes(detectionDateRange, true))));
updateByQueryRequest.setQuery(query);
updateByQueryRequest.setRefresh(true);
String script = String.format(Locale.ROOT, "ctx._source.%s=%s;", IS_LATEST_FIELD, false);
updateByQueryRequest.setScript(new Script(script));
client.execute(UpdateByQueryAction.INSTANCE, updateByQueryRequest, ActionListener.wrap(r -> {
List<BulkItemResponse.Failure> bulkFailures = r.getBulkFailures();
if (bulkFailures.isEmpty()) {
// Realtime AD coordinating node is chosen by job scheduler, we won't know it until realtime AD job
// runs. Just set realtime AD coordinating node as null here, and AD job runner will reset correct
// coordinating node once realtime job starts.
// For historical analysis, this method will be called on coordinating node, so we can set coordinating
// node as local node.
String coordinatingNode = detectionDateRange == null ? null : clusterService.localNode().getId();
createNewADTask(detector, detectionDateRange, user, coordinatingNode, listener);
} else {
logger.error("Failed to update old task's state for detector: {}, response: {} ", detector.getDetectorId(), r.toString());
listener.onFailure(bulkFailures.get(0).getCause());
}
}, e -> {
logger.error("Failed to reset old tasks as not latest for detector " + detector.getDetectorId(), e);
listener.onFailure(e);
}));
}
Aggregations