-
Notifications
You must be signed in to change notification settings - Fork 1
/
flask_statsd.py
135 lines (103 loc) · 3.76 KB
/
flask_statsd.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env python
import time
from flask import request, current_app
import statsd
class Statsd(object):
'''Statsd Extension for Flask
This extension does a couple things
1. Creates status code and latency metrics for all app request handlers
2. Provides a client with flask-specific metric naming so you don't have
to do it inline.
- - - - - - - - - - - -
app = Flask('myapp')
statsd = Statsd(app, config={'STATSD_PREFIX': 'myprefix'})
@app.route('/')
def index():
statsd.incr('doing_stuff')
print 'DOING STUFF'
with statsd.timer('doing_more_stuff'):
print 'DOING MORE STUFF'
return 'OK'
- - - - - - - - - - - -
Metrics follow the naming scheme:
<prefix (optional)>.<app_name>.<metric_name>
The following code will produce the following metrics:
- COUNTER: stats.myprefix.myapp.doing_stuff
- COUNTER: stats.myprefix.myapp.request_handlers.index.<status_code>
- TIMER: stats.timers.myprefix.myapp.request_handlers.index.<status_code>
- TIMER: stats.timers.myprefix.myapp.doing_more_stuff
'''
START_TIME_ATTR = "statsd_start_time"
__client = None
def __init__(self, app=None):
if app is not None:
self.init_app(app)
def init_app(self, app):
app.config.setdefault('STATSD_ENABLE_REQUEST_HANDLERS', True)
app.config.setdefault('STATSD_HOST', 'localhost')
app.config.setdefault('STATSD_PORT', 8125)
app.config.setdefault('STATSD_PREFIX', None)
app.config.setdefault('STATSD_RATE', 1)
if app.config['STATSD_ENABLE_REQUEST_HANDLERS']:
app.before_request(self._before_request)
app.after_request(self._after_request)
###
# Main Interface (proxy commands to pystatsd)
###
def timer(self, stat, rate=None):
return self._client.timer(
rate=rate or current_app.config['STATSD_RATE'],
stat=self._metric_name(stat)
)
def timing(self, stat, delta, rate=None):
return self._client.timing(
rate=rate or current_app.config['STATSD_RATE'],
delta=delta,
stat=self._metric_name(stat)
)
def incr(self, stat, count=1, rate=None):
return self._client.incr(
rate=rate or current_app.config['STATSD_RATE'],
count=count,
stat=self._metric_name(stat)
)
def decr(self, stat, count=1, rate=None):
return self.incr(stat, -count, rate)
###
# HELPERS
###
def _metric_name(self, name):
return "%s.%s" % (current_app.name, name)
@property
def _client(self):
if not self.__client:
self.__client = statsd.StatsClient(
current_app.config['STATSD_HOST'],
current_app.config['STATSD_PORT'],
current_app.config['STATSD_PREFIX']
)
return self.__client
###
# REQUEST HANDLER FUNCTIONALITY
###
def _after_request(self, response):
if not hasattr(request, self.START_TIME_ATTR) or \
current_app.config['STATSD_RATE'] == 0 or \
not request.endpoint:
return response
metrics = [
".".join(["request_handlers", request.endpoint,
str(response.status_code)]),
".".join(["request_handlers", "overall",
str(response.status_code)])
]
for metric_name in metrics:
self.timing(
metric_name,
int((time.time() -
getattr(request, self.START_TIME_ATTR))*1000)
)
self.incr(metric_name)
return response
def _before_request(self):
setattr(request, self.START_TIME_ATTR, time.time())