Skip to content

Commit

Permalink
Alarms options group partially described.
Browse files Browse the repository at this point in the history
  • Loading branch information
idlesign committed Jul 11, 2017
1 parent 5ea589f commit 5ec2227
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 0 deletions.
5 changes: 5 additions & 0 deletions docs/source/grp_alarms.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Alarms
======

.. automodule:: uwsgiconf.options.alarms
:members:
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ API
:maxdepth: 3

config
grp_alarms
grp_applications
grp_caching
grp_locks
Expand Down
65 changes: 65 additions & 0 deletions tests/options/test_alarms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from uwsgiconf import Section


def test_alarms_basics(assert_lines):

assert_lines([
'alarm-msg-size = 10000',
], Section().alarms.set_basic_params(msg_size=10000))

assert_lines([
'alarm-list = true',
], Section().alarms.print_alarms())


def test_alarms_registration(assert_lines):

alarms = Section().alarms
assert_lines([
'alarm = my cmd:some',
], alarms.register_alarm(alarms.cls_alarm_command('my', 'some')))

alarms = Section().alarms
assert_lines([
'alarm = mysig signal:17',
], alarms.register_alarm(alarms.cls_alarm_signal('mysig', 17)))

alarms = Section().alarms
assert_lines([
'alarm = tomule mule:2',
], alarms.register_alarm(alarms.cls_alarm_mule('tomule', 2)))

alarms = Section().alarms
assert_lines([
'plugin = alarm_curl',
'alarm = test2 curl:http://192.168.173.6:9191/argh;auth_pass=foobar;auth_user=topogigio',
], alarms.register_alarm(
alarms.cls_alarm_curl(
'test2', 'http://192.168.173.6:9191/argh',
auth_user='topogigio', auth_pass='foobar')))

alarms = Section().alarms
assert_lines([
'plugin = alarm_xmpp',
'alarm = jab xmpp:idle@some.com;12345;one@some.com,two@some.com',
], alarms.register_alarm(
alarms.cls_alarm_xmpp('jab', 'idle@some.com', '12345', ['one@some.com', 'two@some.com'])))


def test_alarms_on_log(assert_lines):

alarms = Section().alarms

alarm1 = alarms.cls_alarm_command('mycom', 'some')
alarm2 = alarms.cls_alarm_signal('mysig', 27)

assert_lines([
'alarm = mycom cmd:some',
'alarm = mysig signal:27',
'alarm-log = mycom,mysig some text',
], alarms.alarm_on_log([alarm1, alarm2], 'some text'))

assert_lines([
'not-alarm-log = mycom other',
], alarms.alarm_on_log(alarm1, 'other', skip=True))

1 change: 1 addition & 0 deletions uwsgiconf/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Section(SectionBase):
)
"""
alarms = Options(Alarms) # type: Alarms
applications = Options(Applications) # type: Applications
caching = Options(Caching) # type: Caching
locks = Options(Locks) # type: Locks
Expand Down
1 change: 1 addition & 0 deletions uwsgiconf/options/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .alarms import Alarms
from .applications import Applications
from .caching import Caching
from .locks import Locks
Expand Down
147 changes: 147 additions & 0 deletions uwsgiconf/options/alarms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
from operator import attrgetter

from ..base import OptionsGroup, ParametrizedValue
from ..utils import listify, filter_locals, make_key_val_string


class Alarm(ParametrizedValue):

def __init__(self, alias, *args, **kwargs):
self.alias = alias or ''
super(Alarm, self).__init__(*args)


class AlarmCommand(Alarm):
"""Run a shell command, passing the log line to its stdin."""

name = 'cmd'

def __init__(self, alias, command):
super(AlarmCommand, self).__init__(alias, command)


class AlarmSignal(Alarm):
"""Raise an uWSGI signal."""

name = 'signal'

def __init__(self, alias, sig_num):
super(AlarmSignal, self).__init__(alias, sig_num)


class AlarmMule(Alarm):
"""Send the log line to a mule waiting for messages."""

name = 'mule'

def __init__(self, alias, mule_id):
super(AlarmMule, self).__init__(alias, mule_id)


class AlarmCurl(Alarm):
"""Send the log line to a cURL-able URL."""

name = 'curl'
requires_plugin = 'alarm_curl'
args_joiner = ';'

def __init__(
self, alias, url, method=None, ssl=None, ssl_insecure=None,
auth_user=None, auth_pass=None,
timeout=None, conn_timeout=None,
mail_from=None, mail_to=None, subject=None):

opts = make_key_val_string(
filter_locals(locals(), drop=['alias', 'url']),
bool_keys=['ssl', 'ssl_insecure'],
items_separator=self.args_joiner,
)
super(AlarmCurl, self).__init__(alias, url, opts)


class AlarmXmpp(Alarm):
"""Send the log line via XMPP/jabber."""

name = 'xmpp'
requires_plugin = 'alarm_xmpp'
args_joiner = ';'

def __init__(self, alias, jid, password, recipients):
super(AlarmXmpp, self).__init__(alias, jid, password, ','.join(listify(recipients)))


class Alarms(OptionsGroup):
"""Alarms.
This subsystem allows the developer/sysadmin to "announce"
special conditions of an app via various channels.
* http://uwsgi-docs.readthedocs.io/en/latest/AlarmSubsystem.html
"""

cls_alarm_command = AlarmCommand
cls_alarm_signal = AlarmSignal
cls_alarm_mule = AlarmMule
cls_alarm_curl = AlarmCurl
cls_alarm_xmpp = AlarmXmpp

def __init__(self, *args, **kwargs):
self._alarms = []
super(Alarms, self).__init__(*args, **kwargs)

def set_basic_params(self, msg_size=None, cheap=None, anti_loop_timeout=None):
"""
:param int msg_size: Set the max size of an alarm message in bytes. Default: 8192.
:param bool cheap: Use main alarm thread rather than create dedicated
threads for curl-based alarms
:param int anti_loop_timeout: Tune the anti-loop alarm system. Default: 3 seconds.
"""
self._set('alarm-msg-size', msg_size)
self._set('alarm-cheap', cheap, cast=bool)
self._set('alarm-freq', anti_loop_timeout)

return self._section

def print_alarms(self):
"""Print out enabled alarms."""

self._set('alarm-list', True, cast=bool)

return self._section

def register_alarm(self, alarm):
"""Register (create) an alarm.
:param Alarm|list[Alarms] alarm: Alarm.
"""
for alarm in listify(alarm):
if alarm not in self._alarms:
self._set('alarm', alarm, multi=True)
self._alarms.append(alarm)

return self._section

def alarm_on_log(self, alarm, matcher, skip=False):
"""Raise (or skip) the specified alarm when a log line matches the specified regexp.
:param Alarm|list[Alarms] alarm: Alarm.
:param str|unicode matcher: Regular expression to match log line.
:param bool skip:
"""
self.register_alarm(alarm)

value = '%s %s' % (
','.join(map(attrgetter('alias'), listify(alarm))),
matcher)

self._set('not-alarm-log' if skip else 'alarm-log', value)

return self._section

0 comments on commit 5ec2227

Please sign in to comment.