##// END OF EJS Templates
system-info: unified data structures for usage in API....
marcink -
r1112:ff9a513b default
parent child Browse files
Show More
@@ -596,9 +596,9 b' class SettingsController(BaseController)'
596
596
597 # Systems stats
597 # Systems stats
598 (_('CPU'), val('cpu'), state('cpu')),
598 (_('CPU'), val('cpu'), state('cpu')),
599 (_('Load'), val('load'), state('load')),
599 (_('Load'), val('load')['text'], state('load')),
600 (_('Memory'), val('memory'), state('memory')),
600 (_('Memory'), val('memory')['text'], state('memory')),
601 (_('Uptime'), val('uptime')['uptime'], state('uptime')),
601 (_('Uptime'), val('uptime')['text'], state('uptime')),
602 ('', '', ''), # spacer
602 ('', '', ''), # spacer
603
603
604 # Repo storage
604 # Repo storage
@@ -612,8 +612,8 b' class SettingsController(BaseController)'
612 (_('Archive cache storage location'), val('storage_archive')['path'], state('storage_archive')),
612 (_('Archive cache storage location'), val('storage_archive')['path'], state('storage_archive')),
613 (_('Archive cache info'), val('storage_archive')['text'], state('storage_archive')),
613 (_('Archive cache info'), val('storage_archive')['text'], state('storage_archive')),
614
614
615 (_('Search storage'), val('storage_search')['path'], state('storage_search')),
615 (_('Search info'), val('search')['text'], state('search')),
616 (_('Search info'), val('storage_search')['text'], state('storage_search')),
616 (_('Search location'), val('search')['location'], state('search')),
617 ('', '', ''), # spacer
617 ('', '', ''), # spacer
618
618
619 # VCS specific
619 # VCS specific
@@ -4,6 +4,7 b' import time'
4 import platform
4 import platform
5 import pkg_resources
5 import pkg_resources
6 import logging
6 import logging
7 import string
7
8
8
9
9 log = logging.getLogger(__name__)
10 log = logging.getLogger(__name__)
@@ -93,10 +94,8 b' class SysInfo(object):'
93
94
94 # SysInfo functions
95 # SysInfo functions
95 def python_info():
96 def python_info():
96 value = {
97 value = dict(version=' '.join(platform._sys_version()),
97 'version': ' '.join(platform._sys_version()),
98 executable=sys.executable)
98 'executable': sys.executable
99 }
100 return SysInfoRes(value=value)
99 return SysInfoRes(value=value)
101
100
102
101
@@ -115,84 +114,95 b' def platform_type():'
115
114
116 def uptime():
115 def uptime():
117 from rhodecode.lib.helpers import age, time_to_datetime
116 from rhodecode.lib.helpers import age, time_to_datetime
118 from rhodecode.translation import _
119
117
120 _uptime = _uptime_human = {'boot_time': 0, 'uptime': 0}
118 value = dict(boot_time=0, uptime=0, text='')
121 state = STATE_OK_DEFAULT
119 state = STATE_OK_DEFAULT
122 if not psutil:
120 if not psutil:
123 return SysInfoRes(value=_uptime, state=state)
121 return SysInfoRes(value=value, state=state)
124
122
125 boot_time = psutil.boot_time()
123 boot_time = psutil.boot_time()
126 _uptime['boot_time'] = boot_time
124 value['boot_time'] = boot_time
127 _uptime['uptime'] = time.time() - boot_time
125 value['uptime'] = time.time() - boot_time
128
126
129 _uptime_human['boot_time'] = time_to_datetime(boot_time)
127 human_value = value.copy()
130 _uptime_human['uptime'] = _('Server started {}').format(
128 human_value['boot_time'] = time_to_datetime(boot_time)
129 human_value['uptime'] = age(time_to_datetime(boot_time), show_suffix=False)
130 human_value['text'] = 'Server started {}'.format(
131 age(time_to_datetime(boot_time)))
131 age(time_to_datetime(boot_time)))
132
132
133 return SysInfoRes(value=_uptime, human_value=_uptime_human)
133 return SysInfoRes(value=value, human_value=human_value)
134
134
135
135
136 def memory():
136 def memory():
137 from rhodecode.lib.helpers import format_byte_size_binary
137 from rhodecode.lib.helpers import format_byte_size_binary
138 _memory = {'available': 0, 'used': 0, 'cached': 0, 'percent': 0,
138 value = dict(available=0, used=0, cached=0, percent=0, percent_used=0,
139 'percent_used': 0, 'free': 0, 'inactive': 0, 'active': 0,
139 free=0, inactive=0, active=0, shared=0, total=0, buffers=0,
140 'shared': 0, 'total': 0, 'buffers': 0}
140 text='')
141
141 state = STATE_OK_DEFAULT
142 state = STATE_OK_DEFAULT
142 if not psutil:
143 if not psutil:
143 return SysInfoRes(value=_memory, state=state)
144 return SysInfoRes(value=value, state=state)
144
145
145 # memory
146 value.update(dict(psutil.virtual_memory()._asdict()))
146 _memory = dict(psutil.virtual_memory()._asdict())
147 value['percent_used'] = psutil._common.usage_percent(
147 _memory['percent_used'] = psutil._common.usage_percent(
148 (value['total'] - value['free']), value['total'], 1)
148 (_memory['total'] - _memory['free']), _memory['total'], 1)
149
149
150 try:
150 human_value = value.copy()
151 human_value = '%s/%s, %s%% used' % (
151 human_value['text'] = '%s/%s, %s%% used' % (
152 format_byte_size_binary(_memory['used']),
152 format_byte_size_binary(value['used']),
153 format_byte_size_binary(_memory['total']),
153 format_byte_size_binary(value['total']),
154 _memory['percent_used'],)
154 value['percent_used'],)
155 except TypeError:
156 human_value = 'NOT AVAILABLE'
157
155
158 if state['type'] == STATE_OK and _memory['percent_used'] > 90:
156 keys = value.keys()[::]
157 keys.pop(keys.index('percent'))
158 keys.pop(keys.index('percent_used'))
159 keys.pop(keys.index('text'))
160 for k in keys:
161 human_value[k] = format_byte_size_binary(value[k])
162
163 if state['type'] == STATE_OK and value['percent_used'] > 90:
159 msg = 'Critical: your available RAM memory is very low.'
164 msg = 'Critical: your available RAM memory is very low.'
160 state = {'message': msg, 'type': STATE_ERR}
165 state = {'message': msg, 'type': STATE_ERR}
161
166
162 elif state['type'] == STATE_OK and _memory['percent_used'] > 70:
167 elif state['type'] == STATE_OK and value['percent_used'] > 70:
163 msg = 'Warning: your available RAM memory is running low.'
168 msg = 'Warning: your available RAM memory is running low.'
164 state = {'message': msg, 'type': STATE_WARN}
169 state = {'message': msg, 'type': STATE_WARN}
165
170
166 return SysInfoRes(value=_memory, state=state, human_value=human_value)
171 return SysInfoRes(value=value, state=state, human_value=human_value)
167
172
168
173
169 def machine_load():
174 def machine_load():
170 _load = {'1_min': _NA, '5_min': _NA, '15_min': _NA}
175 value = {'1_min': _NA, '5_min': _NA, '15_min': _NA, 'text': ''}
171
172 state = STATE_OK_DEFAULT
176 state = STATE_OK_DEFAULT
173 if not psutil:
177 if not psutil:
174 return SysInfoRes(value=_load, state=state)
178 return SysInfoRes(value=value, state=state)
175
179
176 # load averages
180 # load averages
177 if hasattr(psutil.os, 'getloadavg'):
181 if hasattr(psutil.os, 'getloadavg'):
178 _load = dict(zip(['1_min', '5_min', '15_min'], psutil.os.getloadavg()))
182 value.update(dict(
183 zip(['1_min', '5_min', '15_min'], psutil.os.getloadavg())))
179
184
180 human_value = '1min: %s, 5min: %s, 15min: %s' % (
185 human_value = value.copy()
181 _load['1_min'], _load['5_min'], _load['15_min'])
186 human_value['text'] = '1min: {}, 5min: {}, 15min: {}'.format(
187 value['1_min'], value['5_min'], value['15_min'])
182
188
183 # TODO: warn about too-much load 15 min
189 if state['type'] == STATE_OK and value['15_min'] > 5:
184 return SysInfoRes(value=_load, state=state, human_value=human_value)
190 msg = 'Warning: your machine load is very high.'
191 state = {'message': msg, 'type': STATE_WARN}
192
193 return SysInfoRes(value=value, state=state, human_value=human_value)
185
194
186
195
187 def cpu():
196 def cpu():
197 value = 0
188 state = STATE_OK_DEFAULT
198 state = STATE_OK_DEFAULT
189 cpu_value = 0
199
190 if not psutil:
200 if not psutil:
191 return SysInfoRes(value=cpu_value, state=state)
201 return SysInfoRes(value=value, state=state)
192
202
193 cpu_value = psutil.cpu_percent(0.5)
203 value = psutil.cpu_percent(0.5)
194 human_value = '{} %'.format(cpu_value)
204 human_value = '{} %'.format(value)
195 return SysInfoRes(value=cpu_value, state=state, human_value=human_value)
205 return SysInfoRes(value=value, state=state, human_value=human_value)
196
206
197
207
198 def storage():
208 def storage():
@@ -200,69 +210,70 b' def storage():'
200 from rhodecode.model.settings import VcsSettingsModel
210 from rhodecode.model.settings import VcsSettingsModel
201 path = VcsSettingsModel().get_repos_location()
211 path = VcsSettingsModel().get_repos_location()
202
212
203 # disk storage
213 value = dict(percent=0, used=0, total=0, path=path, text='')
204 disk = {'percent': 0, 'used': 0, 'total': 0, 'path': path, 'text': ''}
205 state = STATE_OK_DEFAULT
214 state = STATE_OK_DEFAULT
206 if not psutil:
215 if not psutil:
207 return SysInfoRes(value=disk, state=state)
216 return SysInfoRes(value=value, state=state)
208
217
209 try:
218 try:
210 disk.update(dict(psutil.disk_usage(path)._asdict()))
219 value.update(dict(psutil.disk_usage(path)._asdict()))
211 except Exception as e:
220 except Exception as e:
212 log.exception('Failed to fetch disk info')
221 log.exception('Failed to fetch disk info')
213 state = {'message': str(e), 'type': STATE_ERR}
222 state = {'message': str(e), 'type': STATE_ERR}
214
223
215 human_value = disk
224 human_value = value.copy()
225 human_value['used'] = format_byte_size_binary(value['used'])
226 human_value['total'] = format_byte_size_binary(value['total'])
216 human_value['text'] = "{}/{}, {}% used".format(
227 human_value['text'] = "{}/{}, {}% used".format(
217 format_byte_size_binary(disk['used']),
228 format_byte_size_binary(value['used']),
218 format_byte_size_binary(disk['total']),
229 format_byte_size_binary(value['total']),
219 (disk['percent']))
230 value['percent'])
220
231
221 if state['type'] == STATE_OK and disk['percent'] > 90:
232 if state['type'] == STATE_OK and value['percent'] > 90:
222 msg = 'Critical: your disk space is very low.'
233 msg = 'Critical: your disk space is very low.'
223 state = {'message': msg, 'type': STATE_ERR}
234 state = {'message': msg, 'type': STATE_ERR}
224
235
225 elif state['type'] == STATE_OK and disk['percent'] > 70:
236 elif state['type'] == STATE_OK and value['percent'] > 70:
226 msg = 'Warning: your disk space is running low.'
237 msg = 'Warning: your disk space is running low.'
227 state = {'message': msg, 'type': STATE_WARN}
238 state = {'message': msg, 'type': STATE_WARN}
228
239
229 return SysInfoRes(value=disk, state=state, human_value=human_value)
240 return SysInfoRes(value=value, state=state, human_value=human_value)
230
241
231
242
232 def storage_inodes():
243 def storage_inodes():
233 from rhodecode.model.settings import VcsSettingsModel
244 from rhodecode.model.settings import VcsSettingsModel
234 path = VcsSettingsModel().get_repos_location()
245 path = VcsSettingsModel().get_repos_location()
235
246
236 _disk_inodes = dict(percent=0, free=0, used=0, total=0, path=path, text='')
247 value = dict(percent=0, free=0, used=0, total=0, path=path, text='')
237 state = STATE_OK_DEFAULT
248 state = STATE_OK_DEFAULT
238 if not psutil:
249 if not psutil:
239 return SysInfoRes(value=_disk_inodes, state=state)
250 return SysInfoRes(value=value, state=state)
240
251
241 try:
252 try:
242 i_stat = os.statvfs(path)
253 i_stat = os.statvfs(path)
243
254
244 _disk_inodes['used'] = i_stat.f_ffree
255 value['used'] = i_stat.f_ffree
245 _disk_inodes['free'] = i_stat.f_favail
256 value['free'] = i_stat.f_favail
246 _disk_inodes['total'] = i_stat.f_files
257 value['total'] = i_stat.f_files
247 _disk_inodes['percent'] = percentage(
258 value['percent'] = percentage(
248 _disk_inodes['used'], _disk_inodes['total'])
259 value['used'], value['total'])
249 except Exception as e:
260 except Exception as e:
250 log.exception('Failed to fetch disk inodes info')
261 log.exception('Failed to fetch disk inodes info')
251 state = {'message': str(e), 'type': STATE_ERR}
262 state = {'message': str(e), 'type': STATE_ERR}
252
263
253 human_value = _disk_inodes
264 human_value = value.copy()
254 human_value['text'] = "{}/{}, {}% used".format(
265 human_value['text'] = "{}/{}, {}% used".format(
255 _disk_inodes['used'], _disk_inodes['total'], _disk_inodes['percent'])
266 value['used'], value['total'], value['percent'])
256
267
257 if state['type'] == STATE_OK and _disk_inodes['percent'] > 90:
268 if state['type'] == STATE_OK and value['percent'] > 90:
258 msg = 'Critical: your disk free inodes are very low.'
269 msg = 'Critical: your disk free inodes are very low.'
259 state = {'message': msg, 'type': STATE_ERR}
270 state = {'message': msg, 'type': STATE_ERR}
260
271
261 elif state['type'] == STATE_OK and _disk_inodes['percent'] > 70:
272 elif state['type'] == STATE_OK and value['percent'] > 70:
262 msg = 'Warning: your disk free inodes are running low.'
273 msg = 'Warning: your disk free inodes are running low.'
263 state = {'message': msg, 'type': STATE_WARN}
274 state = {'message': msg, 'type': STATE_WARN}
264
275
265 return SysInfoRes(value=_disk_inodes, state=state)
276 return SysInfoRes(value=value, state=state)
266
277
267
278
268 def storage_archives():
279 def storage_archives():
@@ -274,21 +285,21 b' def storage_archives():'
274 'archive_cache_dir=/path/to/cache option in the .ini file'
285 'archive_cache_dir=/path/to/cache option in the .ini file'
275 path = safe_str(rhodecode.CONFIG.get('archive_cache_dir', msg))
286 path = safe_str(rhodecode.CONFIG.get('archive_cache_dir', msg))
276
287
277 disk_archive = dict(percent=0, used=0, total=0, items=0, path=path, text='')
288 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
278 state = STATE_OK_DEFAULT
289 state = STATE_OK_DEFAULT
279 try:
290 try:
280 items_count = 0
291 items_count = 0
281 used = 0
292 used = 0
282 for root, dirs, files in os.walk(path):
293 for root, dirs, files in os.walk(path):
283 if root == path:
294 if root == path:
284 items_count = len(dirs)
295 items_count = len(files)
285
296
286 for f in files:
297 for f in files:
287 try:
298 try:
288 used += os.path.getsize(os.path.join(root, f))
299 used += os.path.getsize(os.path.join(root, f))
289 except OSError:
300 except OSError:
290 pass
301 pass
291 disk_archive.update({
302 value.update({
292 'percent': 100,
303 'percent': 100,
293 'used': used,
304 'used': used,
294 'total': used,
305 'total': used,
@@ -299,11 +310,13 b' def storage_archives():'
299 log.exception('failed to fetch archive cache storage')
310 log.exception('failed to fetch archive cache storage')
300 state = {'message': str(e), 'type': STATE_ERR}
311 state = {'message': str(e), 'type': STATE_ERR}
301
312
302 human_value = disk_archive
313 human_value = value.copy()
303 human_value['text'] = "{} ({} items)".format(format_byte_size_binary(
314 human_value['used'] = format_byte_size_binary(value['used'])
304 disk_archive['used']), disk_archive['total'])
315 human_value['total'] = format_byte_size_binary(value['total'])
316 human_value['text'] = "{} ({} items)".format(
317 human_value['used'], value['items'])
305
318
306 return SysInfoRes(value=disk_archive, state=state, human_value=human_value)
319 return SysInfoRes(value=value, state=state, human_value=human_value)
307
320
308
321
309 def storage_gist():
322 def storage_gist():
@@ -315,7 +328,7 b' def storage_gist():'
315 VcsSettingsModel().get_repos_location(), GIST_STORE_LOC))
328 VcsSettingsModel().get_repos_location(), GIST_STORE_LOC))
316
329
317 # gist storage
330 # gist storage
318 _disk_gist = dict(percent=0, used=0, total=0, items=0, path=path, text='')
331 value = dict(percent=0, used=0, total=0, items=0, path=path, text='')
319 state = STATE_OK_DEFAULT
332 state = STATE_OK_DEFAULT
320
333
321 try:
334 try:
@@ -330,7 +343,7 b' def storage_gist():'
330 used += os.path.getsize(os.path.join(root, f))
343 used += os.path.getsize(os.path.join(root, f))
331 except OSError:
344 except OSError:
332 pass
345 pass
333 _disk_gist.update({
346 value.update({
334 'percent': 100,
347 'percent': 100,
335 'used': used,
348 'used': used,
336 'total': used,
349 'total': used,
@@ -340,37 +353,36 b' def storage_gist():'
340 log.exception('failed to fetch gist storage items')
353 log.exception('failed to fetch gist storage items')
341 state = {'message': str(e), 'type': STATE_ERR}
354 state = {'message': str(e), 'type': STATE_ERR}
342
355
343 human_value = _disk_gist
356 human_value = value.copy()
344 human_value['text'] = "{} ({} items)".format(format_byte_size_binary(
357 human_value['used'] = format_byte_size_binary(value['used'])
345 _disk_gist['used']), _disk_gist['items'])
358 human_value['total'] = format_byte_size_binary(value['total'])
346 return SysInfoRes(value=_disk_gist, state=state, human_value=human_value)
359 human_value['text'] = "{} ({} items)".format(
360 human_value['used'], value['items'])
361
362 return SysInfoRes(value=value, state=state, human_value=human_value)
347
363
348
364
349 def storage_search():
365 def search_info():
350 import rhodecode
366 import rhodecode
351 path = rhodecode.CONFIG.get('search.location', '')
367 from rhodecode.lib.index import searcher_from_config
352
368
353 # search index storage
369 backend = rhodecode.CONFIG.get('search.module', '')
354 _disk_index = dict(percent=0, used=0, total=0, path=path, text='')
370 location = rhodecode.CONFIG.get('search.location', '')
355 state = STATE_OK_DEFAULT
371
356 try:
372 try:
357 search_index_storage_path_exists = os.path.isdir(path)
373 searcher = searcher_from_config(rhodecode.CONFIG)
358 if search_index_storage_path_exists:
374 searcher = searcher.__class__.__name__
359 used = get_storage_size(path)
375 except Exception:
360 _disk_index.update({
376 searcher = None
361 'percent': 100,
362 'used': used,
363 'total': used,
364 })
365 except Exception as e:
366 log.exception('failed to fetch search index storage')
367 state = {'message': str(e), 'type': STATE_ERR}
368
377
369 human_value = _disk_index
378 value = dict(
370 human_value['text'] = "{}/{}, {}% used".format(
379 backend=backend, searcher=searcher, location=location, text='')
371 _disk_index['used'], _disk_index['total'], _disk_index['percent'])
380 state = STATE_OK_DEFAULT
372
381
373 return SysInfoRes(value=_disk_index, state=state, human_value=human_value)
382 human_value = value.copy()
383 human_value['text'] = "backend:`{}`".format(human_value['backend'])
384
385 return SysInfoRes(value=value, state=state, human_value=human_value)
374
386
375
387
376 def git_info():
388 def git_info():
@@ -412,7 +424,8 b' def svn_info():'
412
424
413 def vcs_backends():
425 def vcs_backends():
414 import rhodecode
426 import rhodecode
415 value = rhodecode.CONFIG.get('vcs.backends', '').split(',')
427 value = map(
428 string.strip, rhodecode.CONFIG.get('vcs.backends', '').split(','))
416 human_value = 'Enabled backends in order: {}'.format(','.join(value))
429 human_value = 'Enabled backends in order: {}'.format(','.join(value))
417 return SysInfoRes(value=value, human_value=human_value)
430 return SysInfoRes(value=value, human_value=human_value)
418
431
@@ -443,17 +456,21 b' def vcs_server():'
443 text='',
456 text='',
444 )
457 )
445
458
446 human_value = value
459 human_value = value.copy()
447 human_value['text'] = \
460 human_value['text'] = \
448 '{url}@ver:{ver} via {mode} mode, connection:{conn}'.format(
461 '{url}@ver:{ver} via {mode} mode, connection:{conn}'.format(
449 url=server_url, ver=version, mode=protocol, conn=connection)
462 url=server_url, ver=version, mode=protocol, conn=connection)
450
463
451 return SysInfoRes(value='', state=state, human_value=human_value)
464 return SysInfoRes(value=value, state=state, human_value=human_value)
452
465
453
466
454 def rhodecode_app_info():
467 def rhodecode_app_info():
455 import rhodecode
468 import rhodecode
456 return SysInfoRes(value={'rhodecode_version': rhodecode.__version__})
469 value = dict(
470 rhodecode_version=rhodecode.__version__,
471 rhodecode_lib_path=os.path.abspath(rhodecode.__file__)
472 )
473 return SysInfoRes(value=value)
457
474
458
475
459 def rhodecode_config():
476 def rhodecode_config():
@@ -529,7 +546,7 b' def database_info():'
529 url=repr(db_url_obj)
546 url=repr(db_url_obj)
530 )
547 )
531
548
532 human_value = db_info
549 human_value = db_info.copy()
533 human_value['url'] = "{} @ migration version: {}".format(
550 human_value['url'] = "{} @ migration version: {}".format(
534 db_info['url'], db_info['migrate_version'])
551 db_info['url'], db_info['migrate_version'])
535 human_value['version'] = "{} {}".format(db_info['type'], db_info['version'])
552 human_value['version'] = "{} {}".format(db_info['type'], db_info['version'])
@@ -565,9 +582,10 b' def get_system_info(environ):'
565 'storage': SysInfo(storage)(),
582 'storage': SysInfo(storage)(),
566 'storage_inodes': SysInfo(storage_inodes)(),
583 'storage_inodes': SysInfo(storage_inodes)(),
567 'storage_archive': SysInfo(storage_archives)(),
584 'storage_archive': SysInfo(storage_archives)(),
568 'storage_search': SysInfo(storage_search)(),
569 'storage_gist': SysInfo(storage_gist)(),
585 'storage_gist': SysInfo(storage_gist)(),
570
586
587 'search': SysInfo(search_info)(),
588
571 'uptime': SysInfo(uptime)(),
589 'uptime': SysInfo(uptime)(),
572 'load': SysInfo(machine_load)(),
590 'load': SysInfo(machine_load)(),
573 'cpu': SysInfo(cpu)(),
591 'cpu': SysInfo(cpu)(),
General Comments 0
You need to be logged in to leave comments. Login now