-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ML] Decouple open-in-anomaly-explorer action #178729
[ML] Decouple open-in-anomaly-explorer action #178729
Conversation
Pinging @elastic/ml-ui (:ml) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed offline, in x-pack/plugins/ml/public/ui_actions/open_in_anomaly_explorer_action.tsx
, the action can no longer use embeddable.getInput
and embeddable.getOutput
. Instead, action will have to read values directly from embeddable. For example embeddable.jobIds
. All embeddables that support this action will have to expose jobIds
.
|
||
const { jobIds, timeRange, viewBy } = embeddable.getInput(); | ||
const { perPage, fromPage } = embeddable.getOutput(); | ||
const { localTimeRange, viewBy, jobIds, perPage, fromPage } = embeddable; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
update from main, localTimeRange has been renamed to timeRange$
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more thing. embeddable.getInput().timeRange combined dashboard time range and any custom time range stored with the panel. I think when reading this you will need
const timeRange = embeddable.timeRange$?.value ?? embeddable.parentApi?.timeRange$?.value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 4211c14
constructor( | ||
initialInput: AnomalySwimlaneEmbeddableInput, | ||
public services: [CoreStart, MlDependencies, AnomalySwimlaneServices], | ||
parent?: IContainer | ||
) { | ||
super(initialInput, services[2].anomalyDetectorService, services[1].data.dataViews, parent); | ||
|
||
this.apiSubscriptions.add( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you will want to add distinctUntilKeyChanged
so that BehaviorSubject is only updated when the key changes, and not everytime the output or input changes. You should just be able to use embeddableInputToSubject
and embeddableOutputToSubject
utility methods from src/plugins/embeddable/public/lib/embeddables/compatibility/embeddable_compatibility_utils.ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated in fd352ad
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! The actions are decoupled as expected, and the changes to the embeddable plugin look good.
Left a few small nits and cleanups. LGTM!
@@ -41,12 +42,37 @@ export class AnomalySwimlaneEmbeddable extends AnomalyDetectionEmbeddable< | |||
private reload$ = new Subject<void>(); | |||
public readonly type: string = ANOMALY_SWIMLANE_EMBEDDABLE_TYPE; | |||
|
|||
// API | |||
public viewBy = new BehaviorSubject<string | undefined>(this.getInput().viewBy); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit. If you're initializing these in the constructor via embeddableInputToSubject
or embeddableOutputToSubject
, you don't need to initialize them via new
here. The helpers will handle that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good spot, leftovers from the original implementation, updated in 48d9c50
public perPage = new BehaviorSubject<number | undefined>(this.getOutput().perPage); | ||
public fromPage = new BehaviorSubject<number | undefined>(this.getOutput().fromPage); | ||
|
||
private apiSubscriptions = new Subscription(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I pass it to embeddableInputToSubject
and embeddableOutputToSubject
to populate subscriptions and unsubscribe on destroy
@@ -40,12 +41,25 @@ export class AnomalyChartsEmbeddable extends AnomalyDetectionEmbeddable< | |||
private reload$ = new Subject<void>(); | |||
public readonly type: string = ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE; | |||
|
|||
// API | |||
public entityFields = new BehaviorSubject<MlEntityField[] | undefined>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use embeddableOutputToSubject
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made it for one embeddable and forgot the other 🤦🏻 Updated in d4debca
} | ||
|
||
export interface SwimLaneDrilldownApi { | ||
// Props from embeddable input |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need these comments? Ideally soon these won't have any connection to the legacy embeddable's input / output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did the cleanup in 22df822
embeddable, | ||
}: SwimLaneDrilldownContext | AnomalyChartsFieldSelectionContext) { | ||
async isCompatible({ embeddable }: EmbeddableApiContext) { | ||
if (!isApiCompatible(embeddable)) return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Here, wouldn't it be simpler to call your more specific type guards like:
return isSwimLaneEmbeddableContext(context) || isAnomalyChartsEmbeddableContext(context)
? That way you wouldn't need to have the separate isApiCompatible
method which checks the same things?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I first wrote this isCompatible
method looking at the example and added custom type guards later. Updated in dfaef99
💛 Build succeeded, but was flaky
Failed CI StepsTest Failures
Metrics [docs]Public APIs missing comments
Async chunks
Public APIs missing exports
Page load bundle
History
To update your PR or re-run it, just comment with: cc @darnautov |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested the 'Open in Anomaly Explorer' action with embedded swim lane and anomaly charts in dashboards and cases and LGTM
Summary
Decouples open-in-anomaly-explorer UI action from embeddable framework.
Part of #178375
Part of #174967