forked from aws/opsworks-cookbooks
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnginx_status.py.erb
254 lines (207 loc) · 7.18 KB
/
nginx_status.py.erb
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# -*- coding: utf-8 -*-
import time
import threading
import re
import urllib2
import os
# based on https://github.com/csakatoku/ganglia-pymodule_nginx_status/
# Worker thread object
_WorkerThread = None
# Synchronization lock
_glock = threading.Lock()
# Refresh rate of the stub_status data
_refresh_rate = 20
# Global dictionary storing the counts of the last state
_conns = {
'nginx_active_connections': 0,
'nginx_server_accepts' : 0,
'nginx_server_handled' : 0,
'nginx_server_requests' : 0,
'nginx_reading' : 0,
'nginx_writing' : 0,
'nginx_waiting' : 0,
}
def nginx_stub_status(name):
global _WorkerThread
if _WorkerThread is None:
return 0
if not _WorkerThread.running and not _WorkerThread.shuttingdown:
_WorkerThread.start()
_glock.acquire()
ret = int(_conns[name])
_glock.release()
return ret
# Metric descriptions
_descriptors = [
{ 'name' : 'nginx_active_connections',
'call_back' : nginx_stub_status,
'time_max' : 20,
'value_type' : 'uint',
'units' : 'Connections',
'slope' : 'both',
'format' : '%u',
'description': 'Number of all open connections including connections to backends',
'groups' : 'nginx',
},
{ 'name' : 'nginx_server_accepts',
'call_back' : nginx_stub_status,
'time_max' : 20,
'value_type' : 'uint',
'units' : 'Connections',
'slope' : 'both',
'format' : '%u',
'description': 'Total number of connections nginx accepts',
'groups' : 'nginx',
},
{ 'name' : 'nginx_server_handled',
'call_back' : nginx_stub_status,
'time_max' : 20,
'value_type' : 'uint',
'units' : 'Connections',
'slope' : 'both',
'format' : '%u',
'description': 'Total number of connections nginx handled',
'groups' : 'nginx',
},
{ 'name' : 'nginx_server_requests',
'call_back' : nginx_stub_status,
'time_max' : 20,
'value_type' : 'uint',
'units' : 'Requests',
'slope' : 'both',
'format' : '%u',
'description': 'Total number of requests nginx handles',
'groups' : 'nginx',
},
{ 'name' : 'nginx_reading',
'call_back' : nginx_stub_status,
'time_max' : 20,
'value_type' : 'uint',
'units' : 'Requests',
'slope' : 'both',
'format' : '%u',
'description': 'reading',
'groups' : 'nginx',
},
{ 'name' : 'nginx_writing',
'call_back' : nginx_stub_status,
'time_max' : 20,
'value_type' : 'uint',
'units' : 'Requests',
'slope' : 'both',
'format' : '%u',
'description': 'writing',
'groups' : 'nginx',
},
{ 'name' : 'nginx_waiting',
'call_back' : nginx_stub_status,
'time_max' : 20,
'value_type' : 'uint',
'units' : 'Requests',
'slope' : 'both',
'format' : '%u',
'description': 'waiting',
'groups' : 'nginx',
},
]
class NginxThread(threading.Thread):
"""
This thread continually gathers the current state of the nginx
on the machine via nginx stub_state module.
"""
def __init__(self, url):
super(NginxThread, self).__init__()
self.running = False
self.shuttingdown = False
# the URL where stub_status is enabled
# self.url = url # doesn't work
self.url = "http://127.0.0.1/<%= node[:ganglia][:nginx][:status_url] %>"
def shutdown(self):
self.shuttingdown = True
self.join()
def run(self):
global _conns
#Set the state of the running thread
self.running = True
# continue running until a shutdown event is indicated
while not self.shuttingdown:
if self.shuttingdown:
break
try:
res = urllib2.urlopen(self.url)
except urllib2.HTTPError, e:
time.sleep(_refresh_rate)
continue
if res.code != 200:
# error from nginx
pass
tempconn = dict([(k, 0) for k in _conns.keys()])
# Active connections
first = res.readline() or ''
matcher = re.match(r'Active connections: (\d+)', first)
if matcher:
tempconn['nginx_active_connections'] = int(matcher.group(1))
# server accepts handled requests
# discard this line
res.readline()
# actual data of server accepts, handled, requests
second = res.readline() or ''
matcher = re.match(r' (\d+) (\d+) (\d+)', second)
if matcher:
accepts, handled, requests = matcher.groups()
tempconn['nginx_server_accepts'] = int(accepts)
tempconn['nginx_server_handled'] = int(handled)
tempconn['nginx_server_requests'] = int(requests)
# Reading: 0 Writing: 1 Waiting: 0
third = res.readline() or ''
matcher = re.match(r'Reading: (\d+) Writing: (\d+) Waiting: (\d+)', third)
if matcher:
reading, writing, waiting = matcher.groups()
tempconn['nginx_reading'] = int(reading)
tempconn['nginx_writing'] = int(writing)
tempconn['nginx_waiting'] = int(waiting)
# acquire a lock and copy the temporary state
# to the global state dictionary
_glock.acquire()
for key, value in tempconn.items():
_conns[key] = value
_glock.release()
# wait for the refresh_rate period before collecting the status again
if not self.shuttingdown:
time.sleep(_refresh_rate)
# Set the current state of the thread after a shutdown has been indicated.
self.running = False
def metric_init(params):
'''Initialize the tcp connection status module and create the
metric definition dictionary object for each metric.'''
global _refresh_rate, _WorkerThread
#Read the refresh from the gmond.conf parameters.
if 'refresh' in params:
try:
_refresh_rate = int(params['refresh'])
except (ValueError, TypeError):
_refresh_rate = 20
url = params.get('url')
#Start the worker thread
_WorkerThread = NginxThread(url)
#Return the metric descriptions to Gmond
return _descriptors
def metric_cleanup():
'''Clean up the metric module.'''
#Tell the worker thread to shutdown
_WorkerThread.shutdown()
#This code is for debugging and unit testing
if __name__ == '__main__':
try:
params = {'refresh': '20',
'url' : 'http://127.0.0.1/<%= node[:ganglia][:nginx][:status_url] %>',
}
metric_init(params)
while 1:
for d in _descriptors:
v = d['call_back'](d['name'])
print 'value for %s is %u' % (d['name'], v)
time.sleep(5)
except KeyboardInterrupt:
time.sleep(0.2)
os._exit(1)