This repository has been archived by the owner on Aug 2, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 36
Use callbacks and bug fix #83
Merged
kaituo
merged 6 commits into
opendistro-for-elasticsearch:development
from
kaituo:featureCallback2
Apr 14, 2020
Merged
Changes from 1 commit
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
f9d506e
Use callbacks and bug fix
kaituo ed40113
Change the default value of lastUpdateTime from the current timestamp…
kaituo b2fd4cd
Add async getColdStartData (#80)
wnbts d023166
add async trainModel (#81)
wnbts d8ea9cf
Various
kaituo c554a4f
Remove impossible exception throwing
kaituo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
|
@@ -22,7 +22,6 @@ | |
import java.time.Instant; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.Random; | ||
import java.util.AbstractMap.SimpleEntry; | ||
import java.util.Map.Entry; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
|
@@ -31,10 +30,11 @@ | |
import com.amazon.opendistroforelasticsearch.ad.common.exception.LimitExceededException; | ||
import com.amazon.opendistroforelasticsearch.ad.ml.ModelManager; | ||
import com.amazon.opendistroforelasticsearch.ad.model.AnomalyDetector; | ||
import com.amazon.opendistroforelasticsearch.ad.settings.AnomalyDetectorSettings; | ||
import com.amazon.opendistroforelasticsearch.ad.util.ClientUtil; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.elasticsearch.action.ActionListener; | ||
import org.elasticsearch.action.get.GetRequest; | ||
import org.elasticsearch.action.get.GetResponse; | ||
import org.elasticsearch.client.Client; | ||
|
@@ -44,8 +44,6 @@ | |
import org.elasticsearch.common.xcontent.XContentParser; | ||
import org.elasticsearch.common.xcontent.XContentType; | ||
|
||
import com.amazon.randomcutforest.RandomCutForest; | ||
|
||
/** | ||
* ADStateManager is used by transport layer to manage AnomalyDetector object | ||
* and the number of partitions for a detector id. | ||
|
@@ -56,7 +54,6 @@ public class ADStateManager { | |
private ConcurrentHashMap<String, Entry<AnomalyDetector, Instant>> currentDetectors; | ||
private ConcurrentHashMap<String, Entry<Integer, Instant>> partitionNumber; | ||
private Client client; | ||
private Random random; | ||
private ModelManager modelManager; | ||
private NamedXContentRegistry xContentRegistry; | ||
private ClientUtil clientUtil; | ||
|
@@ -77,7 +74,6 @@ public ADStateManager( | |
) { | ||
this.currentDetectors = new ConcurrentHashMap<>(); | ||
this.client = client; | ||
this.random = new Random(); | ||
this.modelManager = modelManager; | ||
this.xContentRegistry = xContentRegistry; | ||
this.partitionNumber = new ConcurrentHashMap<>(); | ||
|
@@ -91,67 +87,63 @@ public ADStateManager( | |
/** | ||
* Get the number of RCF model's partition number for detector adID | ||
* @param adID detector id | ||
* @param detector object | ||
* @return the number of RCF model's partition number for adID | ||
* @throws InterruptedException when we cannot get anomaly detector object for adID before timeout | ||
* @throws LimitExceededException when there is no sufficient resource available | ||
*/ | ||
public int getPartitionNumber(String adID) throws InterruptedException { | ||
public int getPartitionNumber(String adID, Optional<AnomalyDetector> detector) throws InterruptedException { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor. Why not validate detector first and just pass a detector afterwards? saving all the repetitive and unlikely handling of a non-existent detector. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good point. Done. |
||
Entry<Integer, Instant> partitonAndTime = partitionNumber.get(adID); | ||
if (partitonAndTime != null) { | ||
partitonAndTime.setValue(clock.instant()); | ||
return partitonAndTime.getKey(); | ||
} | ||
|
||
Optional<AnomalyDetector> detector = getAnomalyDetector(adID); | ||
if (!detector.isPresent()) { | ||
throw new AnomalyDetectionException(adID, "AnomalyDetector is not found"); | ||
} | ||
|
||
RandomCutForest forest = RandomCutForest | ||
.builder() | ||
.dimensions(detector.get().getFeatureAttributes().size() * AnomalyDetectorSettings.SHINGLE_SIZE) | ||
.sampleSize(AnomalyDetectorSettings.NUM_SAMPLES_PER_TREE) | ||
.numberOfTrees(AnomalyDetectorSettings.NUM_TREES) | ||
.parallelExecutionEnabled(false) | ||
.build(); | ||
int partitionNum = modelManager.getPartitionedForestSizes(forest, adID).getKey(); | ||
int partitionNum = modelManager.getPartitionedForestSizes(adID, detector.get().getEnabledFeatureIds().size()).getKey(); | ||
partitionNumber.putIfAbsent(adID, new SimpleEntry<>(partitionNum, clock.instant())); | ||
return partitionNum; | ||
} | ||
|
||
public Optional<AnomalyDetector> getAnomalyDetector(String adID) { | ||
public void getAnomalyDetector(String adID, ActionListener<Optional<AnomalyDetector>> listener) { | ||
Entry<AnomalyDetector, Instant> detectorAndTime = currentDetectors.get(adID); | ||
if (detectorAndTime != null) { | ||
detectorAndTime.setValue(clock.instant()); | ||
return Optional.of(detectorAndTime.getKey()); | ||
listener.onResponse(Optional.of(detectorAndTime.getKey())); | ||
return; | ||
} | ||
|
||
GetRequest request = new GetRequest(AnomalyDetector.ANOMALY_DETECTORS_INDEX, adID); | ||
|
||
Optional<GetResponse> getResponse = clientUtil.<GetRequest, GetResponse>timedRequest(request, LOG, client::get); | ||
|
||
return onGetResponse(getResponse, adID); | ||
clientUtil.<GetRequest, GetResponse>asyncRequest(request, client::get, onGetResponse(adID, listener)); | ||
} | ||
|
||
private Optional<AnomalyDetector> onGetResponse(Optional<GetResponse> asResponse, String adID) { | ||
if (!asResponse.isPresent() || !asResponse.get().isExists()) { | ||
return Optional.empty(); | ||
} | ||
private ActionListener<GetResponse> onGetResponse(String adID, ActionListener<Optional<AnomalyDetector>> listener) { | ||
return ActionListener.wrap(response -> { | ||
if (response == null || !response.isExists()) { | ||
listener.onResponse(Optional.empty()); | ||
return; | ||
} | ||
|
||
GetResponse response = asResponse.get(); | ||
String xc = response.getSourceAsString(); | ||
LOG.debug("Fetched anomaly detector: {}", xc); | ||
|
||
try (XContentParser parser = XContentType.JSON.xContent().createParser(xContentRegistry, LoggingDeprecationHandler.INSTANCE, xc)) { | ||
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation); | ||
AnomalyDetector detector = AnomalyDetector.parse(parser, response.getId()); | ||
currentDetectors.put(adID, new SimpleEntry<>(detector, clock.instant())); | ||
return Optional.of(detector); | ||
} catch (Exception t) { | ||
LOG.error("Fail to parse detector {}", adID); | ||
LOG.error("Stack trace:", t); | ||
return Optional.empty(); | ||
} | ||
String xc = response.getSourceAsString(); | ||
LOG.info("Fetched anomaly detector: {}", xc); | ||
|
||
try ( | ||
XContentParser parser = XContentType.JSON.xContent().createParser(xContentRegistry, LoggingDeprecationHandler.INSTANCE, xc) | ||
) { | ||
ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation); | ||
AnomalyDetector detector = AnomalyDetector.parse(parser, response.getId()); | ||
currentDetectors.put(adID, new SimpleEntry<>(detector, clock.instant())); | ||
listener.onResponse(Optional.of(detector)); | ||
} catch (Exception t) { | ||
LOG.error("Fail to parse detector {}", adID); | ||
LOG.error("Stack trace:", t); | ||
listener.onResponse(Optional.empty()); | ||
} | ||
}, listener::onFailure); | ||
} | ||
|
||
/** | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we are going to refactor this method, I suggest the new api just takes a detector object, which contains all the needed info and simpler to use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only use use detector id as part of error message. Don't need other detector information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if model manager takes a detector, it can compute the feature dimensions and partitioning so that will be only input needed and that will save client the work to provide a second rcfNumFeatures input. that's why i suggest doing that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make sense. done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please take a look at the recent commit: d8ea9cf