|
2 | 2 | import calendar
|
3 | 3 | import logging
|
4 | 4 | import time
|
| 5 | +import numbers |
5 | 6 | import pytz
|
6 | 7 |
|
7 | 8 | from six import text_type
|
@@ -775,6 +776,43 @@ def are_favorites(cls, user, objects):
|
775 | 776 | return [fav.object_id for fav in cls.query.filter(cls.object_id.in_([o.id for o in objects]), cls.object_type == object_type, cls.user_id == user)]
|
776 | 777 |
|
777 | 778 |
|
| 779 | +OPERATORS = { |
| 780 | + '>': lambda v, t: v > t, |
| 781 | + '>=': lambda v, t: v >= t, |
| 782 | + '<': lambda v, t: v < t, |
| 783 | + '<=': lambda v, t: v <= t, |
| 784 | + '==': lambda v, t: v == t, |
| 785 | + '!=': lambda v, t: v != t, |
| 786 | + |
| 787 | + # backward compatibility |
| 788 | + 'greater than': lambda v, t: v > t, |
| 789 | + 'less than': lambda v, t: v < t, |
| 790 | + 'equals': lambda v, t: v == t, |
| 791 | +} |
| 792 | + |
| 793 | + |
| 794 | +def next_state(op, value, threshold): |
| 795 | + if isinstance(value, numbers.Number) and not isinstance(value, bool): |
| 796 | + try: |
| 797 | + threshold = float(threshold) |
| 798 | + except ValueError: |
| 799 | + return Alert.UNKNOWN_STATE |
| 800 | + # If it's a boolean cast to string and lower case, because upper cased |
| 801 | + # boolean value is Python specific and most likely will be confusing to |
| 802 | + # users. |
| 803 | + elif isinstance(value, bool): |
| 804 | + value = str(value).lower() |
| 805 | + else: |
| 806 | + value = str(value) |
| 807 | + |
| 808 | + if op(value, threshold): |
| 809 | + new_state = Alert.TRIGGERED_STATE |
| 810 | + else: |
| 811 | + new_state = Alert.OK_STATE |
| 812 | + |
| 813 | + return new_state |
| 814 | + |
| 815 | + |
778 | 816 | @generic_repr('id', 'name', 'query_id', 'user_id', 'state', 'last_triggered_at', 'rearm')
|
779 | 817 | class Alert(TimestampMixin, BelongsToOrgMixin, db.Model):
|
780 | 818 | UNKNOWN_STATE = 'unknown'
|
@@ -819,28 +857,12 @@ def evaluate(self):
|
819 | 857 | data = self.query_rel.latest_query_data.data
|
820 | 858 |
|
821 | 859 | if data['rows'] and self.options['column'] in data['rows'][0]:
|
822 |
| - operators = { |
823 |
| - '>': lambda v, t: v > t, |
824 |
| - '>=': lambda v, t: v >= t, |
825 |
| - '<': lambda v, t: v < t, |
826 |
| - '<=': lambda v, t: v <= t, |
827 |
| - '==': lambda v, t: v == t, |
828 |
| - '!=': lambda v, t: v != t, |
829 |
| - |
830 |
| - # backward compatibility |
831 |
| - 'greater than': lambda v, t: v > t, |
832 |
| - 'less than': lambda v, t: v < t, |
833 |
| - 'equals': lambda v, t: v == t, |
834 |
| - } |
835 |
| - should_trigger = operators.get(self.options['op'], lambda v, t: False) |
| 860 | + op = OPERATORS.get(self.options['op'], lambda v, t: False) |
836 | 861 |
|
837 | 862 | value = data['rows'][0][self.options['column']]
|
838 | 863 | threshold = self.options['value']
|
839 | 864 |
|
840 |
| - if should_trigger(value, threshold): |
841 |
| - new_state = self.TRIGGERED_STATE |
842 |
| - else: |
843 |
| - new_state = self.OK_STATE |
| 865 | + new_state = next_state(op, value, threshold) |
844 | 866 | else:
|
845 | 867 | new_state = self.UNKNOWN_STATE
|
846 | 868 |
|
|
0 commit comments