PageRenderTime 49ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/conpaas-services/contrib/ganglia_modules/php_fpm_mon.py

https://gitlab.com/Chevalier/conpaas
Python | 180 lines | 121 code | 40 blank | 19 comment | 15 complexity | b8b14798f9959264ebecec6c6966936a MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, GPL-3.0
  1. # Ganglia module for parsing the PHP-FPM access log.
  2. # Computes average request rate and response time.
  3. # Uses the logtail tool to access the log.
  4. import subprocess, threading;
  5. import time, os;
  6. import logging;
  7. php_fpm_log = '/var/cache/cpsagent/fpm-access.log'
  8. dbg_log = '/tmp/php_mon_dbg.log'
  9. logtail_interval = 15
  10. descriptors = []
  11. logger = logging.getLogger('Ganglia PHP')
  12. # These global variables hold the computed monitoring results
  13. php_response_time = 0
  14. php_request_rate = 0
  15. # Can be used to stop the parsing thread
  16. stop_parsing = False
  17. # A separate thread that checks what has been added to the log,
  18. # at regular time intervals. It computes the response time
  19. # and request rate for the last time interval and stores them
  20. # in the global variables.
  21. class PHPLogParser(threading.Thread):
  22. def __init__(self, php_log_file, parse_interval):
  23. global logger
  24. threading.Thread.__init__(self)
  25. self.log_file = php_log_file
  26. self.parse_interval = parse_interval
  27. logger.debug("Initializing PHPLogParser with parse interval: " + \
  28. str(self.parse_interval) + ", log file: " + self.log_file)
  29. self.tmp_log_file = '/tmp/php_mon_temp.log'
  30. # last timestamp seen in the log
  31. self.last_access_time = 0
  32. # Reads the lines that have been written in the log since the last access.
  33. # Computes the average request rate and response time and stores them
  34. # in global variables.
  35. def process_php_log(self):
  36. global logger, php_response_time, php_request_rate
  37. logger.debug("Processing PHP log...")
  38. try:
  39. # get what has been written in the log since the last time we checked
  40. f_tmp_w = open(self.tmp_log_file, 'w')
  41. subprocess.call(['/usr/sbin/logtail', '-f', self.log_file], stdout=f_tmp_w)
  42. f_tmp_w.close()
  43. start_time = 0
  44. crt_time = self.last_access_time
  45. n_requests = 0
  46. total_resp_time = 0
  47. f_tmp_r = open(self.tmp_log_file, 'r')
  48. for line in f_tmp_r:
  49. logger.debug(line + '\n')
  50. tokens = line.split()
  51. nt = len(tokens)
  52. crt_time = float(tokens[nt - 2])
  53. if (start_time == 0):
  54. start_time = crt_time
  55. total_resp_time += float(tokens[nt - 1])
  56. n_requests += 1
  57. # not the first time we read from the log
  58. if (self.last_access_time != 0):
  59. start_time = self.last_access_time
  60. end_time = crt_time
  61. logger.debug("Start time: " + str(start_time) + ", end time: " + str(end_time) + "\n")
  62. # request rate in requests / sec
  63. if (start_time != end_time):
  64. php_request_rate = n_requests / (end_time - start_time)
  65. self.last_access_time = end_time
  66. else:
  67. php_request_rate = 0
  68. # response time in ms
  69. if (n_requests != 0):
  70. php_response_time = (total_resp_time) / n_requests
  71. else:
  72. php_response_time = 0
  73. logger.debug("Req rate: " + str(php_request_rate) + ", response time: " + str(php_response_time) +
  74. "n. requests: " + str(n_requests) + "\n")
  75. f_tmp_r.close()
  76. except Exception, ex:
  77. logger.exception(ex)
  78. return 1
  79. return 0
  80. def run(self):
  81. logger.info("Started FPM log parsing thread...")
  82. while True:
  83. logger.debug("Preparing to process log...")
  84. self.process_php_log()
  85. logger.debug("Going to sleep for: " + str(self.parse_interval))
  86. if stop_parsing:
  87. break
  88. time.sleep(self.parse_interval)
  89. def request_rate_handler(name):
  90. global php_request_rate
  91. return php_request_rate
  92. def response_time_handler(name):
  93. global php_response_time
  94. return php_response_time
  95. def metric_init(params):
  96. global descriptors, php_fpm_log, logtail_interval
  97. global logger
  98. logging.basicConfig(
  99. filename='/tmp/ganglia_modules.log',
  100. format='%(asctime)-6s: %(name)s - %(levelname)s - %(message)s')
  101. logger.setLevel(logging.INFO)
  102. logger.info("Initializing metrics...")
  103. if 'php_fpm_log' in params:
  104. php_fpm_log = params['php_fpm_log']
  105. if 'monitor_interval' in params:
  106. logtail_interval = int(params['monitor_interval'])
  107. d1 = {'name': 'php_request_rate',
  108. 'call_back': request_rate_handler,
  109. 'time_max': 90,
  110. 'value_type': 'float',
  111. 'units': 'req/s',
  112. 'slope': 'both',
  113. 'format': '%f',
  114. 'description': 'PHP Request Rate',
  115. 'groups': 'web'}
  116. d2 = {'name': 'php_response_time',
  117. 'call_back': response_time_handler,
  118. 'time_max': 90,
  119. 'value_type': 'float',
  120. 'units': 'ms',
  121. 'slope': 'both',
  122. 'format': '%f',
  123. 'description': 'PHP Response Time',
  124. 'groups': 'web'}
  125. descriptors = [d1, d2]
  126. parser_thread = PHPLogParser(php_fpm_log, logtail_interval)
  127. parser_thread.start()
  128. return descriptors
  129. def metric_cleanup():
  130. '''Clean up the metric module.'''
  131. global stop_parsing
  132. stop_parsing = True
  133. # This code is for debugging and unit testing
  134. if __name__ == '__main__':
  135. metric_init({})
  136. time.sleep(5)
  137. for d in descriptors:
  138. v = d['call_back'](d['name'])
  139. print 'value for %s is %f' % (d['name'], v)
  140. stop_parsing = True