Skip to content

Commit a00cfae

Browse files
kc0bfvrehanvdm
andauthored
feat: Static anomaly detection for pr (#89)
* Create minimumViews parameter for anomaly detect * Meet the prettier requirements * Update docs/ANOMALY_DETECTION.md Clarify verbiage on MINIMUM_VIEWS Co-authored-by: Rehan van der Merwe <[email protected]> * Update infra/src/index.ts Clarify comment on min num views Co-authored-by: Rehan van der Merwe <[email protected]> --------- Co-authored-by: Rehan van der Merwe <[email protected]>
1 parent 14b1b12 commit a00cfae

File tree

6 files changed

+17
-2
lines changed

6 files changed

+17
-2
lines changed

application/src/backend/cron-anomaly-detection/environment.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export class LambdaEnvironment {
1616
static EVALUATION_WINDOW: number;
1717
static BREACHING_MULTIPLIER: number;
1818
static EVENT_BRIDGE_SOURCE: string;
19+
static MINIMUM_VIEWS: number;
1920

2021
static init() {
2122
const schema = z.object({
@@ -32,6 +33,7 @@ export class LambdaEnvironment {
3233
EVALUATION_WINDOW: z.string().transform((v) => Number(v)),
3334
BREACHING_MULTIPLIER: z.string().transform((v) => Number(v)),
3435
EVENT_BRIDGE_SOURCE: z.string(),
36+
MINIMUM_VIEWS: z.string().transform((v) => Number(v)),
3537
});
3638
const parsed = schema.safeParse(process.env);
3739

application/src/backend/cron-anomaly-detection/stat_functions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ export function predict(data: CleanedData, seasonLength: number, predictedBreach
168168
const breachingThreshold = predicted * predictedBreachingMultiplier;
169169
/* Use the `data.latest.record` instead of `data.trainingDataViews[data.trainingDataViews.length-1]` because the
170170
* latter has clamped values */
171-
const breachingLatest = latestRecord.views > breachingThreshold;
171+
const breachingLatest =
172+
latestRecord.views > LambdaEnvironment.MINIMUM_VIEWS && latestRecord.views > breachingThreshold;
172173
logger.debug('Prediction', {
173174
Latest: latestRecord,
174175
Predicted: predicted,

docs/ANOMALY_DETECTION.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Two important environment variables are used to configure the detection:
2525
The actual value of 100 is less than the breaching threshold of 160, so the evaluation is not marked as breaching.
2626
If the actual value was say 200, then it would be more than the breaching threshold and the evaluation would be
2727
marked as breaching.
28+
- `MINIMUM_VIEWS` The minimum number of views before an evaluation is considered breached. Continuing with the example above, if the `Minimum Views` parameter is specified as 101, which is less than the actual view of 100, then the predicted value, breaching multiplier, and the breaching threshold are irrelevant as the evaluation will not be able to transition into the breaching state.
2829

2930
### Logic
3031

infra/src/backend.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ export function backend(
349349
EVALUATION_WINDOW: props.anomaly.detection.evaluationWindow!.toString(),
350350
BREACHING_MULTIPLIER: props.anomaly.detection.predictedBreachingMultiplier!.toString(),
351351
EVENT_BRIDGE_SOURCE: eventBridgeSource,
352+
MINIMUM_VIEWS: props.anomaly.detection.minimumViews!.toString(),
352353
},
353354
/* The lambda is NOT idempotent */
354355
retryAttempts: 0,

infra/src/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,12 @@ export interface AnomalyDetectionProps {
180180
* @default 2
181181
*/
182182
readonly predictedBreachingMultiplier?: number;
183+
184+
/**
185+
* The minimum number of views before an evaluation is considered breached.
186+
* @default 0
187+
*/
188+
readonly minimumViews?: number;
183189
}
184190

185191
export interface AnomalyAlertProps {
@@ -210,7 +216,8 @@ export interface AnomalyProps {
210216
* Optional, if specified overrides the default properties
211217
* @default ```{
212218
* evaluationWindow: 2,
213-
* predictedBreachingMultiplier: 2
219+
* predictedBreachingMultiplier: 2,
220+
* minimumViews: 0
214221
* }```
215222
*/
216223
readonly detection?: AnomalyDetectionProps;
@@ -346,6 +353,7 @@ export class Swa extends Construct {
346353
detection: {
347354
evaluationWindow: 2,
348355
predictedBreachingMultiplier: 2,
356+
minimumViews: 0,
349357
},
350358
alert: {
351359
onAlarm: true,

tests/test-config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export type TestConfig = {
3131
EVALUATION_WINDOW: string;
3232
BREACHING_MULTIPLIER: string;
3333
EVENT_BRIDGE_SOURCE: string;
34+
MINIMUM_VIEWS: string;
3435

3536
ALERT_TOPIC_ARN: string;
3637
ALERT_ON_ALARM: string;
@@ -83,6 +84,7 @@ export const TestConfig: TestConfig = {
8384
EVALUATION_WINDOW: '2',
8485
BREACHING_MULTIPLIER: '2',
8586
EVENT_BRIDGE_SOURCE: 'swa-demo-prod',
87+
MINIMUM_VIEWS: '0',
8688

8789
ALERT_TOPIC_ARN: 'arn:aws:sns:eu-west-1:123456789:your-topic-name',
8890
ALERT_ON_ALARM: 'true',

0 commit comments

Comments
 (0)