Skip to content

Commit 854e3a6

Browse files
author
Aaron Caldwell
authored
[7.x] [Maps] Add 'crossed' & 'exited' events to tracking alert (#82463) (#83737)
1 parent 98a8ec0 commit 854e3a6

File tree

4 files changed

+85
-27
lines changed

4 files changed

+85
-27
lines changed

x-pack/plugins/stack_alerts/public/alert_types/geo_threshold/query_builder/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ export const GeoThresholdAlertTypeExpression: React.FunctionComponent<AlertTypeP
277277
}
278278
fullWidth
279279
onChange={(e) => setAlertParams('trackingEvent', e.target.value)}
280-
options={[conditionOptions[0]]} // TODO: Make all options avab. before merge
280+
options={conditionOptions}
281281
/>
282282
</div>
283283
</EuiFormRow>

x-pack/plugins/stack_alerts/public/alert_types/geo_threshold/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
export enum TrackingEvent {
88
entered = 'entered',
99
exited = 'exited',
10+
crossed = 'crossed',
1011
}
1112

1213
export interface GeoThresholdAlertParams {

x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/geo_threshold.ts

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,14 @@ export function getMovedEntities(
144144
[]
145145
)
146146
// Do not track entries to or exits from 'other'
147-
.filter((entityMovementDescriptor: EntityMovementDescriptor) =>
148-
trackingEvent === 'entered'
149-
? entityMovementDescriptor.currLocation.shapeId !== OTHER_CATEGORY
150-
: entityMovementDescriptor.prevLocation.shapeId !== OTHER_CATEGORY
151-
)
147+
.filter((entityMovementDescriptor: EntityMovementDescriptor) => {
148+
if (trackingEvent !== 'crossed') {
149+
return trackingEvent === 'entered'
150+
? entityMovementDescriptor.currLocation.shapeId !== OTHER_CATEGORY
151+
: entityMovementDescriptor.prevLocation.shapeId !== OTHER_CATEGORY;
152+
}
153+
return true;
154+
})
152155
);
153156
}
154157

@@ -253,27 +256,36 @@ export const getGeoThresholdExecutor = (log: Logger) =>
253256
movedEntities.forEach(({ entityName, currLocation, prevLocation }) => {
254257
const toBoundaryName = shapesIdsNamesMap[currLocation.shapeId] || currLocation.shapeId;
255258
const fromBoundaryName = shapesIdsNamesMap[prevLocation.shapeId] || prevLocation.shapeId;
256-
services
257-
.alertInstanceFactory(`${entityName}-${toBoundaryName || currLocation.shapeId}`)
258-
.scheduleActions(ActionGroupId, {
259-
entityId: entityName,
260-
timeOfDetection: new Date(currIntervalEndTime).getTime(),
261-
crossingLine: `LINESTRING (${prevLocation.location[0]} ${prevLocation.location[1]}, ${currLocation.location[0]} ${currLocation.location[1]})`,
259+
let alertInstance;
260+
if (params.trackingEvent === 'entered') {
261+
alertInstance = `${entityName}-${toBoundaryName || currLocation.shapeId}`;
262+
} else if (params.trackingEvent === 'exited') {
263+
alertInstance = `${entityName}-${fromBoundaryName || prevLocation.shapeId}`;
264+
} else {
265+
// == 'crossed'
266+
alertInstance = `${entityName}-${fromBoundaryName || prevLocation.shapeId}-${
267+
toBoundaryName || currLocation.shapeId
268+
}`;
269+
}
270+
services.alertInstanceFactory(alertInstance).scheduleActions(ActionGroupId, {
271+
entityId: entityName,
272+
timeOfDetection: new Date(currIntervalEndTime).getTime(),
273+
crossingLine: `LINESTRING (${prevLocation.location[0]} ${prevLocation.location[1]}, ${currLocation.location[0]} ${currLocation.location[1]})`,
262274

263-
toEntityLocation: `POINT (${currLocation.location[0]} ${currLocation.location[1]})`,
264-
toEntityDateTime: currLocation.date,
265-
toEntityDocumentId: currLocation.docId,
275+
toEntityLocation: `POINT (${currLocation.location[0]} ${currLocation.location[1]})`,
276+
toEntityDateTime: currLocation.date,
277+
toEntityDocumentId: currLocation.docId,
266278

267-
toBoundaryId: currLocation.shapeId,
268-
toBoundaryName,
279+
toBoundaryId: currLocation.shapeId,
280+
toBoundaryName,
269281

270-
fromEntityLocation: `POINT (${prevLocation.location[0]} ${prevLocation.location[1]})`,
271-
fromEntityDateTime: prevLocation.date,
272-
fromEntityDocumentId: prevLocation.docId,
282+
fromEntityLocation: `POINT (${prevLocation.location[0]} ${prevLocation.location[1]})`,
283+
fromEntityDateTime: prevLocation.date,
284+
fromEntityDocumentId: prevLocation.docId,
273285

274-
fromBoundaryId: prevLocation.shapeId,
275-
fromBoundaryName,
276-
});
286+
fromBoundaryId: prevLocation.shapeId,
287+
fromBoundaryName,
288+
});
277289
});
278290

279291
// Combine previous results w/ current results for state of next run

x-pack/plugins/stack_alerts/server/alert_types/geo_threshold/tests/geo_threshold.test.ts

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ describe('geo_threshold', () => {
9999
});
100100

101101
describe('getMovedEntities', () => {
102-
const trackingEvent = 'entered';
103102
it('should return empty array if only movements were within same shapes', async () => {
104103
const currLocationArr = [
105104
{
@@ -133,7 +132,7 @@ describe('geo_threshold', () => {
133132
shapeLocationId: 'sameShape2',
134133
},
135134
];
136-
const movedEntities = getMovedEntities(currLocationArr, prevLocationArr, trackingEvent);
135+
const movedEntities = getMovedEntities(currLocationArr, prevLocationArr, 'entered');
137136
expect(movedEntities).toEqual([]);
138137
});
139138

@@ -170,7 +169,7 @@ describe('geo_threshold', () => {
170169
shapeLocationId: 'thisOneDidntMove',
171170
},
172171
];
173-
const movedEntities = getMovedEntities(currLocationArr, prevLocationArr, trackingEvent);
172+
const movedEntities = getMovedEntities(currLocationArr, prevLocationArr, 'entered');
174173
expect(movedEntities.length).toEqual(1);
175174
});
176175

@@ -193,7 +192,7 @@ describe('geo_threshold', () => {
193192
shapeLocationId: 'oldShapeLocation',
194193
},
195194
];
196-
const movedEntities = getMovedEntities(currLocationArr, prevLocationArr, trackingEvent);
195+
const movedEntities = getMovedEntities(currLocationArr, prevLocationArr, 'entered');
197196
expect(movedEntities).toEqual([]);
198197
});
199198

@@ -219,5 +218,51 @@ describe('geo_threshold', () => {
219218
const movedEntities = getMovedEntities(currLocationArr, prevLocationArr, 'exited');
220219
expect(movedEntities).toEqual([]);
221220
});
221+
222+
it('should not ignore "crossed" results from "other"', async () => {
223+
const currLocationArr = [
224+
{
225+
dateInShape: '2020-09-28T18:01:41.190Z',
226+
docId: 'N-ng1XQB6yyY-xQxnGSM',
227+
entityName: '936',
228+
location: [-82.8814151789993, 41.62806099653244],
229+
shapeLocationId: 'newShapeLocation',
230+
},
231+
];
232+
const prevLocationArr = [
233+
{
234+
dateInShape: '2020-08-28T18:01:41.190Z',
235+
docId: 'N-ng1XQB6yyY-xQxnGSM',
236+
entityName: '936',
237+
location: [-82.8814151789993, 40.62806099653244],
238+
shapeLocationId: OTHER_CATEGORY,
239+
},
240+
];
241+
const movedEntities = getMovedEntities(currLocationArr, prevLocationArr, 'crossed');
242+
expect(movedEntities.length).toEqual(1);
243+
});
244+
245+
it('should not ignore "crossed" results to "other"', async () => {
246+
const currLocationArr = [
247+
{
248+
dateInShape: '2020-08-28T18:01:41.190Z',
249+
docId: 'N-ng1XQB6yyY-xQxnGSM',
250+
entityName: '936',
251+
location: [-82.8814151789993, 40.62806099653244],
252+
shapeLocationId: OTHER_CATEGORY,
253+
},
254+
];
255+
const prevLocationArr = [
256+
{
257+
dateInShape: '2020-09-28T18:01:41.190Z',
258+
docId: 'N-ng1XQB6yyY-xQxnGSM',
259+
entityName: '936',
260+
location: [-82.8814151789993, 41.62806099653244],
261+
shapeLocationId: 'newShapeLocation',
262+
},
263+
];
264+
const movedEntities = getMovedEntities(currLocationArr, prevLocationArr, 'crossed');
265+
expect(movedEntities.length).toEqual(1);
266+
});
222267
});
223268
});

0 commit comments

Comments
 (0)