Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 143 lines (119 sloc) 4.425 kB
c01624e @spladug Initial commit.
spladug authored
1 #!/usr/bin/python
2
3 import ConfigParser
d253f2e Add configurable logging setup to alerts.init().
Logan Hanks authored
4 import logging
5 import logging.handlers
6 import os
7 import sys
8 import time
31101e0 @spladug Add a script to send HAProxy utilization data to graphite.
spladug authored
9 import socket
c01624e @spladug Initial commit.
spladug authored
10
11 import wessex
6bc0b2d @alienth Add support for Zenoss events.
alienth authored
12 from zenoss import Zenoss
c01624e @spladug Initial commit.
spladug authored
13
6bc0b2d @alienth Add support for Zenoss events.
alienth authored
14 __all__ = ["harold", "config", "zenoss"]
c01624e @spladug Initial commit.
spladug authored
15
44be404 Defer alerts module initialization until after import.
Logan Hanks authored
16 harold = None
31101e0 @spladug Add a script to send HAProxy utilization data to graphite.
spladug authored
17 graphite = None
6bc0b2d @alienth Add support for Zenoss events.
alienth authored
18 zenoss = None
44be404 Defer alerts module initialization until after import.
Logan Hanks authored
19 config = None
c01624e @spladug Initial commit.
spladug authored
20
d253f2e Add configurable logging setup to alerts.init().
Logan Hanks authored
21 def init(config_path='production.ini'):
6bc0b2d @alienth Add support for Zenoss events.
alienth authored
22 global config, harold, zenoss
d253f2e Add configurable logging setup to alerts.init().
Logan Hanks authored
23 config = load_config(path=config_path)
24 if config.has_section('logging'):
25 configure_logging(config)
31101e0 @spladug Add a script to send HAProxy utilization data to graphite.
spladug authored
26 if config.has_section('graphite'):
27 configure_graphite(config)
6bc0b2d @alienth Add support for Zenoss events.
alienth authored
28 if config.has_section('zenoss'):
29 zenoss = get_zenoss(config)
d253f2e Add configurable logging setup to alerts.init().
Logan Hanks authored
30
33fc86f @spladug Use centralized wessex config for harold.
spladug authored
31 harold = wessex.connect_harold()
32
44be404 Defer alerts module initialization until after import.
Logan Hanks authored
33 def load_config(path='production.ini'):
34 config = ConfigParser.RawConfigParser()
35 config.read([path])
36 return config
37
6bc0b2d @alienth Add support for Zenoss events.
alienth authored
38 def get_zenoss(config):
39 host = config.get('zenoss', 'host')
40 port = config.getint('zenoss', 'port')
41 user = config.get('zenoss', 'user')
42 password = config.get('zenoss', 'password')
43 return Zenoss('http://%s:%s/' % (host, port), user, password)
44
d253f2e Add configurable logging setup to alerts.init().
Logan Hanks authored
45 class StreamLoggingFormatter(logging.Formatter):
46 def formatTime(self, record, datefmt=None):
47 timestamp = time.strftime(datefmt)
48 return timestamp % dict(ms=(1000 * record.created) % 1000)
49
50 def _get_logging_handler(config):
51 mode = config.get('logging', 'mode')
52 if mode == 'file':
53 return logging.FileHandler(config.get('logging', 'file'))
54 elif mode == 'stderr':
55 return logging.StreamHandler()
56 elif mode == 'syslog':
57 return logging.handlers.SysLogHandler(
58 config.get('logging', 'syslog_addr'))
59 else:
60 raise ValueError('unsupported logging mode: %r' % mode)
61
62 def _get_logging_formatter(config):
63 mode = config.get('logging', 'mode')
64 if mode == 'syslog':
65 app_name = os.path.basename(sys.argv[0])
66 return logging.Formatter(
67 '%s: [%%(levelname)s] %%(message)s' % app_name)
68 else:
69 return StreamLoggingFormatter(
70 '%(levelname).1s%(asctime)s: %(message)s',
71 '%m%d %H:%M:%S.%%(ms)03d')
72
73 def _get_logging_level(config):
74 if config.has_option('logging', 'level'):
75 return config.get('logging', 'level')
76 else:
77 return logging.INFO
78
79 def configure_logging(config):
80 ch = _get_logging_handler(config)
81 ch.setFormatter(_get_logging_formatter(config))
82 logger = logging.getLogger()
83 logger.setLevel(_get_logging_level(config))
84 logger.addHandler(ch)
85 return logger
31101e0 @spladug Add a script to send HAProxy utilization data to graphite.
spladug authored
86
87 def _parse_addr(addr):
88 host, port_str = addr.split(':', 1)
89 return host, int(port_str)
90
91 class Graphite(object):
128fffa @rram alerts: Queue up messages to graphite.
rram authored
92 """Send data to graphite in a fault-tolerant manner.
93
94 Provides a single public method - send_values() - which adds to and
95 flushes an internal queue of messages. Should delivery to graphite fail,
96 messages are queued until the next invocation of send_values(). Up to
97 MAX_QUEUE_SIZE messages are kept, after which the oldest are dropped. This
98 class is not thread-safe.
99
100 """
101 MAX_QUEUE_SIZE = 1000
102
31101e0 @spladug Add a script to send HAProxy utilization data to graphite.
spladug authored
103 def __init__(self, address):
104 self.address = address
128fffa @rram alerts: Queue up messages to graphite.
rram authored
105 self.send_queue = []
31101e0 @spladug Add a script to send HAProxy utilization data to graphite.
spladug authored
106
107 def _send_message(self, msg):
108 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
109 sock.connect(self.address)
110 sock.send(msg + '\n')
111 sock.close()
112
113 def send_values(self, items):
114 messages = []
115 timestamp = str(time.time())
116 for key, value in items.iteritems():
117 messages.append(" ".join((key, str(value), timestamp)))
128fffa @rram alerts: Queue up messages to graphite.
rram authored
118 self.send_queue.extend(messages)
119 if self.send_queue:
120 try:
121 self._send_message("\n".join(self.send_queue))
122 del self.send_queue[:]
123 except socket.error as e:
124 logging.warning(
125 "Error while flushing to graphite. Queue size: %d",
126 len(self.send_queue)
127 )
128 finally:
129 if len(self.send_queue) > Graphite.MAX_QUEUE_SIZE:
130 logging.warning(
131 "Discarding %d messages",
132 len(self.send_queue) - Graphite.MAX_QUEUE_SIZE
133 )
134 self.send_queue = self.send_queue[-Graphite.MAX_QUEUE_SIZE:]
135
31101e0 @spladug Add a script to send HAProxy utilization data to graphite.
spladug authored
136
137 def configure_graphite(config):
138 global graphite
139
140 address_text = config.get('graphite', 'graphite_addr')
141 address = _parse_addr(address_text)
142 graphite = Graphite(address)
Something went wrong with that request. Please try again.