Skip to content

Conversation

@amitgalitz
Copy link
Member

Description

Adding create and start to AD node client.

Involves creating new constructor for a few request types were we pass AD cluster settings from rest layer and utilizing cluster setting fetching in transport layer instead for plugin to plugin communication.

Check List

  • Commits are signed per the DCO using --signoff.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

@codecov
Copy link

codecov bot commented Nov 12, 2025

Codecov Report

❌ Patch coverage is 86.23188% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.33%. Comparing base (4b21947) to head (6538cf5).

Files with missing lines Patch % Lines
...transport/IndexAnomalyDetectorTransportAction.java 74.07% 3 Missing and 4 partials ⚠️
...arch/ad/transport/IndexAnomalyDetectorRequest.java 77.27% 5 Missing ⚠️
...rch/ad/transport/IndexAnomalyDetectorResponse.java 77.77% 2 Missing ⚠️
...rg/opensearch/timeseries/transport/JobRequest.java 81.81% 2 Missing ⚠️
...g/opensearch/timeseries/transport/JobResponse.java 77.77% 2 Missing ⚠️
...s/transport/BaseValidateConfigTransportAction.java 95.83% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##               main    #1611      +/-   ##
============================================
- Coverage     81.42%   81.33%   -0.10%     
- Complexity     6161     6170       +9     
============================================
  Files           542      542              
  Lines         24994    25101     +107     
  Branches       2543     2551       +8     
============================================
+ Hits          20351    20415      +64     
- Misses         3378     3409      +31     
- Partials       1265     1277      +12     
Flag Coverage Δ
plugin 81.33% <86.23%> (-0.10%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...g/opensearch/ad/client/AnomalyDetectionClient.java 100.00% <100.00%> (ø)
...ensearch/ad/client/AnomalyDetectionNodeClient.java 100.00% <100.00%> (ø)
...d/transport/AnomalyDetectorJobTransportAction.java 100.00% <ø> (ø)
...nsport/ValidateAnomalyDetectorTransportAction.java 100.00% <ø> (ø)
...recast/transport/ForecasterJobTransportAction.java 100.00% <ø> (ø)
...t/transport/ValidateForecasterTransportAction.java 100.00% <ø> (ø)
...h/timeseries/transport/BaseJobTransportAction.java 88.63% <100.00%> (+0.54%) ⬆️
...ch/timeseries/transport/ValidateConfigRequest.java 84.90% <100.00%> (+0.59%) ⬆️
...s/transport/BaseValidateConfigTransportAction.java 77.39% <95.83%> (+4.56%) ⬆️
...rch/ad/transport/IndexAnomalyDetectorResponse.java 95.12% <77.77%> (-4.88%) ⬇️
... and 4 more

... and 13 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

void suggestAnomalyDetector(SuggestConfigParamRequest suggestRequest, ActionListener<SuggestConfigParamResponse> listener);

/**
* Create anomaly detector - refer to https://opensearch.org/docs/latest/observing-your-data/ad/api/#create-detector
Copy link
Collaborator

Choose a reason for hiding this comment

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

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

}

/**
* Create anomaly detector - refer to https://opensearch.org/docs/latest/observing-your-data/ad/api/#create-detector
Copy link
Collaborator

Choose a reason for hiding this comment

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

same issue

void createAnomalyDetector(IndexAnomalyDetectorRequest createRequest, ActionListener<IndexAnomalyDetectorResponse> listener);

/**
* Start anomaly detector - refer to https://opensearch.org/docs/latest/observing-your-data/ad/api/#start-detector
Copy link
Collaborator

Choose a reason for hiding this comment

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

build.gradle Outdated

testImplementation "org.opensearch.test:framework:${opensearch_version}"

zipArchive("org.opensearch.plugin:opensearch-ml-plugin:${opensearch_build}")
Copy link
Collaborator

Choose a reason for hiding this comment

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

why do you need ml-plugin?

Copy link
Member Author

@amitgalitz amitgalitz Nov 29, 2025

Choose a reason for hiding this comment

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

removing this, left from testing

this.maxCategoricalFields = maxCategoricalFields;
}

public IndexAnomalyDetectorRequest(String detectorID, AnomalyDetector detector, RestRequest.Method method) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Where do you call this constructor?

Copy link
Member Author

Choose a reason for hiding this comment

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

from skills repo on creating an anomaly detector from create ad tool, will have PR for that by tomorrow

Comment on lines +105 to +111

// Initialize cluster settings for node client requests
this.maxSingleEntityAnomalyDetectors = AnomalyDetectorSettings.AD_MAX_SINGLE_ENTITY_ANOMALY_DETECTORS.get(settings);
this.maxMultiEntityAnomalyDetectors = AnomalyDetectorSettings.AD_MAX_HC_ANOMALY_DETECTORS.get(settings);
this.maxAnomalyFeatures = AnomalyDetectorSettings.MAX_ANOMALY_FEATURES.get(settings);
this.maxCategoricalFields = ADNumericSetting.maxCategoricalFields();

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need these changes?

Copy link
Member Author

Choose a reason for hiding this comment

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

so we can access settings on a transport request call that doesn't go through rest layer at first

Comment on lines +106 to +110
this.maxSingleEntityAnomalyDetectors = AnomalyDetectorSettings.AD_MAX_SINGLE_ENTITY_ANOMALY_DETECTORS.get(settings);
this.maxMultiEntityAnomalyDetectors = AnomalyDetectorSettings.AD_MAX_HC_ANOMALY_DETECTORS.get(settings);
this.maxAnomalyFeatures = AnomalyDetectorSettings.MAX_ANOMALY_FEATURES.get(settings);
this.maxCategoricalFields = ADNumericSetting.maxCategoricalFields();

Copy link
Collaborator

Choose a reason for hiding this comment

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

time series package should try to avoid cross-module dependency. These setting are not useful to forecast subclass.

Copy link
Member Author

@amitgalitz amitgalitz Dec 1, 2025

Choose a reason for hiding this comment

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

will change so we have ad with ad settings and forecaster with forecaster. We have some of those checks on Config level but i see we have different settings for some of them to supply that value. will fix

Copy link
Collaborator

@kaituo kaituo left a comment

Choose a reason for hiding this comment

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

partial review

detector = new AnomalyDetector(in);
method = in.readEnum(RestRequest.Method.class);
requestTimeout = in.readTimeValue();
maxSingleEntityAnomalyDetectors = in.readInt();
Copy link
Collaborator

Choose a reason for hiding this comment

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

This may cause bwc issue as if the caller sends request between new and old nodes.

Copy link
Member Author

Choose a reason for hiding this comment

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

will make this optional

return new IndexAnomalyDetectorResponse(namedWriteableAwareInput);
}
} catch (IOException e) {
throw new UncheckedIOException("failed to parse ActionResponse into IndexAnomalyDetectorResponse", e);
Copy link
Collaborator

Choose a reason for hiding this comment

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

be consistent: IndexAnomalyDetectorRequest.fromActionRequest(...) throws IllegalArgumentException wrapping the IOException, while we throw UncheckedIOException here.

return new IndexAnomalyDetectorResponse(namedWriteableAwareInput);
}
} catch (IOException e) {
throw new UncheckedIOException("failed to parse ActionResponse into IndexAnomalyDetectorResponse", e);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also consider including the source class in the error message, e.g.:

"failed to parse " + actionRequest.getClass().getName() + " into IndexAnomalyDetectorRequest"

Signed-off-by: Amit Galitzky <[email protected]>
Signed-off-by: Amit Galitzky <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

infra Changes to infrastructure, testing, CI/CD, pipelines, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants