-
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
[Maps][ML] Integration follow up: adds partition field info to map point tooltip if available #123516
[Maps][ML] Integration follow up: adds partition field info to map point tooltip if available #123516
Changes from 3 commits
6a4dbf4
690b39d
2321384
1ae5ddc
5e55ba0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,18 +40,58 @@ export const ANOMALY_SOURCE_FIELDS: Record<string, Record<string, string>> = { | |
}), | ||
type: 'string', | ||
}, | ||
// this value is only used to place the point on the map | ||
actual: {}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: suggestion to add a comment to clarify what's the difference between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added in 2321384 |
||
actualDisplay: { | ||
label: i18n.translate('xpack.ml.maps.anomalyLayerActualLabel', { | ||
defaultMessage: 'Actual', | ||
}), | ||
type: 'string', | ||
}, | ||
// this value is only used to place the point on the map | ||
typical: {}, | ||
typicalDisplay: { | ||
label: i18n.translate('xpack.ml.maps.anomalyLayerTypicalLabel', { | ||
defaultMessage: 'Typical', | ||
}), | ||
type: 'string', | ||
}, | ||
partition_field_name: { | ||
label: i18n.translate('xpack.ml.maps.anomalyLayerPartitionFieldNameLabel', { | ||
defaultMessage: 'Partition field name', | ||
}), | ||
type: 'string', | ||
}, | ||
partition_field_value: { | ||
label: i18n.translate('xpack.ml.maps.anomalyLayerPartitionFieldValueLabel', { | ||
defaultMessage: 'Partition field value', | ||
}), | ||
type: 'string', | ||
}, | ||
by_field_name: { | ||
label: i18n.translate('xpack.ml.maps.anomalyLayerByFieldNameLabel', { | ||
defaultMessage: 'By field name', | ||
}), | ||
type: 'string', | ||
}, | ||
by_field_value: { | ||
label: i18n.translate('xpack.ml.maps.anomalyLayerByFieldValueLabel', { | ||
defaultMessage: 'By field value', | ||
}), | ||
type: 'string', | ||
}, | ||
over_field_name: { | ||
label: i18n.translate('xpack.ml.maps.anomalyLayerOverFieldNameLabel', { | ||
defaultMessage: 'Over field name', | ||
}), | ||
type: 'string', | ||
}, | ||
over_field_value: { | ||
label: i18n.translate('xpack.ml.maps.anomalyLayerOverFieldValueLabel', { | ||
defaultMessage: 'Over field value', | ||
}), | ||
type: 'string', | ||
}, | ||
}; | ||
|
||
export class AnomalySourceTooltipProperty implements ITooltipProperty { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,12 @@ import type { MlApiServices } from '../application/services/ml_api_service'; | |
import { MLAnomalyDoc } from '../../common/types/anomalies'; | ||
import { VectorSourceRequestMeta } from '../../../maps/common'; | ||
|
||
export type MlAnomalyLayers = 'typical' | 'actual' | 'connected'; | ||
export type MlAnomalyLayers = 'typical' | 'actual' | 'typical to actual'; | ||
export enum ML_ANOMALY_LAYERS { | ||
TYPICAL = 'typical', | ||
ACTUAL = 'actual', | ||
TYPICAL_TO_ACTUAL = 'typical to actual', | ||
} | ||
|
||
// Must reverse coordinates here. Map expects [lon, lat] - anomalies are stored as [lat, lon] for lat_lon jobs | ||
function getCoordinates(actualCoordinateStr: string, round: boolean = false): number[] { | ||
|
@@ -64,16 +69,6 @@ export async function getResultsForJobId( | |
} | ||
|
||
let resp: ESSearchResponse<MLAnomalyDoc> | null = null; | ||
let hits: Array<{ | ||
actual: number[]; | ||
actualDisplay: number[]; | ||
fieldName?: string; | ||
functionDescription: string; | ||
typical: number[]; | ||
typicalDisplay: number[]; | ||
record_score: number; | ||
timestamp: string; | ||
}> = []; | ||
|
||
try { | ||
resp = await mlResultsService.anomalySearch( | ||
|
@@ -86,8 +81,9 @@ export async function getResultsForJobId( | |
// search may fail if the job doesn't already exist | ||
// ignore this error as the outer function call will raise a toast | ||
} | ||
if (resp !== null && resp.hits.total.value > 0) { | ||
hits = resp.hits.hits.map(({ _source }) => { | ||
|
||
const features: Feature[] = | ||
resp?.hits.hits.map(({ _source }) => { | ||
const geoResults = _source.geo_results; | ||
const actualCoordStr = geoResults && geoResults.actual_point; | ||
const typicalCoordStr = geoResults && geoResults.typical_point; | ||
|
@@ -104,47 +100,41 @@ export async function getResultsForJobId( | |
typical = getCoordinates(typicalCoordStr); | ||
typicalDisplay = getCoordinates(typicalCoordStr, true); | ||
} | ||
return { | ||
fieldName: _source.field_name, | ||
functionDescription: _source.function_description, | ||
timestamp: formatHumanReadableDateTimeSeconds(_source.timestamp), | ||
typical, | ||
typicalDisplay, | ||
actual, | ||
actualDisplay, | ||
record_score: Math.floor(_source.record_score), | ||
}; | ||
}); | ||
} | ||
|
||
const features: Feature[] = hits.map((result) => { | ||
let geometry: Geometry; | ||
if (locationType === 'typical' || locationType === 'actual') { | ||
geometry = { | ||
type: 'Point', | ||
coordinates: locationType === 'typical' ? result.typical : result.actual, | ||
}; | ||
} else { | ||
geometry = { | ||
type: 'LineString', | ||
coordinates: [result.typical, result.actual], | ||
let geometry: Geometry; | ||
if (locationType === 'typical' || locationType === 'actual') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: I think we can use the new ML_ANOMALY_LAYERS here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep - missed it! thanks - 1ae5ddc |
||
geometry = { | ||
type: 'Point', | ||
coordinates: locationType === 'typical' ? typical : actual, | ||
}; | ||
} else { | ||
geometry = { | ||
type: 'LineString', | ||
coordinates: [typical, actual], | ||
}; | ||
} | ||
return { | ||
type: 'Feature', | ||
geometry, | ||
properties: { | ||
actual, | ||
actualDisplay, | ||
typical, | ||
typicalDisplay, | ||
fieldName: _source.field_name, | ||
functionDescription: _source.function_description, | ||
timestamp: formatHumanReadableDateTimeSeconds(_source.timestamp), | ||
record_score: Math.floor(_source.record_score), | ||
...(_source.partition_field_name | ||
? { [_source.partition_field_name]: _source.partition_field_value } | ||
: {}), | ||
...(_source.by_field_name ? { [_source.by_field_name]: _source.by_field_value } : {}), | ||
...(_source.over_field_name | ||
? { [_source.over_field_name]: _source.over_field_value } | ||
: {}), | ||
}, | ||
}; | ||
} | ||
return { | ||
type: 'Feature', | ||
geometry, | ||
properties: { | ||
actual: result.actual, | ||
actualDisplay: result.actualDisplay, | ||
typical: result.typical, | ||
typicalDisplay: result.typicalDisplay, | ||
fieldName: result.fieldName, | ||
functionDescription: result.functionDescription, | ||
timestamp: result.timestamp, | ||
record_score: result.record_score, | ||
}, | ||
}; | ||
}); | ||
}) || []; | ||
|
||
return { | ||
type: 'FeatureCollection', | ||
|
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: should this be ML_ANOMALY_LAYERS.TYPICAL_TO_ACTUAL?
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 1ae5ddc