def test_spike_deep_key(): rules = {'threshold_ref': 10, 'spike_height': 2, 'timeframe': datetime.timedelta(seconds=10), 'spike_type': 'both', 'timestamp_field': '@timestamp', 'query_key': 'foo.bar.baz'} rule = SpikeRule(rules) rule.add_data([{'@timestamp': ts_to_dt('2015'), 'foo': {'bar': {'baz': 'LOL'}}}]) assert 'LOL' in rule.cur_windows
def test_spike_query_key(): events = hits(100, timestamp_field='ts', username='******') # Constant rate, doesn't match rules = {'threshold_ref': 10, 'spike_height': 2, 'timeframe': datetime.timedelta(seconds=10), 'spike_type': 'both', 'use_count_query': False, 'timestamp_field': 'ts', 'query_key': 'username'} rule = SpikeRule(rules) rule.add_data(events) assert len(rule.matches) == 0 # Double the rate of events, but with a different usename events_bob = hits(100, timestamp_field='ts', username='******') events2 = events[:50] for num in range(50, 99): events2.append(events_bob[num]) events2.append(events[num]) rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 0 # Double the rate of events, with the same username events2 = events[:50] for num in range(50, 99): events2.append(events_bob[num]) events2.append(events[num]) events2.append(events[num]) rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 1
def test_spike_query_key(): events = hits(100, timestamp_field="ts", username="******") # Constant rate, doesn't match rules = { "threshold_ref": 10, "spike_height": 2, "timeframe": datetime.timedelta(seconds=10), "spike_type": "both", "use_count_query": False, "timestamp_field": "ts", "query_key": "username", } rule = SpikeRule(rules) rule.add_data(events) assert len(rule.matches) == 0 # Double the rate of events, but with a different usename events_bob = hits(100, timestamp_field="ts", username="******") events2 = events[:50] for num in range(50, 99): events2.append(events_bob[num]) events2.append(events[num]) rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 0 # Double the rate of events, with the same username events2 = events[:50] for num in range(50, 99): events2.append(events_bob[num]) events2.append(events[num]) events2.append(events[num]) rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 1
def test_spike_deep_key(): rules = { "threshold_ref": 10, "spike_height": 2, "timeframe": datetime.timedelta(seconds=10), "spike_type": "both", "timestamp_field": "@timestamp", "query_key": "foo.bar.baz", } rule = SpikeRule(rules) rule.add_data([{"@timestamp": ts_to_dt("2015"), "foo": {"bar": {"baz": "LOL"}}}]) assert "LOL" in rule.cur_windows
def test_spike_terms(): rules = { 'threshold_ref': 5, 'spike_height': 2, 'timeframe': datetime.timedelta(minutes=10), 'spike_type': 'both', 'use_count_query': False, 'timestamp_field': 'ts', 'query_key': 'username', 'use_term_query': True } terms1 = { ts_to_dt('2014-01-01T00:01:00Z'): [{ 'key': 'userA', 'doc_count': 10 }, { 'key': 'userB', 'doc_count': 5 }] } terms2 = { ts_to_dt('2014-01-01T00:10:00Z'): [{ 'key': 'userA', 'doc_count': 22 }, { 'key': 'userB', 'doc_count': 5 }] } terms3 = { ts_to_dt('2014-01-01T00:25:00Z'): [{ 'key': 'userA', 'doc_count': 25 }, { 'key': 'userB', 'doc_count': 27 }] } terms4 = { ts_to_dt('2014-01-01T00:27:00Z'): [{ 'key': 'userA', 'doc_count': 10 }, { 'key': 'userB', 'doc_count': 12 }, { 'key': 'userC', 'doc_count': 100 }] } terms5 = { ts_to_dt('2014-01-01T00:30:00Z'): [{ 'key': 'userD', 'doc_count': 100 }, { 'key': 'userC', 'doc_count': 100 }] } rule = SpikeRule(rules) # Initial input rule.add_terms_data(terms1) assert len(rule.matches) == 0 # No spike for UserA because windows not filled rule.add_terms_data(terms2) assert len(rule.matches) == 0 # Spike for userB only rule.add_terms_data(terms3) assert len(rule.matches) == 1 assert rule.matches[0].get('username') == 'userB' # Test no alert for new user over threshold rules.pop('threshold_ref') rules['threshold_cur'] = 50 rule = SpikeRule(rules) rule.add_terms_data(terms1) rule.add_terms_data(terms2) rule.add_terms_data(terms3) rule.add_terms_data(terms4) assert len(rule.matches) == 0 # Test alert_on_new_data rules['alert_on_new_data'] = True rule = SpikeRule(rules) rule.add_terms_data(terms1) rule.add_terms_data(terms2) rule.add_terms_data(terms3) rule.add_terms_data(terms4) assert len(rule.matches) == 1 # Test that another alert doesn't fire immediately for userC but it does for userD rule.matches = [] rule.add_terms_data(terms5) assert len(rule.matches) == 1 assert rule.matches[0]['username'] == 'userD'
def test_spike_query_key(): events = hits(100, timestamp_field='ts', username='******') # Constant rate, doesn't match rules = { 'threshold_ref': 10, 'spike_height': 2, 'timeframe': datetime.timedelta(seconds=10), 'spike_type': 'both', 'use_count_query': False, 'timestamp_field': 'ts', 'query_key': 'username' } rule = SpikeRule(rules) rule.add_data(events) assert len(rule.matches) == 0 # Double the rate of events, but with a different usename events_bob = hits(100, timestamp_field='ts', username='******') events2 = events[:50] for num in range(50, 99): events2.append(events_bob[num]) events2.append(events[num]) rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 0 # Double the rate of events, with the same username events2 = events[:50] for num in range(50, 99): events2.append(events_bob[num]) events2.append(events[num]) events2.append(events[num]) rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 1
def test_spike(): # Events are 1 per second events = hits(100, timestamp_field='ts') # Constant rate, doesn't match rules = { 'threshold_ref': 10, 'spike_height': 2, 'timeframe': datetime.timedelta(seconds=10), 'spike_type': 'both', 'use_count_query': False, 'timestamp_field': 'ts' } rule = SpikeRule(rules) rule.add_data(events) assert len(rule.matches) == 0 # Double the rate of events after [50:] events2 = events[:50] for event in events[50:]: events2.append(event) events2.append( {'ts': event['ts'] + datetime.timedelta(milliseconds=1)}) rules['spike_type'] = 'up' rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 1 # Doesn't match rules['spike_height'] = 3 rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 0 # Downward spike events = events[:50] + events[75:] rules['spike_type'] = 'down' rule = SpikeRule(rules) rule.add_data(events) assert len(rule.matches) == 1 # Doesn't meet threshold_ref # When ref hits 11, cur is only 20 rules['spike_height'] = 2 rules['threshold_ref'] = 11 rules['spike_type'] = 'up' rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 0 # Doesn't meet threshold_cur # Maximum rate of events is 20 per 10 seconds rules['threshold_ref'] = 10 rules['threshold_cur'] = 30 rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 0 # Alert on new data # (At least 25 events occur before 30 seconds has elapsed) rules.pop('threshold_ref') rules['timeframe'] = datetime.timedelta(seconds=30) rules['threshold_cur'] = 25 rules['spike_height'] = 2 rules['alert_on_new_data'] = True rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 1
def test_spike_count(): rules = { 'threshold_ref': 10, 'spike_height': 2, 'timeframe': datetime.timedelta(seconds=10), 'spike_type': 'both', 'timestamp_field': '@timestamp' } rule = SpikeRule(rules) # Double rate of events at 20 seconds rule.add_count_data({ts_to_dt('2014-09-26T00:00:00'): 10}) assert len(rule.matches) == 0 rule.add_count_data({ts_to_dt('2014-09-26T00:00:10'): 10}) assert len(rule.matches) == 0 rule.add_count_data({ts_to_dt('2014-09-26T00:00:20'): 20}) assert len(rule.matches) == 1 # Downward spike rule = SpikeRule(rules) rule.add_count_data({ts_to_dt('2014-09-26T00:00:00'): 10}) assert len(rule.matches) == 0 rule.add_count_data({ts_to_dt('2014-09-26T00:00:10'): 10}) assert len(rule.matches) == 0 rule.add_count_data({ts_to_dt('2014-09-26T00:00:20'): 0}) assert len(rule.matches) == 1
def test_spike_terms(): rules = {'threshold_ref': 5, 'spike_height': 2, 'timeframe': datetime.timedelta(minutes=10), 'spike_type': 'both', 'use_count_query': False, 'timestamp_field': 'ts', 'query_key': 'username', 'use_term_query': True} terms1 = {ts_to_dt('2014-01-01T00:01:00Z'): [{'key': 'userA', 'doc_count': 10}, {'key': 'userB', 'doc_count': 5}]} terms2 = {ts_to_dt('2014-01-01T00:10:00Z'): [{'key': 'userA', 'doc_count': 22}, {'key': 'userB', 'doc_count': 5}]} terms3 = {ts_to_dt('2014-01-01T00:25:00Z'): [{'key': 'userA', 'doc_count': 25}, {'key': 'userB', 'doc_count': 27}]} terms4 = {ts_to_dt('2014-01-01T00:27:00Z'): [{'key': 'userA', 'doc_count': 10}, {'key': 'userB', 'doc_count': 12}, {'key': 'userC', 'doc_count': 100}]} terms5 = {ts_to_dt('2014-01-01T00:30:00Z'): [{'key': 'userD', 'doc_count': 100}, {'key': 'userC', 'doc_count': 100}]} rule = SpikeRule(rules) # Initial input rule.add_terms_data(terms1) assert len(rule.matches) == 0 # No spike for UserA because windows not filled rule.add_terms_data(terms2) assert len(rule.matches) == 0 # Spike for userB only rule.add_terms_data(terms3) assert len(rule.matches) == 1 assert rule.matches[0].get('username') == 'userB' # Test no alert for new user over threshold rules.pop('threshold_ref') rules['threshold_cur'] = 50 rule = SpikeRule(rules) rule.add_terms_data(terms1) rule.add_terms_data(terms2) rule.add_terms_data(terms3) rule.add_terms_data(terms4) assert len(rule.matches) == 0 # Test alert_on_new_data rules['alert_on_new_data'] = True rule = SpikeRule(rules) rule.add_terms_data(terms1) rule.add_terms_data(terms2) rule.add_terms_data(terms3) rule.add_terms_data(terms4) assert len(rule.matches) == 1 # Test that another alert doesn't fire immediately for userC but it does for userD rule.matches = [] rule.add_terms_data(terms5) assert len(rule.matches) == 1 assert rule.matches[0]['username'] == 'userD'
def test_spike(): # Events are 1 per second events = hits(100, timestamp_field='ts') # Constant rate, doesn't match rules = {'threshold_ref': 10, 'spike_height': 2, 'timeframe': datetime.timedelta(seconds=10), 'spike_type': 'both', 'use_count_query': False, 'timestamp_field': 'ts'} rule = SpikeRule(rules) rule.add_data(events) assert len(rule.matches) == 0 # Double the rate of events after [50:] events2 = events[:50] for event in events[50:]: events2.append(event) events2.append({'ts': event['ts'] + datetime.timedelta(milliseconds=1)}) rules['spike_type'] = 'up' rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 1 # Doesn't match rules['spike_height'] = 3 rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 0 # Downward spike events = events[:50] + events[75:] rules['spike_type'] = 'down' rule = SpikeRule(rules) rule.add_data(events) assert len(rule.matches) == 1 # Doesn't meet threshold_ref # When ref hits 11, cur is only 20 rules['spike_height'] = 2 rules['threshold_ref'] = 11 rules['spike_type'] = 'up' rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 0 # Doesn't meet threshold_cur # Maximum rate of events is 20 per 10 seconds rules['threshold_ref'] = 10 rules['threshold_cur'] = 30 rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 0 # Alert on new data # (At least 25 events occur before 30 seconds has elapsed) rules.pop('threshold_ref') rules['timeframe'] = datetime.timedelta(seconds=30) rules['threshold_cur'] = 25 rules['spike_height'] = 2 rules['alert_on_new_data'] = True rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 1
def test_spike_count(): rules = {'threshold_ref': 10, 'spike_height': 2, 'timeframe': datetime.timedelta(seconds=10), 'spike_type': 'both', 'timestamp_field': '@timestamp'} rule = SpikeRule(rules) # Double rate of events at 20 seconds rule.add_count_data({ts_to_dt('2014-09-26T00:00:00'): 10}) assert len(rule.matches) == 0 rule.add_count_data({ts_to_dt('2014-09-26T00:00:10'): 10}) assert len(rule.matches) == 0 rule.add_count_data({ts_to_dt('2014-09-26T00:00:20'): 20}) assert len(rule.matches) == 1 # Downward spike rule = SpikeRule(rules) rule.add_count_data({ts_to_dt('2014-09-26T00:00:00'): 10}) assert len(rule.matches) == 0 rule.add_count_data({ts_to_dt('2014-09-26T00:00:10'): 10}) assert len(rule.matches) == 0 rule.add_count_data({ts_to_dt('2014-09-26T00:00:20'): 0}) assert len(rule.matches) == 1
def test_spike_terms_query_key_alert_on_new_data(): rules = { 'spike_height': 1.5, 'timeframe': datetime.timedelta(minutes=10), 'spike_type': 'both', 'use_count_query': False, 'timestamp_field': 'ts', 'query_key': 'username', 'use_term_query': True, 'alert_on_new_data': True } terms1 = { ts_to_dt('2014-01-01T00:01:00Z'): [{ 'key': 'userA', 'doc_count': 10 }] } terms2 = { ts_to_dt('2014-01-01T00:06:00Z'): [{ 'key': 'userA', 'doc_count': 10 }] } terms3 = { ts_to_dt('2014-01-01T00:11:00Z'): [{ 'key': 'userA', 'doc_count': 10 }] } terms4 = { ts_to_dt('2014-01-01T00:21:00Z'): [{ 'key': 'userA', 'doc_count': 20 }] } terms5 = { ts_to_dt('2014-01-01T00:26:00Z'): [{ 'key': 'userA', 'doc_count': 20 }] } terms6 = { ts_to_dt('2014-01-01T00:31:00Z'): [{ 'key': 'userA', 'doc_count': 20 }] } terms7 = { ts_to_dt('2014-01-01T00:36:00Z'): [{ 'key': 'userA', 'doc_count': 20 }] } terms8 = { ts_to_dt('2014-01-01T00:41:00Z'): [{ 'key': 'userA', 'doc_count': 20 }] } rule = SpikeRule(rules) # Initial input rule.add_terms_data(terms1) assert len(rule.matches) == 0 # No spike for UserA because windows not filled rule.add_terms_data(terms2) assert len(rule.matches) == 0 rule.add_terms_data(terms3) assert len(rule.matches) == 0 rule.add_terms_data(terms4) assert len(rule.matches) == 0 # Spike rule.add_terms_data(terms5) assert len(rule.matches) == 1 rule.matches[:] = [] # There will be no more spikes since all terms have the same doc_count rule.add_terms_data(terms6) assert len(rule.matches) == 0 rule.add_terms_data(terms7) assert len(rule.matches) == 0 rule.add_terms_data(terms8) assert len(rule.matches) == 0
def test_spike_terms(): rules = { "threshold_ref": 5, "spike_height": 2, "timeframe": datetime.timedelta(minutes=10), "spike_type": "both", "use_count_query": False, "timestamp_field": "ts", "query_key": "username", "use_term_query": True, } terms1 = {ts_to_dt("2014-01-01T00:01:00Z"): [{"key": "userA", "doc_count": 10}, {"key": "userB", "doc_count": 5}]} terms2 = {ts_to_dt("2014-01-01T00:10:00Z"): [{"key": "userA", "doc_count": 22}, {"key": "userB", "doc_count": 5}]} terms3 = {ts_to_dt("2014-01-01T00:25:00Z"): [{"key": "userA", "doc_count": 25}, {"key": "userB", "doc_count": 27}]} terms4 = { ts_to_dt("2014-01-01T00:27:00Z"): [ {"key": "userA", "doc_count": 10}, {"key": "userB", "doc_count": 12}, {"key": "userC", "doc_count": 100}, ] } terms5 = { ts_to_dt("2014-01-01T00:30:00Z"): [{"key": "userD", "doc_count": 100}, {"key": "userC", "doc_count": 100}] } rule = SpikeRule(rules) # Initial input rule.add_terms_data(terms1) assert len(rule.matches) == 0 # No spike for UserA because windows not filled rule.add_terms_data(terms2) assert len(rule.matches) == 0 # Spike for userB only rule.add_terms_data(terms3) assert len(rule.matches) == 1 assert rule.matches[0].get("username") == "userB" # Test no alert for new user over threshold rules.pop("threshold_ref") rules["threshold_cur"] = 50 rule = SpikeRule(rules) rule.add_terms_data(terms1) rule.add_terms_data(terms2) rule.add_terms_data(terms3) rule.add_terms_data(terms4) assert len(rule.matches) == 0 # Test alert_on_new_data rules["alert_on_new_data"] = True rule = SpikeRule(rules) rule.add_terms_data(terms1) rule.add_terms_data(terms2) rule.add_terms_data(terms3) rule.add_terms_data(terms4) assert len(rule.matches) == 1 # Test that another alert doesn't fire immediately for userC but it does for userD rule.matches = [] rule.add_terms_data(terms5) assert len(rule.matches) == 1 assert rule.matches[0]["username"] == "userD"
def test_spike(): # Events are 1 per second events = hits(100, timestamp_field="ts") # Constant rate, doesn't match rules = { "threshold_ref": 10, "spike_height": 2, "timeframe": datetime.timedelta(seconds=10), "spike_type": "both", "use_count_query": False, "timestamp_field": "ts", } rule = SpikeRule(rules) rule.add_data(events) assert len(rule.matches) == 0 # Double the rate of events after [50:] events2 = events[:50] for event in events[50:]: events2.append(event) events2.append({"ts": event["ts"] + datetime.timedelta(milliseconds=1)}) rules["spike_type"] = "up" rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 1 # Doesn't match rules["spike_height"] = 3 rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 0 # Downward spike events = events[:50] + events[75:] rules["spike_type"] = "down" rule = SpikeRule(rules) rule.add_data(events) assert len(rule.matches) == 1 # Doesn't meet threshold_ref # When ref hits 11, cur is only 20 rules["spike_height"] = 2 rules["threshold_ref"] = 11 rules["spike_type"] = "up" rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 0 # Doesn't meet threshold_cur # Maximum rate of events is 20 per 10 seconds rules["threshold_ref"] = 10 rules["threshold_cur"] = 30 rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 0 # Alert on new data # (At least 25 events occur before 30 seconds has elapsed) rules.pop("threshold_ref") rules["timeframe"] = datetime.timedelta(seconds=30) rules["threshold_cur"] = 25 rules["spike_height"] = 2 rules["alert_on_new_data"] = True rule = SpikeRule(rules) rule.add_data(events2) assert len(rule.matches) == 1
def test_spike_count(): rules = { "threshold_ref": 10, "spike_height": 2, "timeframe": datetime.timedelta(seconds=10), "spike_type": "both", "timestamp_field": "@timestamp", } rule = SpikeRule(rules) # Double rate of events at 20 seconds rule.add_count_data({ts_to_dt("2014-09-26T00:00:00"): 10}) assert len(rule.matches) == 0 rule.add_count_data({ts_to_dt("2014-09-26T00:00:10"): 10}) assert len(rule.matches) == 0 rule.add_count_data({ts_to_dt("2014-09-26T00:00:20"): 20}) assert len(rule.matches) == 1 # Downward spike rule = SpikeRule(rules) rule.add_count_data({ts_to_dt("2014-09-26T00:00:00"): 10}) assert len(rule.matches) == 0 rule.add_count_data({ts_to_dt("2014-09-26T00:00:10"): 10}) assert len(rule.matches) == 0 rule.add_count_data({ts_to_dt("2014-09-26T00:00:20"): 0}) assert len(rule.matches) == 1
def test_spike_terms_query_key_alert_on_new_data(): rules = {'spike_height': 1.5, 'timeframe': datetime.timedelta(minutes=10), 'spike_type': 'both', 'use_count_query': False, 'timestamp_field': 'ts', 'query_key': 'username', 'use_term_query': True, 'alert_on_new_data': True} terms1 = {ts_to_dt('2014-01-01T00:01:00Z'): [{'key': 'userA', 'doc_count': 10}]} terms2 = {ts_to_dt('2014-01-01T00:06:00Z'): [{'key': 'userA', 'doc_count': 10}]} terms3 = {ts_to_dt('2014-01-01T00:11:00Z'): [{'key': 'userA', 'doc_count': 10}]} terms4 = {ts_to_dt('2014-01-01T00:21:00Z'): [{'key': 'userA', 'doc_count': 20}]} terms5 = {ts_to_dt('2014-01-01T00:26:00Z'): [{'key': 'userA', 'doc_count': 20}]} terms6 = {ts_to_dt('2014-01-01T00:31:00Z'): [{'key': 'userA', 'doc_count': 20}]} terms7 = {ts_to_dt('2014-01-01T00:36:00Z'): [{'key': 'userA', 'doc_count': 20}]} terms8 = {ts_to_dt('2014-01-01T00:41:00Z'): [{'key': 'userA', 'doc_count': 20}]} rule = SpikeRule(rules) # Initial input rule.add_terms_data(terms1) assert len(rule.matches) == 0 # No spike for UserA because windows not filled rule.add_terms_data(terms2) assert len(rule.matches) == 0 rule.add_terms_data(terms3) assert len(rule.matches) == 0 rule.add_terms_data(terms4) assert len(rule.matches) == 0 # Spike rule.add_terms_data(terms5) assert len(rule.matches) == 1 rule.matches[:] = [] # There will be no more spikes since all terms have the same doc_count rule.add_terms_data(terms6) assert len(rule.matches) == 0 rule.add_terms_data(terms7) assert len(rule.matches) == 0 rule.add_terms_data(terms8) assert len(rule.matches) == 0