Full example on a generic elastic Watcher alert
{ | |
"trigger": { | |
"schedule": { | |
"interval": "5m" | |
} | |
}, | |
"input": { | |
"chain": { | |
"inputs": [ | |
{ | |
"first": { | |
"search": { | |
"request": { | |
"search_type": "query_then_fetch", | |
"indices": [ | |
".ml-accesslogs*" | |
], | |
"types": [], | |
"body": { | |
"query": { | |
"bool": { | |
"filter": [ | |
{ | |
"range": { | |
"timestamp": { | |
"gt": "now-10m", | |
"lt": "now-5m" | |
} | |
} | |
}, | |
{ | |
"term": { | |
"result_type": "bucket" | |
} | |
}, | |
{ | |
"range": { | |
"anomaly_score": { | |
"gte": "{{ctx.metadata.min_anomaly_score}}" | |
} | |
} | |
} | |
] | |
} | |
} | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"second": { | |
"search": { | |
"request": { | |
"search_type": "query_then_fetch", | |
"indices": [ | |
".ml-*" | |
], | |
"types": [], | |
"body": { | |
"query": { | |
"bool": { | |
"filter": [ | |
{ | |
"term": { | |
"timestamp": "{{ctx.payload.first.hits.hits.0._source.timestamp}}" | |
} | |
}, | |
{ | |
"term": { | |
"result_type": "record" | |
} | |
} | |
] | |
} | |
}, | |
"collapse": { | |
"field": "partition_field_value" | |
}, | |
"sort": [ | |
{ | |
"record_score": { | |
"order": "desc" | |
} | |
} | |
] | |
} | |
} | |
} | |
} | |
} | |
] | |
} | |
}, | |
"condition": { | |
"compare": { | |
"ctx.payload.first.hits.total": { | |
"gt": 0 | |
} | |
} | |
}, | |
"actions": { | |
"log": { | |
"transform": { | |
"script": { | |
"source": "def df = new DecimalFormat('##.##'); return ['start_time' : Instant.ofEpochMilli(ctx.payload.first.hits.hits.0._source.timestamp).atZone(ZoneId.systemDefault()).minus(Duration.ofMinutes(20)).format(DateTimeFormatter.ISO_INSTANT), 'end_time' : Instant.ofEpochMilli(ctx.payload.first.hits.hits.0._source.timestamp).atZone(ZoneId.systemDefault()).plus(Duration.ofMinutes(20)).format(DateTimeFormatter.ISO_INSTANT), 'job_id': ctx.payload.first.hits.hits.0._source.job_id, 'anomaly_score': ctx.payload.first.hits.hits.0._source.anomaly_score, 'bucket_time': Instant.ofEpochMilli(ctx.payload.first.hits.hits.0._source.timestamp).atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ISO_INSTANT), 'anomaly_details':ctx.payload.second.hits.hits.stream().map(p -> ['metric':p._source.partition_field_value,'score':df.format(p._source.record_score),'actual':df.format(p._source.actual.0),'typical':df.format(p._source.typical.0)]).collect(Collectors.toList())]", | |
"lang": "painless" | |
} | |
}, | |
"slack": { | |
"message": { | |
"to": [ | |
"#my-channel" | |
], | |
"text": "Job: {{ctx.payload.job_id}}\nAnomaly of score={{ctx.payload.anomaly_score}} at {{ctx.payload.bucket_time}} influenced by:\n {{#ctx.payload.anomaly_details}}influencer={{metric}}: score={{score}}, actual={{actual}} (typical={{typical}})\n{{/ctx.payload.anomaly_details}}\n\n :kibana: http://10.1.10.129:5601/app/ml#/explorer?_g=(ml:(jobIds:!({{ctx.payload.job_id}})),refreshInterval:(pause:!f,value:30000),time:(from:'{{ctx.payload.start_time}}',mode:quick,to:'{{ctx.payload.end_time}}'))&_a=(filters:!(),mlCheckboxShowCharts:(showCharts:!t),mlExplorerSwimlane:(viewBy:domain.keyword),mlSelectInterval:(interval:(display:Auto,val:auto)),mlSelectLimit:(limit:(display:'10',val:10)),mlSelectSeverity:(threshold:(display:major,val:50)))" | |
} | |
} | |
} | |
}, | |
"metadata": { | |
"min_anomaly_score": 75 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment