3
3
* SPDX-License-Identifier: Apache-2.0
4
4
*/
5
5
6
- import React , { useState , useEffect , Fragment } from 'react' ;
6
+ import React , { useState , useEffect , Fragment , useCallback } from 'react' ;
7
7
import {
8
8
EuiFlyoutHeader ,
9
9
EuiFlyoutBody ,
@@ -22,6 +22,7 @@ import {
22
22
EuiButtonEmpty ,
23
23
EuiPanel ,
24
24
EuiComboBox ,
25
+ EuiSmallButtonIcon ,
25
26
} from '@elastic/eui' ;
26
27
import '../FeatureAnywhereContextMenu/CreateAnomalyDetector/styles.scss' ;
27
28
import { useDispatch , useSelector } from 'react-redux' ;
@@ -62,8 +63,8 @@ import {
62
63
import { formikToDetector } from '../../pages/ReviewAndCreate/utils/helpers' ;
63
64
import { FormattedFormRow } from '../FormattedFormRow/FormattedFormRow' ;
64
65
import { FeatureAccordion } from '../../pages/ConfigureModel/components/FeatureAccordion' ;
65
- import { AD_DOCS_LINK , DEFAULT_SHINGLE_SIZE , MAX_FEATURE_NUM , PLUGIN_NAME } from '../../utils/constants' ;
66
- import { getAssistantClient , getNotifications , getQueryService } from '../../services' ;
66
+ import { AD_DOCS_LINK , DEFAULT_SHINGLE_SIZE , MAX_FEATURE_NUM , PLUGIN_NAME , SUGGEST_ANOMALY_DETECTOR_METRIC_TYPE } from '../../utils/constants' ;
67
+ import { getAssistantClient , getNotifications , getQueryService , getUsageCollection } from '../../services' ;
67
68
import { prettifyErrorMessage } from '../../../server/utils/helpers' ;
68
69
import EnhancedAccordion from '../FeatureAnywhereContextMenu/EnhancedAccordion' ;
69
70
import MinimalAccordion from '../FeatureAnywhereContextMenu/MinimalAccordion' ;
@@ -75,6 +76,7 @@ import { mountReactNode } from '../../../../../src/core/public/utils';
75
76
import { formikToDetectorName } from '../FeatureAnywhereContextMenu/CreateAnomalyDetector/helpers' ;
76
77
import { DEFAULT_DATA } from '../../../../../src/plugins/data/common' ;
77
78
import { AppState } from '../../redux/reducers' ;
79
+ import { v4 as uuidv4 } from 'uuid' ;
78
80
79
81
export interface GeneratedParameters {
80
82
categoryField : string ;
@@ -89,6 +91,7 @@ function SuggestAnomalyDetector({
89
91
} ) {
90
92
const dispatch = useDispatch ( ) ;
91
93
const notifications = getNotifications ( ) ;
94
+ const usageCollection = getUsageCollection ( ) ;
92
95
const assistantClient = getAssistantClient ( ) ;
93
96
94
97
const queryString = getQueryService ( ) . queryString ;
@@ -136,12 +139,15 @@ function SuggestAnomalyDetector({
136
139
const dateNanoFields = get ( indexDataTypes , 'date_nanos' , [ ] ) as string [ ] ;
137
140
const allDateFields = dateFields . concat ( dateNanoFields ) ;
138
141
142
+ const [ feedbackResult , setFeedbackResult ] = useState < boolean | undefined > ( undefined ) ;
143
+
139
144
// let LLM to generate parameters for creating anomaly detector
140
145
async function getParameters ( ) {
141
146
try {
142
147
const executeAgentResponse = await
143
148
assistantClient . executeAgentByName ( SUGGEST_ANOMALY_DETECTOR_CONFIG_ID , { index : indexName } , { dataSourceId }
144
149
) ;
150
+ reportMetric ( SUGGEST_ANOMALY_DETECTOR_METRIC_TYPE . GENERATED ) ;
145
151
const rawGeneratedParameters = executeAgentResponse ?. body ?. inference_results ?. [ 0 ] ?. output ?. [ 0 ] ?. result ;
146
152
if ( ! rawGeneratedParameters ) {
147
153
throw new Error ( 'Cannot get generated parameters!' ) ;
@@ -240,6 +246,28 @@ function SuggestAnomalyDetector({
240
246
setDelayValue ( e . target . value ) ;
241
247
} ;
242
248
249
+ const reportMetric = usageCollection
250
+ ? ( metric : string ) => {
251
+ usageCollection . reportUiStats (
252
+ `suggestAD` ,
253
+ usageCollection . METRIC_TYPE . CLICK ,
254
+ metric + '-' + uuidv4 ( )
255
+ ) ;
256
+ }
257
+ : ( ) => { } ;
258
+
259
+ const feedbackOutput = useCallback (
260
+ ( correct : boolean , result : boolean | undefined ) => {
261
+ // No repeated feedback.
262
+ if ( result !== undefined ) {
263
+ return ;
264
+ }
265
+ reportMetric ( correct ? SUGGEST_ANOMALY_DETECTOR_METRIC_TYPE . THUMBUP : SUGGEST_ANOMALY_DETECTOR_METRIC_TYPE . THUMBDOWN ) ;
266
+ setFeedbackResult ( correct ) ;
267
+ } ,
268
+ [ ]
269
+ ) ;
270
+
243
271
const handleValidationAndSubmit = ( formikProps : any ) => {
244
272
if ( formikProps . values . featureList . length !== 0 ) {
245
273
formikProps . setFieldTouched ( 'featureList' , true ) ;
@@ -264,6 +292,7 @@ function SuggestAnomalyDetector({
264
292
const detectorToCreate = formikToDetector ( formikProps . values ) ;
265
293
await dispatch ( createDetector ( detectorToCreate , dataSourceId ) )
266
294
. then ( async ( response : any ) => {
295
+ reportMetric ( SUGGEST_ANOMALY_DETECTOR_METRIC_TYPE . CREATED ) ;
267
296
const detectorId = response . response . id ;
268
297
dispatch ( startDetector ( detectorId , dataSourceId ) )
269
298
. then ( ( ) => { } )
@@ -839,6 +868,34 @@ function SuggestAnomalyDetector({
839
868
< EuiFlexItem grow = { false } >
840
869
< EuiButtonEmpty onClick = { closeFlyout } > Cancel</ EuiButtonEmpty >
841
870
</ EuiFlexItem >
871
+ < EuiFlexGroup alignItems = "center" gutterSize = 'none' justifyContent = "flexEnd" >
872
+ < EuiFlexItem grow = { false } >
873
+ < EuiText size = 's' > Was this helpful?</ EuiText >
874
+ </ EuiFlexItem >
875
+ { feedbackResult !== false ? (
876
+ < EuiFlexItem grow = { false } >
877
+ < EuiSmallButtonIcon
878
+ aria-label = "feedback thumbs up"
879
+ color = { feedbackResult === true ? 'primary' : 'text' }
880
+ iconType = "thumbsUp"
881
+ disabled = { isLoading }
882
+ onClick = { ( ) => feedbackOutput ( true , feedbackResult ) }
883
+ />
884
+ </ EuiFlexItem >
885
+ ) : null }
886
+ { feedbackResult !== true ? (
887
+ < EuiFlexItem grow = { false } >
888
+ < EuiSmallButtonIcon
889
+ aria-label = "feedback thumbs down"
890
+ color = { feedbackResult === false ? 'primary' : 'text' }
891
+ iconType = "thumbsDown"
892
+ disabled = { isLoading }
893
+ onClick = { ( ) => feedbackOutput ( false , feedbackResult ) }
894
+ />
895
+ </ EuiFlexItem >
896
+ ) : null }
897
+ </ EuiFlexGroup >
898
+
842
899
< EuiFlexItem grow = { false } >
843
900
< EuiButton
844
901
fill = { true }
0 commit comments