Projet

Général

Profil

0001-qommon-added-basic-statsd-infrastructure.patch

Frédéric Péters, 08 novembre 2012 15:57

Télécharger (7,04 ko)

Voir les différences:

Subject: [PATCH] qommon: added basic statsd infrastructure

 wcs/qommon/ident/password.ptl |    6 ++-
 wcs/qommon/publisher.py       |   13 +++++
 wcs/qommon/vendor/pystatsd.py |  113 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 131 insertions(+), 1 deletion(-)
 create mode 100644 wcs/qommon/vendor/pystatsd.py
wcs/qommon/ident/password.ptl
206 206
        username = form.get_widget('username').parse()
207 207
        password = form.get_widget('password').parse()
208 208

  
209
        get_publisher().statsd.increment('login-submit')
210

  
209 211
        try:
210 212
            user = PasswordAccount.get_with_credentials(username, password)
211 213
        except:
212 214
            form.set_error('username', _('Invalid credentials'))
215
            get_publisher().statsd.increment('login-error')
213 216
            return
214 217

  
215
        account = PasswordAccount.get(username)
218
        get_publisher().statsd.increment('login-success')
216 219

  
220
        account = PasswordAccount.get(username)
217 221
        return self.login_submit_account_user(account, user, form)
218 222

  
219 223
    def login_submit_account_user(self, account, user, form=None):
wcs/qommon/publisher.py
240 240
            # this could happen on file descriptor exhaustion
241 241
            pass
242 242

  
243
    def finish_successful_request(self):
244
        Publisher.finish_successful_request(self)
245
        self.statsd.increment('successful-request')
246

  
243 247
    def finish_failed_request(self):
244 248
        # duplicate at lot from parent class, just to use our own HTTPResponse
245 249
        request = get_request()
246 250
        original_response = request.response
247 251
        request.response = HTTPResponse()
248 252

  
253
        self.statsd.increment('failed-request')
254

  
249 255
        (exc_type, exc_value, tb) = sys.exc_info()
250 256

  
251 257
        if exc_type is NotImplementedError:
......
452 458
        except ImmediateRedirectException, e:
453 459
            return redirect(e.location)
454 460

  
461
        from vendor import pystatsd
462
        self.statsd = pystatsd.Client(
463
                        host=request.get_environ('QOMMON_STATSD_HOSTNAME', 'localhost'),
464
                        prefix='%s.%s' % (
465
                                self.APP_NAME,
466
                                os.path.split(self.app_dir)[-1].replace('+', '-').replace('.', '-')))
467

  
455 468
        self.initialize_app_dir()
456 469

  
457 470
        canonical_hostname = request.get_server(False).lower().split(':')[0].rstrip('.')
wcs/qommon/vendor/pystatsd.py
1
# w.c.s. - web application for online forms
2
# Copyright (C) 2005-2012  Entr'ouvert
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16
#
17
#
18
# statsd.py - Python implementation of the statsd client
19
#
20
# Initially released (as License :: OSI Approved :: BSD License, from setup.py)
21
# by Steve Ivy <steveivy@gmail.com> - <https://github.com/sivy/py-statsd>
22

  
23
import random
24
import socket
25
import time
26

  
27

  
28
# Sends statistics to the stats daemon over UDP
29
class Client(object):
30

  
31
    def __init__(self, host='localhost', port=8125, prefix=None):
32
        """
33
        Create a new Statsd client.
34
        * host: the host where statsd is listening, defaults to localhost
35
        * port: the port where statsd is listening, defaults to 8125
36

  
37
        >>> from pystatsd import statsd
38
        >>> stats_client = statsd.Statsd(host, port)
39
        """
40
        self.addr = (socket.gethostbyname(host), port)
41
        self.prefix = prefix
42
        self.udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
43

  
44
    def timing_since(self, stat, start, sample_rate=1):
45
        """
46
        Log timing information as the number of microseconds since the provided time float
47
        >>> start = time.time()
48
        >>> # do stuff
49
        >>> statsd_client.timing_since('some.time', start)
50
        """
51
        self.timing(stat, int((time.time() - start) * 1000000), sample_rate)
52

  
53
    def timing(self, stat, time, sample_rate=1):
54
        """
55
        Log timing information for a single stat
56
        >>> statsd_client.timing('some.time',500)
57
        """
58
        stats = {stat: "%f|ms" % time}
59
        self.send(stats, sample_rate)
60

  
61
    def gauge(self, stat, value, sample_rate=1):
62
        """
63
        Log gauge information for a single stat
64
        >>> statsd_client.gauge('some.gauge',42)
65
        """
66
        stats = {stat: "%f|g" % value}
67
        self.send(stats, sample_rate)
68

  
69
    def increment(self, stats, sample_rate=1):
70
        """
71
        Increments one or more stats counters
72
        >>> statsd_client.increment('some.int')
73
        >>> statsd_client.increment('some.int',0.5)
74
        """
75
        self.update_stats(stats, 1, sample_rate=sample_rate)
76

  
77
    def decrement(self, stats, sample_rate=1):
78
        """
79
        Decrements one or more stats counters
80
        >>> statsd_client.decrement('some.int')
81
        """
82
        self.update_stats(stats, -1, sample_rate=sample_rate)
83

  
84
    def update_stats(self, stats, delta, sample_rate=1):
85
        """
86
        Updates one or more stats counters by arbitrary amounts
87
        >>> statsd_client.update_stats('some.int',10)
88
        """
89
        if not isinstance(stats, list):
90
            stats = [stats]
91

  
92
        data = dict((stat, "%s|c" % delta) for stat in stats)
93
        self.send(data, sample_rate)
94

  
95
    def send(self, data, sample_rate=1):
96
        """
97
        Squirt the metrics over UDP
98
        """
99

  
100
        if self.prefix:
101
            data = dict((".".join((self.prefix, stat)), value) for stat, value in data.iteritems())
102

  
103
        if sample_rate < 1:
104
            if random.random() > sample_rate:
105
                return
106
            sampled_data = dict((stat, "%s|@%s" % (value, sample_rate)) for stat, value in data.iteritems())
107
        else:
108
            sampled_data = data
109

  
110
        try:
111
            [self.udp_sock.sendto("%s:%s" % (stat, value), self.addr) for stat, value in sampled_data.iteritems()]
112
        except:
113
            pass
0
-