ok
Direktori : /proc/self/root/lib/fm-agent/plugins/ |
Current File : //proc/self/root/lib/fm-agent/plugins/nodejs.py |
import agent_util import re try: import json except: import simplejson as json from agent_util import float from os.path import isfile class NodeJSPlugin(agent_util.Plugin): """ NodeJS checking plugin for the fm agent. """ textkey = "nodejs" label = "NodeJS" _node = agent_util.which("nodejs") and "nodejs" or "node" @classmethod def get_metadata(self, config): if NodeJSPlugin._node_executable(config): status = agent_util.SUPPORTED else: status = agent_util.UNSUPPORTED if status == agent_util.UNSUPPORTED: msg = "Error finding a valid nodejs application." return {} else: msg = None found_keys = ["resident_set_size", "heap_total", "heap_used"] metadata = {} for key in found_keys: unit = "MB" metadata[key] = { "label": key.replace("_", " ").capitalize(), "options": None, "status": status, "msg": msg, "unit": unit, } metadata["cluster_workers"] = { "label": "Cluster workers", "options": None, "status": status, "msg": msg, "unit": "worker count", } metadata["high_resolution_time"] = { "label": "High resolution time", "options": None, "status": status, "msg": msg, "unit": "seconds", } return metadata @staticmethod def _node_executable(config): """ Run a simple command to make sure that the nodejs executable is available to the system. """ custom_path = config.get("node_binary_location", None) if custom_path: return isfile(custom_path) and agent_util.which(custom_path) return agent_util.which(NodeJSPlugin._node) def _retrieve_heap_data(self): """ Make a pass of retrieving the heap size of the V8. """ heap_stats = "require('v8').getHeapStatistics()" return self._eval_node(heap_stats) def _eval_node(self, instruction): """ Evaluate the passed instruction in node. All instructions are included with a console log statement to retrieve the passed information. """ node_executable = NodeJSPlugin._node_executable(self.config) eval_command = """ %s -p "%s" """ % (node_executable, instruction) result = agent_util.execute_command(eval_command) if result[0] == 0: return result[1] else: return 0 def _retrieve_entry_from_data(self, data, value): """ Retrieve a single value of the heap data returned by nodejs. """ expr = r"%s: (\d+)" % (str(value)) result = re.findall(expr, data) if result: return float(result[0]) def _retrieve_workers_data(self): """ Retrieve the result of gettings the workers. """ instruction = "require('cluster').workers" worker_obj = self._eval_node(instruction) if not worker_obj: self.log.error( "node returned unexpected output. Is the binary location correct?" ) return None expr = r"(\S+):" result = re.findall(expr, worker_obj) return len(result) def _retrieve_high_resolution_time(self): """ Retrieve the high resolution time in seconds. """ instruction = "process.hrtime()" result = self._eval_node(instruction) if not result: self.log.error( "node returned unexpected output. Is the binary location correct?" ) return None expr = r"\[ (\d+)," seconds = re.findall(expr, result) if seconds: return float(seconds[0]) else: return None def _retrieve_memory_data(self): """ Retrieve the memory data of NodeJS process. """ instruction = "process.memoryUsage()" result = self._eval_node(instruction) return result def _retrieve_resident_set_size(self): """ Extract the resident set size from the process memoryUsage. """ data = self._retrieve_memory_data() if not data: self.log.error( "node returned unexpected output. Is the binary location correct?" ) return None value = self._find_value("rss", data) value = value and self._convert_bytes_to_mb(value) or None return value def _retrieve_heap_total(self): """ Return the heap total. """ data = self._retrieve_memory_data() if not data: self.log.error( "node returned unexpected output. Is the binary location correct?" ) return None value = self._find_value("heapTotal", data) value = value and self._convert_bytes_to_mb(value) or None return value def _retrieve_heap_used(self): """ Return the heap used. """ data = self._retrieve_memory_data() if not data: self.log.error( "node returned unexpected output. Is the binary location correct?" ) return None value = self._find_value("heapUsed", data) value = value and self._convert_bytes_to_mb(value) or None return value def _convert_bytes_to_mb(self, value): """ Peform a quick conversion to mb. """ return float(value) / (2**20) def _find_value(self, target, data): """ Find the target in the passed data string as a javascript object. """ expr = r"%s: (\d+)" % (str(target)) result = re.findall(expr, data) return result and result[0] or None def check(self, textkey, data, config): self.config = config if textkey == "cluster_workers": return self._retrieve_workers_data() elif textkey == "high_resolution_time": return self._retrieve_high_resolution_time() elif textkey == "resident_set_size": return self._retrieve_resident_set_size() elif textkey == "heap_total": return self._retrieve_heap_total() else: return self._retrieve_heap_used()