Skip to content

Commit 36fd364

Browse files
committed
Check feature flag before registering action to Discover page
Signed-off-by: gaobinlong <gbinlong@amazon.com>
1 parent c9c5eeb commit 36fd364

File tree

3 files changed

+74
-20
lines changed

3 files changed

+74
-20
lines changed

public/components/DiscoverAction/SuggestAnomalyDetector.test.tsx

+54-13
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ jest.mock('../../services', () => ({
4141
},
4242
}),
4343
getAssistantClient: jest.fn().mockReturnValue({
44-
executeAgentByName: jest.fn(),
44+
agentConfigExists: jest.fn(),
45+
executeAgentByConfigName: jest.fn(),
4546
}),
4647
getUsageCollection: jest.fn(),
4748
}));
@@ -127,11 +128,13 @@ describe('GenerateAnomalyDetector spec', () => {
127128
timeFieldName: '@timestamp',
128129
},
129130
});
130-
131+
(getAssistantClient().agentConfigExists as jest.Mock).mockResolvedValueOnce({
132+
exists: true
133+
});
131134
});
132135

133136
it('renders with empty generated parameters', async () => {
134-
(getAssistantClient().executeAgentByName as jest.Mock).mockResolvedValueOnce({
137+
(getAssistantClient().executeAgentByConfigName as jest.Mock).mockResolvedValueOnce({
135138
body: {
136139
inference_results: [
137140
{
@@ -155,7 +158,7 @@ describe('GenerateAnomalyDetector spec', () => {
155158
});
156159

157160
it('renders with empty parameter', async () => {
158-
(getAssistantClient().executeAgentByName as jest.Mock).mockResolvedValueOnce({
161+
(getAssistantClient().executeAgentByConfigName as jest.Mock).mockResolvedValueOnce({
159162
body: {
160163
inference_results: [
161164
{
@@ -179,7 +182,7 @@ describe('GenerateAnomalyDetector spec', () => {
179182
});
180183

181184
it('renders with empty aggregation field or empty aggregation method', async () => {
182-
(getAssistantClient().executeAgentByName as jest.Mock).mockResolvedValueOnce({
185+
(getAssistantClient().executeAgentByConfigName as jest.Mock).mockResolvedValueOnce({
183186
body: {
184187
inference_results: [
185188
{
@@ -203,7 +206,7 @@ describe('GenerateAnomalyDetector spec', () => {
203206
});
204207

205208
it('renders with different number of aggregation methods and fields', async () => {
206-
(getAssistantClient().executeAgentByName as jest.Mock).mockResolvedValueOnce({
209+
(getAssistantClient().executeAgentByConfigName as jest.Mock).mockResolvedValueOnce({
207210
body: {
208211
inference_results: [
209212
{
@@ -227,7 +230,7 @@ describe('GenerateAnomalyDetector spec', () => {
227230
});
228231

229232
it('renders component completely', async () => {
230-
(getAssistantClient().executeAgentByName as jest.Mock).mockResolvedValueOnce({
233+
(getAssistantClient().executeAgentByConfigName as jest.Mock).mockResolvedValueOnce({
231234
body: {
232235
inference_results: [
233236
{
@@ -252,6 +255,37 @@ describe('GenerateAnomalyDetector spec', () => {
252255
});
253256
});
254257

258+
describe('Test agent not configured', () => {
259+
beforeEach(() => {
260+
jest.clearAllMocks();
261+
const queryService = getQueryService();
262+
queryService.queryString.getQuery.mockReturnValue({
263+
dataset: {
264+
id: 'test-pattern',
265+
title: 'test-pattern',
266+
type: 'INDEX_PATTERN',
267+
timeFieldName: '@timestamp',
268+
},
269+
});
270+
});
271+
272+
it('renders with empty generated parameters', async () => {
273+
(getAssistantClient().agentConfigExists as jest.Mock).mockResolvedValueOnce({
274+
exists: false
275+
});
276+
277+
const { queryByText } = renderWithRouter();
278+
expect(queryByText('Suggested anomaly detector')).not.toBeNull();
279+
280+
await waitFor(() => {
281+
expect(getNotifications().toasts.addDanger).toHaveBeenCalledTimes(1);
282+
expect(getNotifications().toasts.addDanger).toHaveBeenCalledWith(
283+
'Generate parameters for creating anomaly detector failed, reason: Error: Agent for suggest anomaly detector not found, please configure an agent firstly!'
284+
);
285+
});
286+
});
287+
});
288+
255289
describe('Test feedback', () => {
256290
let reportUiStatsMock: any;
257291

@@ -273,14 +307,18 @@ describe('GenerateAnomalyDetector spec', () => {
273307
CLICK: 'click',
274308
},
275309
});
310+
311+
(getAssistantClient().agentConfigExists as jest.Mock).mockResolvedValueOnce({
312+
exists: true
313+
});
276314
});
277315

278316
afterEach(() => {
279317
jest.clearAllMocks();
280318
});
281319

282320
it('should call reportMetric with thumbup when thumbs up is clicked', async () => {
283-
(getAssistantClient().executeAgentByName as jest.Mock).mockResolvedValueOnce({
321+
(getAssistantClient().executeAgentByConfigName as jest.Mock).mockResolvedValueOnce({
284322
body: {
285323
inference_results: [
286324
{
@@ -316,7 +354,7 @@ describe('GenerateAnomalyDetector spec', () => {
316354

317355

318356
it('should call reportMetric with thumbdown when thumbs down is clicked', async () => {
319-
(getAssistantClient().executeAgentByName as jest.Mock).mockResolvedValueOnce({
357+
(getAssistantClient().executeAgentByConfigName as jest.Mock).mockResolvedValueOnce({
320358
body: {
321359
inference_results: [
322360
{
@@ -363,6 +401,9 @@ describe('GenerateAnomalyDetector spec', () => {
363401
timeFieldName: '@timestamp',
364402
},
365403
});
404+
(getAssistantClient().agentConfigExists as jest.Mock).mockResolvedValueOnce({
405+
exists: true
406+
});
366407
});
367408

368409
it('All API calls execute successfully', async () => {
@@ -382,7 +423,7 @@ describe('GenerateAnomalyDetector spec', () => {
382423
});
383424
}
384425
});
385-
(getAssistantClient().executeAgentByName as jest.Mock).mockResolvedValueOnce({
426+
(getAssistantClient().executeAgentByConfigName as jest.Mock).mockResolvedValueOnce({
386427
body: {
387428
inference_results: [
388429
{
@@ -414,7 +455,7 @@ describe('GenerateAnomalyDetector spec', () => {
414455
});
415456

416457
it('Generate parameters failed', async () => {
417-
(getAssistantClient().executeAgentByName as jest.Mock).mockRejectedValueOnce('Generate parameters failed');
458+
(getAssistantClient().executeAgentByConfigName as jest.Mock).mockRejectedValueOnce('Generate parameters failed');
418459

419460
const { queryByText } = renderWithRouter();
420461
expect(queryByText('Suggested anomaly detector')).not.toBeNull();
@@ -441,7 +482,7 @@ describe('GenerateAnomalyDetector spec', () => {
441482
});
442483
}
443484
});
444-
(getAssistantClient().executeAgentByName as jest.Mock).mockResolvedValueOnce({
485+
(getAssistantClient().executeAgentByConfigName as jest.Mock).mockResolvedValueOnce({
445486
body: {
446487
inference_results: [
447488
{
@@ -512,7 +553,7 @@ describe('GenerateAnomalyDetector spec', () => {
512553
},
513554
});
514555

515-
(getAssistantClient().executeAgentByName as jest.Mock).mockResolvedValueOnce({
556+
(getAssistantClient().executeAgentByConfigName as jest.Mock).mockResolvedValueOnce({
516557
body: {
517558
inference_results: [
518559
{

public/components/DiscoverAction/SuggestAnomalyDetector.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,12 @@ function SuggestAnomalyDetector({
144144
// let LLM to generate parameters for creating anomaly detector
145145
async function getParameters() {
146146
try {
147+
const checkAgentExistsResponse = await assistantClient.agentConfigExists(SUGGEST_ANOMALY_DETECTOR_CONFIG_ID, { dataSourceId });
148+
if (!checkAgentExistsResponse?.exists) {
149+
throw new Error('Agent for suggest anomaly detector not found, please configure an agent firstly!');
150+
}
147151
const executeAgentResponse = await
148-
assistantClient.executeAgentByName(SUGGEST_ANOMALY_DETECTOR_CONFIG_ID, { index: indexName }, { dataSourceId }
152+
assistantClient.executeAgentByConfigName(SUGGEST_ANOMALY_DETECTOR_CONFIG_ID, { index: indexName }, { dataSourceId }
149153
);
150154
reportMetric(SUGGEST_ANOMALY_DETECTOR_METRIC_TYPE.GENERATED);
151155
const rawGeneratedParameters = executeAgentResponse?.body?.inference_results?.[0]?.output?.[0]?.result;
@@ -317,7 +321,7 @@ function SuggestAnomalyDetector({
317321
<EuiText>
318322
Detector created: <a href="#" onClick={(e) => {
319323
e.preventDefault();
320-
const url = `../${PLUGIN_NAME}#/detectors/${detectorId}`;
324+
const url = `../${PLUGIN_NAME}#/detectors/${detectorId}/results?dataSourceId=${dataSourceId}`;
321325
window.open(url, '_blank');
322326
}} style={{ textDecoration: 'underline' }}>{formikProps.values.name}</a>
323327
</EuiText >

public/plugin.ts

+14-5
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,20 @@ export class AnomalyDetectionOpenSearchDashboardsPlugin
195195
plugins.uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, action);
196196
});
197197

198-
setUsageCollection(plugins.usageCollection);
199-
// Add suggest anomaly detector action to the uiActions in Discover
200-
if (plugins.assistantDashboards?.assistantTriggers?.AI_ASSISTANT_QUERY_EDITOR_TRIGGER) {
201-
const suggestAnomalyDetectorAction = getSuggestAnomalyDetectorAction();
202-
plugins.uiActions.addTriggerAction(plugins.assistantDashboards.assistantTriggers.AI_ASSISTANT_QUERY_EDITOR_TRIGGER, suggestAnomalyDetectorAction);
198+
// register suggest anomaly detector action to Discover only if the feature flag is enabled
199+
if (plugins.assistantDashboards?.getFeatureStatus().smartAnomalyDetector && plugins.assistantDashboards?.assistantTriggers?.AI_ASSISTANT_QUERY_EDITOR_TRIGGER) {
200+
const checkAndRegisterAction = async () => {
201+
const [coreStart] = await core.getStartServices();
202+
const assistantEnabled = coreStart.application.capabilities?.assistant?.enabled === true;
203+
if (assistantEnabled) {
204+
// Add suggest anomaly detector action to the uiActions in Discover
205+
const suggestAnomalyDetectorAction = getSuggestAnomalyDetectorAction();
206+
plugins.uiActions.addTriggerAction(plugins.assistantDashboards.assistantTriggers.AI_ASSISTANT_QUERY_EDITOR_TRIGGER, suggestAnomalyDetectorAction);
207+
// set usageCollection for metric report
208+
setUsageCollection(plugins.usageCollection);
209+
}
210+
}
211+
checkAndRegisterAction();
203212
}
204213
// registers the expression function used to render anomalies on an Augmented Visualization
205214
plugins.expressions.registerFunction(overlayAnomaliesFunction);

0 commit comments

Comments
 (0)