diff --git a/src/main/java/org/opensearch/agent/tools/SearchAlertsTool.java b/src/main/java/org/opensearch/agent/tools/SearchAlertsTool.java index 0997198f..b27d0887 100644 --- a/src/main/java/org/opensearch/agent/tools/SearchAlertsTool.java +++ b/src/main/java/org/opensearch/agent/tools/SearchAlertsTool.java @@ -33,7 +33,7 @@ public class SearchAlertsTool implements Tool { public static final String TYPE = "SearchAlertsTool"; private static final String DEFAULT_DESCRIPTION = - "This is a tool that finds alert trigger information. It takes 12 optional argument named sortOrder which defines the order of the results (options are asc or desc, and default is asc), and sortString which defines how to sort the results (default is monitor_name.keyword), and size which defines the size of the request to be returned (default is 20), and startIndex which defines the index to start from (default is 0), and searchString which defines the search string to use for searching a specific alert (default is an empty String), and severityLevel which defines the severity level to filter for (default is ALL), and alertState which defines the alert state to filter for (default is ALL), and monitorId which defines the monitor ID to filter for, and alertIndex which defines the alert index to search from (default is null), and monitorIds which defines the list of monitor IDs to filter for, and workflowIds which defines the list of workflow IDs to filter for(default is null), and alertIds which defines the list of alert IDs to filter for (default is null). The tool returns a list of alerts, and the total number of alerts."; + "This is a tool that finds alert trigger information. It takes 12 optional argument named sortOrder which defines the order of the results (options are asc or desc, and default is asc), and sortString which defines how to sort the results (default is monitor_name.keyword), and size which defines the size of the request to be returned (default is 20), and startIndex which defines the index to start from (default is 0), and searchString which defines the search string to use for searching a specific alert (default is an empty String), and severityLevel which defines the severity level to filter for (default is ALL), and alertState which defines the alert state to filter for (default is ALL), and monitorId which defines the monitor ID to filter for, and alertIndex which defines the alert index to search from (default is null), and monitorIds which defines the list of monitor IDs to filter for, and workflowIds which defines the list of workflow IDs to filter for(default is null), and alertIds which defines the list of alert IDs to filter for (default is null). The tool returns 2 values: a list of alerts (each containining id, version, schema version, monitor ID, workflow ID, workflow name, monitor name, monitor version, monitor user, trigger ID, trigger name, finding IDs, related doc IDs, state, start time, end time, last notifcation time, acknowledged time, error message, error history, severity, action execution results, aggregation result bucket, execution ID, associated alert IDs), and the total number of alerts."; @Setter @Getter diff --git a/src/main/java/org/opensearch/agent/tools/SearchAnomalyDetectorsTool.java b/src/main/java/org/opensearch/agent/tools/SearchAnomalyDetectorsTool.java index db042979..2bbbcfa7 100644 --- a/src/main/java/org/opensearch/agent/tools/SearchAnomalyDetectorsTool.java +++ b/src/main/java/org/opensearch/agent/tools/SearchAnomalyDetectorsTool.java @@ -49,7 +49,7 @@ public class SearchAnomalyDetectorsTool implements Tool { public static final String TYPE = "SearchAnomalyDetectorsTool"; private static final String DEFAULT_DESCRIPTION = - "This is a tool that searches anomaly detectors. It takes 12 optional arguments named detectorName which is the explicit name of the monitor (default is null), and detectorNamePattern which is a wildcard query to match detector name (default is null), and indices which defines the index being detected (default is null), and highCardinality which defines whether the anomaly detector is high cardinality (default is null), and lastUpdateTime which defines the latest update time of the anomaly detector (default is null), and sortOrder which defines the order of the results (options are asc or desc, and default is asc), and sortString which defines how to sort the results (default is name.keyword), and size which defines the size of the request to be returned (default is 20), and startIndex which defines the index to start from (default is 0), and running which defines whether the anomaly detector is running (default is null, indicating both), and disabled which defines whether the anomaly detector is disabled (default is null, indicating both), and failed which defines whether the anomaly detector has failed (default is null, indicating both). The tool returns the list of anomaly detectors, and the total number of anomaly detectors."; + "This is a tool that searches anomaly detectors. It takes 12 optional arguments named detectorName which is the explicit name of the monitor (default is null), and detectorNamePattern which is a wildcard query to match detector name (default is null), and indices which defines the index being detected (default is null), and highCardinality which defines whether the anomaly detector is high cardinality (default is null), and lastUpdateTime which defines the latest update time of the anomaly detector (default is null), and sortOrder which defines the order of the results (options are asc or desc, and default is asc), and sortString which defines how to sort the results (default is name.keyword), and size which defines the size of the request to be returned (default is 20), and startIndex which defines the index to start from (default is 0), and running which defines whether the anomaly detector is running (default is null, indicating both), and disabled which defines whether the anomaly detector is disabled (default is null, indicating both), and failed which defines whether the anomaly detector has failed (default is null, indicating both). The tool returns 2 values: a list of anomaly detectors (each containing the id, name, type, description, index, last update time), and the total number of anomaly results."; @Setter @Getter @@ -244,7 +244,11 @@ private void processHits(Map hitsAsMap, ActionListener for (SearchHit hit : hitsAsMap.values()) { sb.append("{"); sb.append("id=").append(hit.getId()).append(","); - sb.append("name=").append(hit.getSourceAsMap().get("name")); + sb.append("name=").append(hit.getSourceAsMap().get("name")).append(","); + sb.append("type=").append(hit.getSourceAsMap().get("type")).append(","); + sb.append("description=").append(hit.getSourceAsMap().get("description")).append(","); + sb.append("index=").append(hit.getSourceAsMap().get("indices")).append(","); + sb.append("lastUpdateTime=").append(hit.getSourceAsMap().get("last_update_time")); sb.append("}"); } sb.append("]"); diff --git a/src/main/java/org/opensearch/agent/tools/SearchAnomalyResultsTool.java b/src/main/java/org/opensearch/agent/tools/SearchAnomalyResultsTool.java index 86c62918..d9d63545 100644 --- a/src/main/java/org/opensearch/agent/tools/SearchAnomalyResultsTool.java +++ b/src/main/java/org/opensearch/agent/tools/SearchAnomalyResultsTool.java @@ -40,7 +40,7 @@ public class SearchAnomalyResultsTool implements Tool { public static final String TYPE = "SearchAnomalyResultsTool"; private static final String DEFAULT_DESCRIPTION = - "This is a tool that searches anomaly results. It takes 9 arguments named detectorId which defines the detector ID to filter for (default is null), and realtime which defines whether the anomaly is real time, and anomalyGradeThreshold which defines the threshold for anomaly grade (a number between 0 and 1 that indicates how anomalous a data point is) (default is 0), and dataStartTime which defines the start time of the anomaly query (default is null), and dataEndTime which defines the end time of the anomaly query (default is null), and sortOrder which defines the order of the results (options are asc or desc, and default is desc), and sortString which which defines how to sort the results (default is data_start_time), and size which defines the size of the request to be returned (default is 20), and startIndex which defines the index to start from (default is 0). The tool returns a list of anomaly results, and the total number of anomaly result."; + "This is a tool that searches anomaly results. It takes 9 arguments named detectorId which defines the detector ID to filter for (default is null), and realtime which defines whether the anomaly is real time, and anomalyGradeThreshold which defines the threshold for anomaly grade (a number between 0 and 1 that indicates how anomalous a data point is) (default is 0), and dataStartTime which defines the start time of the anomaly query (default is null), and dataEndTime which defines the end time of the anomaly query (default is null), and sortOrder which defines the order of the results (options are asc or desc, and default is desc), and sortString which which defines how to sort the results (default is data_start_time), and size which defines the size of the request to be returned (default is 20), and startIndex which defines the index to start from (default is 0). The tool returns 2 values: a list of anomaly results (where each result contains the detector ID, the anomaly grade, and the confidence), and the total number of anomaly results."; @Setter @Getter diff --git a/src/main/java/org/opensearch/agent/tools/SearchMonitorsTool.java b/src/main/java/org/opensearch/agent/tools/SearchMonitorsTool.java index 8edcf22c..bbb9aaa7 100644 --- a/src/main/java/org/opensearch/agent/tools/SearchMonitorsTool.java +++ b/src/main/java/org/opensearch/agent/tools/SearchMonitorsTool.java @@ -49,8 +49,7 @@ public class SearchMonitorsTool implements Tool { public static final String TYPE = "SearchMonitorsTool"; private static final String DEFAULT_DESCRIPTION = - "This is a tool that searches alerting monitors. It takes 10 optional arguments named monitorId which defines the monitor ID to filter for (default is null), and monitorName which defines explicit name of the monitor (default is null), and monitorNamePattern which is a wildcard query to match detector name (default is null), and enabled which defines whether the monitor is enabled (default is null, indicating both), and hasTriggers which defines whether the monitor has triggers enabled (default is null, indicating both), and indices which defines the index being monitored (default is null), and sortOrder which defines the order of the results (options are asc or desc, and default is asc), and sortString which defines how to sort the results (default is name.keyword), and size which defines the size of the request to be returned (default is 20), and startIndex which defines the index to start from (default is 0). The tool returns a list of monitors, and the total number of monitors."; - + "This is a tool that searches alerting monitors. It takes 10 optional arguments named monitorId which defines the monitor ID to filter for (default is null), and monitorName which defines explicit name of the monitor (default is null), and monitorNamePattern which is a wildcard query to match detector name (default is null), and enabled which defines whether the monitor is enabled (default is null, indicating both), and hasTriggers which defines whether the monitor has triggers enabled (default is null, indicating both), and indices which defines the index being monitored (default is null), and sortOrder which defines the order of the results (options are asc or desc, and default is asc), and sortString which defines how to sort the results (default is name.keyword), and size which defines the size of the request to be returned (default is 20), and startIndex which defines the index to start from (default is 0). The tool returns 2 values: a list of alerting monitors (each containining ID, name, type, enabled, enabled time, last update time), and the total number of monitors."; @Setter @Getter private String name = TYPE; @@ -204,7 +203,11 @@ private void processHits(Map hitsAsMap, ActionListener for (SearchHit hit : hitsAsMap.values()) { sb.append("{"); sb.append("id=").append(hit.getId()).append(","); - sb.append("name=").append(hit.getSourceAsMap().get("name")); + sb.append("name=").append(hit.getSourceAsMap().get("name")).append(","); + sb.append("type=").append(hit.getSourceAsMap().get("type")).append(","); + sb.append("enabled=").append(hit.getSourceAsMap().get("enabled")).append(","); + sb.append("enabledTime=").append(hit.getSourceAsMap().get("enabled_time")).append(","); + sb.append("lastUpdateTime=").append(hit.getSourceAsMap().get("last_update_time")); sb.append("}"); } sb.append("]"); @@ -218,7 +221,11 @@ private void processGetMonitorHit(Monitor monitor, ActionListener listene sb.append("Monitors=["); sb.append("{"); sb.append("id=").append(monitor.getId()).append(","); - sb.append("name=").append(monitor.getName()); + sb.append("name=").append(monitor.getName()).append(","); + sb.append("type=").append(monitor.getType()).append(","); + sb.append("enabled=").append(monitor.getEnabled()).append(","); + sb.append("enabledTime=").append(monitor.getEnabledTime().toEpochMilli()).append(","); + sb.append("lastUpdateTime=").append(monitor.getLastUpdateTime().toEpochMilli()); sb.append("}]"); sb.append("TotalMonitors=1"); } else { diff --git a/src/test/java/org/opensearch/agent/tools/SearchAnomalyDetectorsToolTests.java b/src/test/java/org/opensearch/agent/tools/SearchAnomalyDetectorsToolTests.java index 3c5b4295..c4f0c293 100644 --- a/src/test/java/org/opensearch/agent/tools/SearchAnomalyDetectorsToolTests.java +++ b/src/test/java/org/opensearch/agent/tools/SearchAnomalyDetectorsToolTests.java @@ -14,6 +14,10 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Locale; @@ -27,6 +31,8 @@ import org.mockito.MockitoAnnotations; import org.opensearch.action.ActionType; import org.opensearch.action.search.SearchResponse; +import org.opensearch.ad.model.AnomalyDetector; +import org.opensearch.ad.model.IntervalTimeConfiguration; import org.opensearch.ad.transport.GetAnomalyDetectorAction; import org.opensearch.ad.transport.GetAnomalyDetectorResponse; import org.opensearch.ad.transport.SearchAnomalyDetectorAction; @@ -48,6 +54,8 @@ public class SearchAnomalyDetectorsToolTests { private Map emptyParams; private Map nonEmptyParams; + private AnomalyDetector testDetector; + @Before public void setup() { MockitoAnnotations.openMocks(this); @@ -56,6 +64,26 @@ public void setup() { nullParams = null; emptyParams = Collections.emptyMap(); nonEmptyParams = Map.of("detectorName", "foo"); + + testDetector = new AnomalyDetector( + "foo-id", + 1L, + "foo-name", + "foo-description", + "foo-time-field", + new ArrayList(Arrays.asList("foo-index")), + Collections.emptyList(), + null, + new IntervalTimeConfiguration(5, ChronoUnit.MINUTES), + null, + 1, + Collections.emptyMap(), + 1, + Instant.now(), + Collections.emptyList(), + null, + null + ); } @Test @@ -87,13 +115,16 @@ public void testRunWithSingleAnomalyDetector() throws Exception { XContentBuilder content = XContentBuilder.builder(XContentType.JSON.xContent()); content.startObject(); - content.field("name", detectorName); + content.field("name", testDetector.getName()); + content.field("type", testDetector.getDetectorType()); + content.field("description", testDetector.getDescription()); + content.field("indices", testDetector.getIndices().get(0)); + content.field("last_update_time", testDetector.getLastUpdateTime().toEpochMilli()); content.endObject(); SearchHit[] hits = new SearchHit[1]; - hits[0] = new SearchHit(0, detectorId, null, null).sourceRef(BytesReference.bytes(content)); + hits[0] = new SearchHit(0, testDetector.getDetectorId(), null, null).sourceRef(BytesReference.bytes(content)); SearchResponse getDetectorsResponse = TestHelpers.generateSearchResponse(hits); - String expectedResponseStr = String - .format("AnomalyDetectors=[{id=%s,name=%s}]TotalAnomalyDetectors=%d", detectorId, detectorName, hits.length); + String expectedResponseStr = getExpectedResponseString(testDetector); @SuppressWarnings("unchecked") ActionListener listener = Mockito.mock(ActionListener.class); @@ -122,8 +153,6 @@ public void testRunWithRunningDetectorTrue() throws Exception { SearchResponse getDetectorsResponse = TestHelpers.generateSearchResponse(hits); GetAnomalyDetectorResponse getDetectorProfileResponse = TestHelpers .generateGetAnomalyDetectorResponses(new String[] { detectorId }, new String[] { DetectorStateString.Running.name() }); - String expectedResponseStr = String - .format("AnomalyDetectors=[{id=%s,name=%s}]TotalAnomalyDetectors=%d", detectorId, detectorName, hits.length); @SuppressWarnings("unchecked") ActionListener listener = Mockito.mock(ActionListener.class); mockProfileApiCalls(getDetectorsResponse, getDetectorProfileResponse); @@ -131,7 +160,10 @@ public void testRunWithRunningDetectorTrue() throws Exception { tool.run(Map.of("running", "true"), listener); ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(String.class); verify(listener, times(1)).onResponse(responseCaptor.capture()); - assertEquals(expectedResponseStr, responseCaptor.getValue()); + String response = responseCaptor.getValue(); + assertTrue(response.contains(String.format("id=%s", detectorId))); + assertTrue(response.contains(String.format("name=%s", detectorName))); + assertTrue(response.contains(String.format("TotalAnomalyDetectors=%d", hits.length))); } @Test @@ -169,8 +201,6 @@ public void testRunWithRunningDetectorUndefined() throws Exception { SearchResponse getDetectorsResponse = TestHelpers.generateSearchResponse(hits); GetAnomalyDetectorResponse getDetectorProfileResponse = TestHelpers .generateGetAnomalyDetectorResponses(new String[] { detectorId }, new String[] { DetectorStateString.Running.name() }); - String expectedResponseStr = String - .format("AnomalyDetectors=[{id=%s,name=%s}]TotalAnomalyDetectors=%d", detectorId, detectorName, hits.length); @SuppressWarnings("unchecked") ActionListener listener = Mockito.mock(ActionListener.class); mockProfileApiCalls(getDetectorsResponse, getDetectorProfileResponse); @@ -178,7 +208,10 @@ public void testRunWithRunningDetectorUndefined() throws Exception { tool.run(Map.of("foo", "bar"), listener); ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(String.class); verify(listener, times(1)).onResponse(responseCaptor.capture()); - assertEquals(expectedResponseStr, responseCaptor.getValue()); + String response = responseCaptor.getValue(); + assertTrue(response.contains(String.format("id=%s", detectorId))); + assertTrue(response.contains(String.format("name=%s", detectorName))); + assertTrue(response.contains(String.format("TotalAnomalyDetectors=%d", hits.length))); } @Test @@ -196,8 +229,6 @@ public void testRunWithNullRealtimeTask() throws Exception { // Overriding the mocked response to realtime task and setting to null. This occurs when // a detector is created but is never started. when(getDetectorProfileResponse.getRealtimeAdTask()).thenReturn(null); - String expectedResponseStr = String - .format("AnomalyDetectors=[{id=%s,name=%s}]TotalAnomalyDetectors=%d", detectorId, detectorName, hits.length); @SuppressWarnings("unchecked") ActionListener listener = Mockito.mock(ActionListener.class); mockProfileApiCalls(getDetectorsResponse, getDetectorProfileResponse); @@ -205,7 +236,10 @@ public void testRunWithNullRealtimeTask() throws Exception { tool.run(Map.of("disabled", "true"), listener); ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(String.class); verify(listener, times(1)).onResponse(responseCaptor.capture()); - assertEquals(expectedResponseStr, responseCaptor.getValue()); + String response = responseCaptor.getValue(); + assertTrue(response.contains(String.format("id=%s", detectorId))); + assertTrue(response.contains(String.format("name=%s", detectorName))); + assertTrue(response.contains(String.format("TotalAnomalyDetectors=%d", hits.length))); } @Test @@ -222,8 +256,6 @@ public void testRunWithTaskStateCreated() throws Exception { .generateGetAnomalyDetectorResponses(new String[] { detectorId }, new String[] { DetectorStateString.Running.name() }); // Overriding the mocked response to set realtime task state to CREATED when(getDetectorProfileResponse.getRealtimeAdTask().getState()).thenReturn("CREATED"); - String expectedResponseStr = String - .format("AnomalyDetectors=[{id=%s,name=%s}]TotalAnomalyDetectors=%d", detectorId, detectorName, hits.length); @SuppressWarnings("unchecked") ActionListener listener = Mockito.mock(ActionListener.class); mockProfileApiCalls(getDetectorsResponse, getDetectorProfileResponse); @@ -231,7 +263,10 @@ public void testRunWithTaskStateCreated() throws Exception { tool.run(Map.of("running", "false"), listener); ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(String.class); verify(listener, times(1)).onResponse(responseCaptor.capture()); - assertEquals(expectedResponseStr, responseCaptor.getValue()); + String response = responseCaptor.getValue(); + assertTrue(response.contains(String.format("id=%s", detectorId))); + assertTrue(response.contains(String.format("name=%s", detectorName))); + assertTrue(response.contains(String.format("TotalAnomalyDetectors=%d", hits.length))); } @Test @@ -262,7 +297,14 @@ public void testRunWithTaskStateVariousFailed() throws Exception { tool.run(Map.of("failed", "true"), listener); ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(String.class); verify(listener, times(1)).onResponse(responseCaptor.capture()); - assertTrue(responseCaptor.getValue().contains("TotalAnomalyDetectors=3")); + String response = responseCaptor.getValue(); + assertTrue(response.contains(String.format("id=%s", detectorId1))); + assertTrue(response.contains(String.format("name=%s", detectorName1))); + assertTrue(response.contains(String.format("id=%s", detectorId2))); + assertTrue(response.contains(String.format("name=%s", detectorName2))); + assertTrue(response.contains(String.format("id=%s", detectorId3))); + assertTrue(response.contains(String.format("name=%s", detectorName3))); + assertTrue(response.contains(String.format("TotalAnomalyDetectors=%d", hits.length))); } @Test @@ -293,7 +335,14 @@ public void testRunWithCombinedDetectorStatesTrue() throws Exception { tool.run(Map.of("running", "true", "disabled", "true", "failed", "true"), listener); ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(String.class); verify(listener, times(1)).onResponse(responseCaptor.capture()); - assertTrue(responseCaptor.getValue().contains("TotalAnomalyDetectors=3")); + String response = responseCaptor.getValue(); + assertTrue(response.contains(String.format("id=%s", detectorId1))); + assertTrue(response.contains(String.format("name=%s", detectorName1))); + assertTrue(response.contains(String.format("id=%s", detectorId2))); + assertTrue(response.contains(String.format("name=%s", detectorName2))); + assertTrue(response.contains(String.format("id=%s", detectorId3))); + assertTrue(response.contains(String.format("name=%s", detectorName3))); + assertTrue(response.contains(String.format("TotalAnomalyDetectors=%d", hits.length))); } @Test @@ -355,7 +404,12 @@ public void testRunWithCombinedDetectorStatesMixed() throws Exception { tool.run(Map.of("running", "true", "disabled", "false", "failed", "true"), listener); ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(String.class); verify(listener, times(1)).onResponse(responseCaptor.capture()); - assertTrue(responseCaptor.getValue().contains("TotalAnomalyDetectors=2")); + String response = responseCaptor.getValue(); + assertTrue(response.contains(String.format("id=%s", detectorId1))); + assertTrue(response.contains(String.format("name=%s", detectorName1))); + assertTrue(response.contains(String.format("id=%s", detectorId3))); + assertTrue(response.contains(String.format("name=%s", detectorName3))); + assertTrue(response.contains(String.format("TotalAnomalyDetectors=%d", 2))); } @Test @@ -403,4 +457,19 @@ private void mockProfileApiCalls(SearchResponse getDetectorsResponse, GetAnomaly return null; }).when(nodeClient).execute(any(GetAnomalyDetectorAction.class), any(), any()); } + + private String getExpectedResponseString(AnomalyDetector testDetector) { + return String + .format( + "AnomalyDetectors=[{id=%s,name=%s,type=%s,description=%s,index=%s,lastUpdateTime=%d}]TotalAnomalyDetectors=%d", + testDetector.getDetectorId(), + testDetector.getName(), + testDetector.getDetectorType(), + testDetector.getDescription(), + testDetector.getIndices().get(0), + testDetector.getLastUpdateTime().toEpochMilli(), + 1 + ); + + } } diff --git a/src/test/java/org/opensearch/agent/tools/SearchMonitorsToolTests.java b/src/test/java/org/opensearch/agent/tools/SearchMonitorsToolTests.java index 37bc960f..72338fec 100644 --- a/src/test/java/org/opensearch/agent/tools/SearchMonitorsToolTests.java +++ b/src/test/java/org/opensearch/agent/tools/SearchMonitorsToolTests.java @@ -140,9 +140,7 @@ public void testRunWithMonitorId() throws Exception { testMonitor, Collections.emptyList() ); - String expectedResponseStr = String - .format("Monitors=[{id=%s,name=%s}]TotalMonitors=%d", testMonitor.getId(), testMonitor.getName(), 1); - + String expectedResponseStr = getExpectedResponseString(testMonitor); @SuppressWarnings("unchecked") ActionListener listener = Mockito.mock(ActionListener.class); @@ -186,8 +184,11 @@ public void testRunWithSingleMonitor() throws Exception { XContentBuilder content = XContentBuilder.builder(XContentType.JSON.xContent()); content.startObject(); - content.field("type", "monitor"); content.field("name", testMonitor.getName()); + content.field("type", testMonitor.getType()); + content.field("enabled", Boolean.toString(testMonitor.getEnabled())); + content.field("enabled_time", Long.toString(testMonitor.getEnabledTime().toEpochMilli())); + content.field("last_update_time", Long.toString(testMonitor.getLastUpdateTime().toEpochMilli())); content.endObject(); SearchHit[] hits = new SearchHit[1]; hits[0] = new SearchHit(0, testMonitor.getId(), null, null).sourceRef(BytesReference.bytes(content)); @@ -204,8 +205,7 @@ public void testRunWithSingleMonitor() throws Exception { null, null ); - String expectedResponseStr = String - .format("Monitors=[{id=%s,name=%s}]TotalMonitors=%d", testMonitor.getId(), testMonitor.getName(), hits.length); + String expectedResponseStr = getExpectedResponseString(testMonitor); @SuppressWarnings("unchecked") ActionListener listener = Mockito.mock(ActionListener.class); @@ -253,4 +253,19 @@ public void testValidate() { assertTrue(tool.validate(monitorIdParams)); assertTrue(tool.validate(nullParams)); } + + private String getExpectedResponseString(Monitor testMonitor) { + return String + .format( + "Monitors=[{id=%s,name=%s,type=%s,enabled=%s,enabledTime=%d,lastUpdateTime=%d}]TotalMonitors=%d", + testMonitor.getId(), + testMonitor.getName(), + testMonitor.getType(), + testMonitor.getEnabled(), + testMonitor.getEnabledTime().toEpochMilli(), + testMonitor.getLastUpdateTime().toEpochMilli(), + 1 + ); + + } } diff --git a/src/test/java/org/opensearch/integTest/SearchAnomalyDetectorsToolIT.java b/src/test/java/org/opensearch/integTest/SearchAnomalyDetectorsToolIT.java index 0faa7a21..aa406f8d 100644 --- a/src/test/java/org/opensearch/integTest/SearchAnomalyDetectorsToolIT.java +++ b/src/test/java/org/opensearch/integTest/SearchAnomalyDetectorsToolIT.java @@ -8,7 +8,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; -import java.util.Locale; import org.junit.After; import org.junit.Before; @@ -69,10 +68,9 @@ public void testSearchAnomalyDetectorsToolInFlowAgent_matching() { String agentId = createAgent(registerAgentRequestBody); String agentInput = "{\"parameters\":{\"detectorName\": \"" + detectorName + "\"}}"; String result = executeAgent(agentId, agentInput); - assertEquals( - String.format(Locale.ROOT, "AnomalyDetectors=[{id=%s,name=%s}]TotalAnomalyDetectors=%d", detectorId, detectorName, 1), - result - ); + assertTrue(result.contains(String.format("id=%s", detectorId))); + assertTrue(result.contains(String.format("name=%s", detectorName))); + assertTrue(result.contains(String.format("TotalAnomalyDetectors=%d", 1))); } @SneakyThrows