Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Add shingle size, total model size, and model's hash ring to profile API #113

Merged

Conversation

kaituo
Copy link
Member

@kaituo kaituo commented May 6, 2020

Issue #, if available:
#111

Description of changes:

Hash ring helps identify node X runs the AD job for a detector Y with models on node 1,2,3.  This helps oncalls locate logs. Total model size gives transparency relating to the current memory usage. What's more, shingle size help answer question "why my detector does not report anything?"

This PR adds the above info to profile API via a broadcast call that consults ModelManager and FeatureManager about current state pertaining to a detector.  Then these states are consolidated into information humans can parse.

This PR also queries all AD result indices instead of only current result index so that we can fetch a stopped detector's error after the result index with the error is rotated.

Testing done:

  1. add unit tests for the newly added code
  2. Run end-to-end testing to verify new profiles make senses when a detector stops running and is running

Example:

% curl -X GET "localhost:9200/_opendistro/_anomaly_detection/detectors/cneh7HEBHPICjJIdXdrR/_profile?_all=true&pretty"
{
  "state" : "RUNNING",
  "models" : [
    {
      "model_id" : "cneh7HEBHPICjJIdXdrR_model_rcf_2",
      "model_size_in_bytes" : 4456448,
      "node_id" : "VS29z70PSzOdHiEw4SoV9Q"
    },
    {
      "model_id" : "cneh7HEBHPICjJIdXdrR_model_rcf_1",
      "model_size_in_bytes" : 4456448,
      "node_id" : "VS29z70PSzOdHiEw4SoV9Q"
    },
    {
      "model_id" : "cneh7HEBHPICjJIdXdrR_model_threshold",
      "node_id" : "Og23iUroTdKrkwS-y89zLw"
    },
    {
      "model_id" : "cneh7HEBHPICjJIdXdrR_model_rcf_0",
      "model_size_in_bytes" : 4456448,
      "node_id" : "Og23iUroTdKrkwS-y89zLw"
    }
  ],
  "shingle_size" : 8,
  "coordinating_node" : "Og23iUroTdKrkwS-y89zLw",
  "total_size_in_bytes" : 13369344
}

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@@ -280,8 +312,42 @@ private SearchRequest createLatestAnomalyResultRequest(String detectorId, long e

SearchSourceBuilder source = new SearchSourceBuilder().query(filterQuery).size(1).sort(sortQuery);

SearchRequest request = new SearchRequest(AnomalyResult.ANOMALY_RESULT_INDEX);
SearchRequest request = new SearchRequest(AnomalyDetectionIndices.ALL_AD_RESULTS_INDEX_PATTERN);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool. I guess this can fix this issue as well: #111

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

Copy link
Member

@jmazanec15 jmazanec15 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple questions: (1) Does Documentation need to be updated? (2) "This PR also queries all AD result indices instead of only current result index so that we can fetch a stopped detector's error" Could this call eventually get very expensive if many result indices are queried?

@@ -70,9 +78,26 @@ public void profile(String detectorId, ActionListener<DetectorProfile> listener,
return;
}

int totalListener = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Add a comment describing what this means for those not familiar with MultiResponseDelegateActionListener

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

import org.elasticsearch.common.xcontent.XContentBuilder;

public class ModelProfile implements Writeable, ToXContent {
// filed name in toXContent
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Typo

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

public static ProfileName getName(String name) {
switch (name) {
case "state":
return STATE;
case "error":
return ERROR;
case "coordinating_node":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why hardcode these strings?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to "case CommonName.COORDINATING_NODE:".

String typesStr = request.param(TYPE);
String rawPath = request.rawPath();
if (!Strings.isEmpty(typesStr) || rawPath.endsWith(PROFILE) || rawPath.endsWith(PROFILE + "/")) {
boolean all = request.paramAsBoolean("all", false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use _all instead of all?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

*/
public class ProfileResponse extends BaseNodesResponse<ProfileNodeResponse> implements ToXContentFragment {
// filed name in toXContent
static final String COORDINATING_NODE = "coordinating_node";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These strings are already defined aren't they?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved these strings to CommonName and use CommonName

/**
* Key indicating all profiles should be retrieved
*/
public static final String ALL_PROFILE_KEY = "_all";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it used?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. Removed.

Comment on lines 38 to 41
static final String COORDINATING_NODE = "coordinating_node";
static final String SHINGLE_SIZE = "shingle_size";
static final String TOTAL_SIZE = "total_size";
static final String MODELS = "models";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use ProfileName enum to replace these?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved these strings to CommonName and use CommonName

* @param paths path fragments
* @return list of double
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why removing this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added back with changed contents.


Response profileResponse = getDetectorProfile(detector.getDetectorId(), true);
assertEquals("Incorrect profile status", RestStatus.OK, restStatus(profileResponse));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there test case against customized profiles?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added one.

Copy link
Contributor

@yizheliu-amazon yizheliu-amazon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a few minor issues. no blocker

@kaituo kaituo closed this May 7, 2020
@kaituo kaituo reopened this May 7, 2020
@kaituo
Copy link
Member Author

kaituo commented May 7, 2020

A couple questions: (1) Does Documentation need to be updated? (2) "This PR also queries all AD result indices instead of only current result index so that we can fetch a stopped detector's error" Could this call eventually get very expensive if many result indices are queried?

(1) Yes, will contact our doc writer.
(2) It can be. It's a tradeoff between accuracy vs performance. I didn't include all AD result indices because I am afraid of performance issues. Let's see.

Hash ring helps identify node X runs the AD job for a detector Y with models on node 1,2,3.  This helps oncalls locate logs. Total model size gives transparency relating to the current memory usage. What's more, shingle size help answer question "why my detector does not report anything?"

This PR adds the above info to profile API via a broadcast call that consults ModelManager and FeatureManager about current state pertaining to a detector.  Then these states are consolidated into information humans can parse.

This PR also queries all AD result indices instead of only current result index so that we can fetch a stopped detector's error after the result index with the error is rotated.

Testing done:
1. add unit tests for the newly added code
2. Run end-to-end testing to verify new profiles make senses when a detector stops running and is running
@kaituo kaituo merged commit e06cf6f into opendistro-for-elasticsearch:opendistro-1.4 May 7, 2020
kaituo added a commit to kaituo/anomaly-detection that referenced this pull request May 19, 2020
…API (opendistro-for-elasticsearch#113)

Hash ring helps identify node X runs the AD job for a detector Y with models on node 1,2,3.  This helps oncalls locate logs. Total model size gives transparency relating to the current memory usage. What's more, shingle size help answer question "why my detector does not report anything?"

This PR adds the above info to profile API via a broadcast call that consults ModelManager and FeatureManager about current state pertaining to a detector.  Then these states are consolidated into information humans can parse.

This PR also queries all AD result indices instead of only current result index so that we can fetch a stopped detector's error after the result index with the error is rotated.

Testing done:
1. add unit tests for the newly added code
2. Run end-to-end testing to verify new profiles make senses when a detector stops running and is running
kaituo added a commit that referenced this pull request May 20, 2020
* Add shingle size, total model size, and model's hash ring to profile API (#113)

Hash ring helps identify node X runs the AD job for a detector Y with models on node 1,2,3.  This helps oncalls locate logs. Total model size gives transparency relating to the current memory usage. What's more, shingle size help answer question "why my detector does not report anything?"

This PR adds the above info to profile API via a broadcast call that consults ModelManager and FeatureManager about current state pertaining to a detector.  Then these states are consolidated into information humans can parse.

This PR also queries all AD result indices instead of only current result index so that we can fetch a stopped detector's error after the result index with the error is rotated.

Testing done:
1. add unit tests for the newly added code
2. Run end-to-end testing to verify new profiles make senses when a detector stops running and is running

* Fix bug in profile API (#115)

DetectorProfile's merge does not include new fields added.  This PR fixes that.

Testing done:
* Manually verified profile API works as expected

* Improve profile API's error fetching efficiency (#117)

Previously, profile API scans all anomaly result indices to get a detector's most recent error, which can cause performance bottleneck with large anomaly result indices. This PR improves this aspect via various efforts.

First, when a detector is running, we only need to scan the current index, not all of the rolled over ones since we are interested in the latest error.
Second, when a detector is disabled, we only need to scan the latest anomaly result indices created before the detector's enable time.
Third, setting track total hits false makes ES terminate search early. ES will not try to count the number of documents and will be able to end the query as soon as N document have been collected per segment.

Testing done:
1. patched a cluster with 1,000 detectors and 2GB anomaly result indices. Without the PR, scanning anomaly result indices 1000 times would timeout after 30 seconds. After the PR, we would not see the timeout.
2. A detector's error message can be on a rotated index. Adds a test case to makes sure we get error info from .opendistro-anomaly-results index that has been rolled over.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants