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

Prevent creating detector with duplicate name. Issue:#118 #134

Conversation

yizheliu-amazon
Copy link
Contributor

Issue #, if available:
#118
Description of changes:
Add logic to prevent user from creating detector with duplicate name

Testing:

./gradlew build
./gradlew integTest

Manual testing:

// create detector cli-d-1-min-001
~/Downloads [ curl -X POST "localhost:9200/_opendistro/_anomaly_detection/detectors" -H 'Content-Type: application/json' -d'                                               ] 5:09 PM
{
    "name":"cli-d-1-min-001",
    "description":"Test nab daily jumpsup",
    "time_field":"timestamp",
    "indices":[
        "test-index"
    ],
    "feature_attributes":[
        {
            "feature_name":"feature-1",
            "feature_enabled":true,
            "aggregation_query":{
                "value_sum":{
                    "sum":{
                        "field":"feature-1"
                    }
                }
            }
        }
    ],
    "detection_interval":{
        "period":{
            "interval":1,
            "unit":"Minutes"
        }
    }
}
'
{"_id":"LNm2OXIB8qLpH1US_aNC","_version":1,"_seq_no":0,"_primary_term":1,"anomaly_detector":{"name":"cli-d-1-min-001","description":"Test nab daily jumpsup","time_field":"timestamp","indices":["test-index"],"filter_query":{"match_all":{"boost":1.0}},"detection_interval":{"period":{"interval":1,"unit":"Minutes"}},"window_delay":{"period":{"interval":0,"unit":"Seconds"}},"schema_version":0,"feature_attributes":[{"feature_id":"Jtm2OXIB8qLpH1US_KNj","feature_name":"feature-1","feature_enabled":true,"aggregation_query":{"value_sum":{"sum":{"field":"feature-1"}}}}]}}

// create detector cli-d-1-min-002
~/Downloads [ curl -X POST "localhost:9200/_opendistro/_anomaly_detection/detectors" -H 'Content-Type: application/json' -d'                                               ] 5:09 PM
{
    "name":"cli-d-1-min-002",
    "description":"Test nab daily jumpsup",
    "time_field":"timestamp",
    "indices":[
        "test-index"
    ],
    "feature_attributes":[
        {
            "feature_name":"feature-1",
            "feature_enabled":true,
            "aggregation_query":{
                "value_sum":{
                    "sum":{
                        "field":"feature-1"
                    }
                }
            }
        }
    ],
    "detection_interval":{
        "period":{
            "interval":1,
            "unit":"Minutes"
        }
    }
}
'
{"_id":"M9m3OXIB8qLpH1USKaM3","_version":1,"_seq_no":1,"_primary_term":1,"anomaly_detector":{"name":"cli-d-1-min-002","description":"Test nab daily jumpsup","time_field":"timestamp","indices":["test-index"],"filter_query":{"match_all":{"boost":1.0}},"detection_interval":{"period":{"interval":1,"unit":"Minutes"}},"window_delay":{"period":{"interval":0,"unit":"Seconds"}},"schema_version":0,"feature_attributes":[{"feature_id":"Ldm3OXIB8qLpH1USKaMu","feature_name":"feature-1","feature_enabled":true,"aggregation_query":{"value_sum":{"sum":{"field":"feature-1"}}}}]}}

// Update cli-d-1-min-002 name to cli-d-1-min-001 -> failed
~/Downloads [ curl -X PUT "localhost:9200/_opendistro/_anomaly_detection/detectors/M9m3OXIB8qLpH1USKaM3" -H 'Content-Type: application/json' -d'                           ] 5:10 PM
{
    "name":"cli-d-1-min-001",
    "description":"Test nab daily jumpsup--",
    "time_field":"timestamp",
    "indices":[
        "test-index"
    ],
    "feature_attributes":[
        {
            "feature_name":"feature-1",
            "feature_enabled":true,
            "aggregation_query":{
                "value_sum":{
                    "sum":{
                        "field":"feature-1"
                    }
                }
            }
        }
    ],
    "detection_interval":{
        "period":{
            "interval":1,
            "unit":"Minutes"
        }
    }
}
'
{"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"Cannot create anomaly detector with name[cli-d-1-min-001] used by detectorId LNm2OXIB8qLpH1US_aNC."}],"type":"illegal_argument_exception","reason":"Cannot create anomaly detector with name[cli-d-1-min-001] used by detectorId LNm2OXIB8qLpH1US_aNC"},"status":400}

// Update cli-d-1-min-002 description -> pass
~/Downloads [ curl -X PUT "localhost:9200/_opendistro/_anomaly_detection/detectors/M9m3OXIB8qLpH1USKaM3" -H 'Content-Type: application/json' -d'                           ] 5:11 PM
{
    "name":"cli-d-1-min-002",
    "description":"Test nab daily jumpsup--updated",
    "time_field":"timestamp",
    "indices":[
        "test-index"
    ],
    "feature_attributes":[
        {
            "feature_name":"feature-1",
            "feature_enabled":true,
            "aggregation_query":{
                "value_sum":{
                    "sum":{
                        "field":"feature-1"
                    }
                }
            }
        }
    ],
    "detection_interval":{
        "period":{
            "interval":1,
            "unit":"Minutes"
        }
    }
}
'
{"_id":"M9m3OXIB8qLpH1USKaM3","_version":2,"_seq_no":2,"_primary_term":1,"anomaly_detector":{"name":"cli-d-1-min-002","description":"Test nab daily jumpsup--updated","time_field":"timestamp","indices":["test-index"],"filter_query":{"match_all":{"boost":1.0}},"detection_interval":{"period":{"interval":1,"unit":"Minutes"}},"window_delay":{"period":{"interval":0,"unit":"Seconds"}},"schema_version":0,"feature_attributes":[{"feature_id":"Odm4OXIB8qLpH1USqKNz","feature_name":"feature-1","feature_enabled":true,"aggregation_query":{"value_sum":{"sum":{"field":"feature-1"}}}}]}}

// Create detector with name cli-d-1-min-001 -> failed 
~/Downloads [ curl -X POST "localhost:9200/_opendistro/_anomaly_detection/detectors" -H 'Content-Type: application/json' -d'                                                                            ] 10:32 PM
{
    "name":"cli-d-1-min-001",
    "description":"new detector 003",
    "time_field":"timestamp",
    "indices":[
        "test-index"
    ],
    "feature_attributes":[
        {
            "feature_name":"feature-1",
            "feature_enabled":true,
            "aggregation_query":{
                "value_sum":{
                    "sum":{
                        "field":"feature-1"
                    }
                }
            }
        }
    ],
    "detection_interval":{
        "period":{
            "interval":1,
            "unit":"Minutes"
        }
    }
}
'
{"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"Cannot create anomaly detector with name[cli-d-1-min-001] used by detectorId TYTeOnIBwvgo5IJfiD1y"}],"type":"illegal_argument_exception","reason":"Cannot create anomaly detector with name[cli-d-1-min-001] used by detectorId TYTeOnIBwvgo5IJfiD1y"},"status":400}

// Create detector cli-d-1-min-003 -> pass
~/Downloads [ curl -X POST "localhost:9200/_opendistro/_anomaly_detection/detectors" -H 'Content-Type: application/json' -d'                                                                            ] 10:34 PM
{
    "name":"cli-d-1-min-003",
    "description":"new detector 003",
    "time_field":"timestamp",
    "indices":[
        "test-index"
    ],
    "feature_attributes":[
        {
            "feature_name":"feature-1",
            "feature_enabled":true,
            "aggregation_query":{
                "value_sum":{
                    "sum":{
                        "field":"feature-1"
                    }
                }
            }
        }
    ],
    "detection_interval":{
        "period":{
            "interval":1,
            "unit":"Minutes"
        }
    }
}
'
{"_id":"WoTgOnIBwvgo5IJfcT0P","_version":1,"_seq_no":1,"_primary_term":1,"anomaly_detector":{"name":"cli-d-1-min-003","description":"new detector 003","time_field":"timestamp","indices":["test-index"],"filter_query":{"match_all":{"boost":1.0}},"detection_interval":{"period":{"interval":1,"unit":"Minutes"}},"window_delay":{"period":{"interval":0,"unit":"Seconds"}},"schema_version":0,"feature_attributes":[{"feature_id":"VITgOnIBwvgo5IJfcT0M","feature_name":"feature-1","feature_enabled":true,"aggregation_query":{"value_sum":{"sum":{"field":"feature-1"}}}}]}}

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

private void checkADNameExists(String detectorId) throws IOException {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
// src/main/resources/mappings/anomaly-detectors.json#L14
.query(QueryBuilders.termQuery("name.keyword", anomalyDetector.getName()))
Copy link
Contributor

Choose a reason for hiding this comment

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

minor. can this query also include a condition like not this detector id to utilize es search instead of additional postprocessing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that's a good point. will change to use must_not to exclude this detector id

Comment on lines 262 to 263
String errorMsg = String.format("Cannot create anomaly detector with name[%s] used by detectorId %s", name, existingDetectorId);
logger.error(errorMsg);
Copy link
Contributor

Choose a reason for hiding this comment

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

minor. i would use a warning for this case since it's a harmless user error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure. will do

// src/main/resources/mappings/anomaly-detectors.json#L14
boolQueryBuilder.must(QueryBuilders.termQuery("name.keyword", anomalyDetector.getName()));
// _id field does not allow "", but allows " "
boolQueryBuilder.mustNot(QueryBuilders.termQuery(RestHandlerUtils._ID, StringUtils.isBlank(detectorId) ? " " : detectorId));
Copy link
Contributor

Choose a reason for hiding this comment

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

How about we add mustNot condition only when detectorId is not blank?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like the idea. Thanks!

if (response.getHits().getTotalHits().value > 0) {
String errorMsg = String
.format(
"Cannot create anomaly detector with name[%s] used by detectorId %s",
Copy link
Contributor

Choose a reason for hiding this comment

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

We may show this error message on Kibana. How about we make it more readable?
Cannot create anomaly detector with name [%s] as it's already used by detector [%s]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure. will change that.

@yizheliu-amazon yizheliu-amazon requested a review from ylwu-amzn May 22, 2020 23:14
Copy link
Contributor

@ylwu-amzn ylwu-amzn left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks for the change.

@yizheliu-amazon yizheliu-amazon merged commit 64d7f0e into opendistro-for-elasticsearch:master May 22, 2020
@yizheliu-amazon yizheliu-amazon deleted the forbid-duplicate branch May 22, 2020 23:25
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.

4 participants