Skip to content

Commit 6cf017a

Browse files
authored
Merge pull request #136 from simvue-io/wk9874/get_alerts
Add `get_alerts` and `get_run_id_from_name` methods to Client
2 parents 8c80f43 + e35db05 commit 6cf017a

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed

simvue/client.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,24 @@ def __init__(self):
3939
self._headers = {"Authorization": f"Bearer {self._token}"}
4040
self._version = get_server_version()
4141

42+
def get_run_id_from_name(self, name):
43+
"""
44+
Get run id for the specified run name
45+
"""
46+
params = {'filters': json.dumps([f"name == {name}"])}
47+
48+
response = requests.get(f"{self._url}/api/runs", headers=self._headers, params=params)
49+
50+
if response.status_code == 200:
51+
if 'data' in response.json():
52+
if len(response.json()['data']) == 0:
53+
raise RuntimeError("Could not collect ID - no run found with this name.")
54+
if len(response.json()['data']) > 1:
55+
raise RuntimeError("Could not collect ID - more than one run exists with this name.")
56+
else:
57+
return response.json()['data'][0]['id']
58+
raise RuntimeError(response.text)
59+
4260
def get_run(self, run, system=False, tags=False, metadata=False):
4361
"""
4462
Get a single run
@@ -468,3 +486,36 @@ def get_events(self, run, filter=None, start=0, num=0):
468486
return response.json()['data']
469487

470488
raise Exception(response.text)
489+
490+
def get_alerts(self, run, triggered_only = True, names_only = True):
491+
"""_summary_
492+
493+
Parameters
494+
----------
495+
run : str
496+
The ID of the run to find alerts for
497+
critical_only : bool, optional
498+
Whether to only return details about alerts which are currently critical, by default True
499+
names_only: bool, optional
500+
Whether to only return the names of the alerts (otherwise return the full details of the alerts), by default True
501+
"""
502+
response = requests.get(f"{self._url}/api/runs/{run}", headers=self._headers)
503+
504+
if response.status_code == 404:
505+
if 'detail' in response.json():
506+
if response.json()['detail'] == 'run does not exist':
507+
raise Exception('Run does not exist')
508+
509+
elif response.status_code == 200:
510+
if triggered_only:
511+
if names_only:
512+
return [alert['alert']['name'] for alert in response.json()['alerts'] if alert['status']['current'] == 'critical']
513+
else:
514+
return [alert for alert in response.json()['alerts'] if alert['status']['current'] == 'critical']
515+
else:
516+
if names_only:
517+
return [alert['alert']['name'] for alert in response.json()['alerts']]
518+
else:
519+
return response.json()['alerts']
520+
521+
raise Exception(response.text)

tests/functional/test_get_alerts.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import time
2+
import unittest
3+
import uuid
4+
from simvue import Run, Client
5+
from simvue.sender import sender
6+
7+
import common
8+
9+
class TestGetAlerts(unittest.TestCase):
10+
def test_get_alerts(self):
11+
"""
12+
Create a run & two alerts, make one alert be triggered
13+
If triggered_only is True, check that only the triggered alert is returned
14+
IF triggered_only is False, check both alerts are returned
15+
If names_only is False, check that full dictionary of information is returned
16+
"""
17+
run = Run()
18+
client = Client()
19+
folder = '/test-%s' % str(uuid.uuid4())
20+
name = common.RUNNAME3
21+
run.init(name, folder=folder)
22+
run.add_alert(
23+
name='value_below_1',
24+
source='metrics',
25+
frequency=1,
26+
rule='is below',
27+
threshold=1,
28+
metric='test_metric',
29+
window=2
30+
)
31+
run.add_alert(
32+
name='value_above_1',
33+
source='metrics',
34+
frequency=1,
35+
rule='is above',
36+
threshold=1,
37+
metric='test_metric',
38+
window=2
39+
)
40+
41+
run.log_metrics({'test_metric': 5})
42+
time.sleep(180)
43+
44+
run_id = client.get_run_id_from_name(name)
45+
46+
triggered_alerts_names = client.get_alerts(run_id)
47+
self.assertListEqual(triggered_alerts_names, ['value_above_1'])
48+
49+
triggered_alerts_full = client.get_alerts(run_id, names_only=False)
50+
self.assertIsInstance(triggered_alerts_full[0], dict)
51+
self.assertEqual(triggered_alerts_full[0]["alert"]["name"], "value_above_1")
52+
self.assertEqual(triggered_alerts_full[0]["status"]["current"], "critical")
53+
54+
all_alerts_names = client.get_alerts(run_id, triggered_only=False)
55+
self.assertListEqual(all_alerts_names, ['value_above_1', 'value_below_1'])
56+
57+
run.close()
58+
59+
if __name__ == '__main__':
60+
unittest.main()

0 commit comments

Comments
 (0)