Skip to content
This repository has been archived by the owner on Dec 18, 2019. It is now read-only.

Support for slack alert #100

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/analyzer/alerters.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@ def alert_hipchat(alert, metric):
hipster.method('rooms/message', method='POST', parameters={'room_id': room, 'from': 'Skyline', 'color': settings.HIPCHAT_OPTS['color'], 'message': 'Anomaly: <a href="%s">%s</a> : %s' % (link, metric[1], metric[0])})


def alert_slack(alert, metric):
import slack
import slack.chat
token = settings.SLACK_OPTS['auth_token']
username = settings.SLACK_OPTS['username']
channels = settings.SLACK_OPTS['channels']
icon_url = settings.SLACK_OPTS['icon_url']
slack.api_token = token

for channel in channels:
slack.chat.post_message(channel, "Anomalous metric: %s (value: %s)" % (metric[1], metric[0]), username=username, icon_url=icon_url)


def trigger_alert(alert, metric):

if '@' in alert[1]:
Expand Down
78 changes: 40 additions & 38 deletions src/horizon/listen.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,67 +10,69 @@

logger = logging.getLogger("HorizonLog")

##SafeUnpickler taken from Carbon: https://github.com/graphite-project/carbon/blob/master/lib/carbon/util.py
# SafeUnpickler taken from Carbon: https://github.com/graphite-project/carbon/blob/master/lib/carbon/util.py
import sys
try:
from cStringIO import StringIO
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from StringIO import StringIO

try:
import cPickle as pickle
USING_CPICKLE = True
import cPickle as pickle
USING_CPICKLE = True
except:
import pickle
USING_CPICKLE = False
import pickle
USING_CPICKLE = False

# This whole song & dance is due to pickle being insecure
# yet performance critical for carbon. We leave the insecure
# mode (which is faster) as an option (USE_INSECURE_UNPICKLER).
# The SafeUnpickler classes were largely derived from
# http://nadiana.com/python-pickle-insecure
if USING_CPICKLE:
class SafeUnpickler(object):
PICKLE_SAFE = {
'copy_reg' : set(['_reconstructor']),
'__builtin__' : set(['object']),
}
class SafeUnpickler(object):
PICKLE_SAFE = {
'copy_reg': set(['_reconstructor']),
'__builtin__': set(['object']),
}

@classmethod
def find_class(cls, module, name):
if not module in cls.PICKLE_SAFE:
raise pickle.UnpicklingError('Attempting to unpickle unsafe module %s' % module)
__import__(module)
mod = sys.modules[module]
if not name in cls.PICKLE_SAFE[module]:
raise pickle.UnpicklingError('Attempting to unpickle unsafe class %s' % name)
return getattr(mod, name)
if module not in cls.PICKLE_SAFE:
raise pickle.UnpicklingError('Attempting to unpickle unsafe module %s' % module)
__import__(module)
mod = sys.modules[module]
if name not in cls.PICKLE_SAFE[module]:
raise pickle.UnpicklingError('Attempting to unpickle unsafe class %s' % name)
return getattr(mod, name)

@classmethod
def loads(cls, pickle_string):
pickle_obj = pickle.Unpickler(StringIO(pickle_string))
pickle_obj.find_global = cls.find_class
return pickle_obj.load()
pickle_obj = pickle.Unpickler(StringIO(pickle_string))
pickle_obj.find_global = cls.find_class
return pickle_obj.load()

else:
class SafeUnpickler(pickle.Unpickler):
PICKLE_SAFE = {
'copy_reg' : set(['_reconstructor']),
'__builtin__' : set(['object']),
}
def find_class(self, module, name):
if not module in self.PICKLE_SAFE:
raise pickle.UnpicklingError('Attempting to unpickle unsafe module %s' % module)
__import__(module)
mod = sys.modules[module]
if not name in self.PICKLE_SAFE[module]:
raise pickle.UnpicklingError('Attempting to unpickle unsafe class %s' % name)
return getattr(mod, name)
class SafeUnpickler(pickle.Unpickler):
PICKLE_SAFE = {
'copy_reg': set(['_reconstructor']),
'__builtin__': set(['object']),
}

def find_class(self, module, name):
if module not in self.PICKLE_SAFE:
raise pickle.UnpicklingError('Attempting to unpickle unsafe module %s' % module)
__import__(module)
mod = sys.modules[module]
if name not in self.PICKLE_SAFE[module]:
raise pickle.UnpicklingError('Attempting to unpickle unsafe class %s' % name)
return getattr(mod, name)

@classmethod
def loads(cls, pickle_string):
return cls(StringIO(pickle_string)).load()
##//SafeUnpickler
return cls(StringIO(pickle_string)).load()
# //SafeUnpickler


class Listen(Process):
"""
Expand All @@ -90,7 +92,7 @@ def __init__(self, port, queue, parent_pid, type="pickle"):
self.current_pid = getpid()
self.type = type

##Use the safe unpickler that comes with carbon rather than standard python pickle/cpickle
# Use the safe unpickler that comes with carbon rather than standard python pickle/cpickle
self.unpickler = SafeUnpickler

def gen_unpickle(self, infile):
Expand Down
12 changes: 12 additions & 0 deletions src/settings.py.example
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ ENABLE_ALERTS = True
# )
ALERTS = (
("skyline", "smtp", 1800),
("skyline", "slack", 1800),
)

# Each alert module requires additional information.
Expand Down Expand Up @@ -158,6 +159,17 @@ PAGERDUTY_OPTS = {
"key": "your_pagerduty_service_api_key",
}

# Slack alerts require pyslack
SLACK_OPTS = {
"auth_token": "your_slack_auth_token",
# Name of bot
"username": "your_username",
# Channels to send message to. Can be a public channel, private group or IM channel.
# Can be an encoded ID, or a name
"channels": ["#custom_chat"],
# URL to an image to use as the icon for this message
"icon_url": "http://yoursite.com/icon.jpeg",
}

"""
Horizon settings
Expand Down