Example #1
0
    def get_pid_jmx_stats(self, pid, port, output):
        """Call get_jmx_parameters function for each doc_type and add dict to queue"""
        jolokiaclient = JolokiaClient.get_jolokia_inst(port)
        for doc in GENERIC_DOCS:
            try:
                dict_jmx = {}
                self.get_jmx_parameters(jolokiaclient, doc, dict_jmx)
                if not dict_jmx:
                    raise ValueError("No data found")

                collectd.info("Plugin kafkajmx: Added %s doctype information successfully for pid %s" % (doc, pid))
                self.add_common_params(doc, dict_jmx)
                output.put((doc, dict_jmx))
            except Exception as err:
                collectd.error("Plugin kafkajmx: Error in collecting stats of %s doctype: %s" % (doc, str(err)))
Example #2
0
    def get_pid_jmx_stats(self, pid, port, output):
        """Call get_jmx_parameters function for each doc_type and add dict to queue"""
        jolokiaclient = JolokiaClient.get_jolokia_inst(port)
        for doc in KAFKA_DOCS:
            try:
                dict_jmx = {}
                self.get_jmx_parameters(jolokiaclient, doc, dict_jmx)
                if not dict_jmx:
                    raise ValueError("No data found")

                collectd.info(
                    "Plugin kafkatopic: Added %s doctype information successfully for pid %s"
                    % (doc, pid))
                if doc in ["topicStats", "partitionStats", "consumerStats"]:
                    output.append((pid, doc, dict_jmx))
                    continue

                self.add_common_params(doc, dict_jmx)
                output.append((pid, doc, dict_jmx))
            except Exception as err:
                collectd.error(
                    "Plugin kafkatopic: Error in collecting stats of %s doctype: %s"
                    % (doc, str(err)))
class JmxStat(object):
    """Plugin object will be created only once and collects JMX statistics info every interval."""
    def __init__(self):
        """Initializes interval and previous dictionary variable."""
        self.process = 'zookeeper'
        self.interval = DEFAULT_INTERVAL
        self.listenerip = 'localhost'
        self.port = None
        self.prev_data = {}
        self.documentsTypes = []
        self.jclient = JolokiaClient(
            os.path.basename(__file__)[:-3], self.process)

    def config(self, cfg):
        """Initializes variables from conf files."""
        for children in cfg.children:
            if children.key == INTERVAL:
                self.interval = children.values[0]
            if children.key == LISTENERIP:
                self.listenerip = children.values[0]
            if children.key == PORT:
                self.port = children.values[0]
            if children.key == DOCUMENTSTYPES:
                self.documentsTypes = children.values[0]

    def get_jmx_parameters(self, jolokiaclient, doc, dict_jmx):
        """Fetch stats based on doc_type"""
        if doc == "memoryPoolStats":
            self.add_memory_pool_parameters(jolokiaclient, dict_jmx)
        elif doc == "memoryStats":
            self.add_memory_parameters(jolokiaclient, dict_jmx)
        elif doc == "threadStats":
            self.add_threading_parameters(jolokiaclient, dict_jmx)
        elif doc == "gcStats":
            self.add_gc_parameters(jolokiaclient, dict_jmx)
        elif doc == "classLoadingStats":
            self.add_classloading_parameters(jolokiaclient, dict_jmx)
        elif doc == "compilationStats":
            self.add_compilation_parameters(jolokiaclient, dict_jmx)
        elif doc == "nioStats":
            self.add_nio_parameters(jolokiaclient, dict_jmx)
        elif doc == "operatingSysStats":
            self.add_operating_system_parameters(jolokiaclient, dict_jmx)
        elif doc == "zookeeperStats":
            self.add_zookeeper_parameters(jolokiaclient, dict_jmx)
        elif doc == "jmxStats":
            self.add_jmxstats_parameters(jolokiaclient, dict_jmx)

    def add_default_rate_value(self, dict_jmx):
        """Add default value to rate key based on type"""
        keylist = ["packetsReceivedRate", "packetsSentRate"]
        for key in keylist:
            dict_jmx[key] = 0

    def get_rate(self, key, curr_data, prev_data):
        """Calculate and returns rate. Rate=(current_value-prev_value)/time."""
        #TODO The code is similar to the one in utils.py.
        rate = NAN
        if not prev_data:
            return rate

        if key not in prev_data:
            collectd.error("%s key not in previous data. Shouldn't happen." %
                           key)
            return rate

        if TIMESTAMP not in curr_data or TIMESTAMP not in prev_data:
            collectd.error("%s key not in previous data. Shouldn't happen." %
                           key)
            return rate

        curr_time = curr_data[TIMESTAMP]
        prev_time = prev_data[TIMESTAMP]
        if curr_time <= prev_time:
            collectd.error(
                "Current data time: %s is less than previous data time: %s. "
                "Shouldn't happen." % (curr_time, prev_time))
            return rate

        rate = (curr_data[key] - prev_data[key]) / float(self.interval)
        if rate < 0:
            rate = 0
        return rate

    def add_rate(self, pid, dict_jmx):
        """Rate only for zookeeper jmx metrics"""
        rate = self.get_rate("packetsReceived", dict_jmx, self.prev_data[pid])
        if rate != NAN:
            dict_jmx["packetsReceivedRate"] = round(rate, FLOATING_FACTOR)
        rate = self.get_rate("packetsSent", dict_jmx, self.prev_data[pid])
        if rate != NAN:
            dict_jmx["packetsSentRate"] = round(rate, FLOATING_FACTOR)

    def add_rate_dispatch(self, pid, doc, dict_jmx):
        """Add default for rate keys in first poll."""
        if pid in self.prev_data:
            self.add_rate(pid, dict_jmx)
        else:
            self.add_default_rate_value(dict_jmx)
        self.prev_data[pid] = dict_jmx
        self.dispatch_data(doc, deepcopy(dict_jmx))

    def get_memory_pool_names(self, jolokiaclient):
        """Get memory pool names of jvm process"""
        mempool_json = jolokiaclient.request(
            type='read', mbean='java.lang:type=MemoryPool,*', attribute='Name')
        mempool_names = []
        if mempool_json['status'] == 200:
            for _, value in mempool_json['value'].items():
                if value['Name'] in DEFAULT_MP:
                    mempool_names.append(value['Name'])
                else:
                    collectd.error(
                        "Plugin zookeeperjmx: not supported for memory pool %s"
                        % value['Name'])
        return mempool_names

    def get_gc_names(self, jolokiaclient):
        gc_json = jolokiaclient.request(
            type='read',
            mbean='java.lang:type=GarbageCollector,*',
            attribute='Name')
        gc_names = []
        if gc_json['status'] == 200:
            for _, value in gc_json['value'].items():
                if value['Name'] in DEFAULT_GC:
                    gc_names.append(value['Name'])
                else:
                    collectd.error(
                        "Plugin zookeeperjmx: not supported for GC %s" %
                        value['Name'])
        return gc_names

    def add_jmxstats_parameters(self, jolokiaclient, dict_jmx):
        """Add specific jmxstats parameter"""
        #classloading Stats
        classloading = jolokiaclient.request(
            type='read', mbean='java.lang:type=ClassLoading')
        if classloading['status'] == 200:
            dict_jmx['unloadedClass'] = classloading['value'][
                'UnloadedClassCount']
            dict_jmx['loadedClass'] = classloading['value']['LoadedClassCount']

        #threading Stats
        thread_json = jolokiaclient.request(type='read',
                                            mbean='java.lang:type=Threading')
        if thread_json['status'] == 200:
            dict_jmx['threads'] = thread_json['value']['ThreadCount']

        #memory Stats
        memory_json = jolokiaclient.request(type='read',
                                            mbean='java.lang:type=Memory')
        if memory_json['status'] == 200:
            heap = memory_json['value']['HeapMemoryUsage']
            self.handle_neg_bytes(heap['init'], 'heapMemoryUsageInit',
                                  dict_jmx)
            dict_jmx['heapMemoryUsageUsed'] = round(
                heap['used'] / 1024.0 / 1024.0, 2)
            dict_jmx['heapMemoryUsageCommitted'] = round(
                heap['committed'] / 1024.0 / 1024.0, 2)
            non_heap = memory_json['value']['NonHeapMemoryUsage']
            self.handle_neg_bytes(non_heap['init'], 'nonHeapMemoryUsageInit',
                                  dict_jmx)
            dict_jmx['nonHeapMemoryUsageUsed'] = round(
                non_heap['used'] / 1024.0 / 1024.0, 2)
            dict_jmx['nonHeapMemoryUsageCommitted'] = round(
                non_heap['committed'] / 1024.0 / 1024.0, 2)

        #initailize default values
        param_list = ['G1OldGenerationCollectionTime', 'G1OldGenerationCollectionCount', 'G1YoungGenerationCollectionTime',\
                      'G1YoungGenerationCollectionCount', 'G1OldGenUsageUsed', 'G1SurvivorSpaceUsageUsed', 'MetaspaceUsageUsed',\
                      'CodeCacheUsageUsed', 'CompressedClassSpaceUsageUsed', 'G1EdenSpaceUsageUsed']
        for param in param_list:
            dict_jmx[param] = 0

        #gc Stats
        gc_names = self.get_gc_names(jolokiaclient)
        for gc_name in gc_names:
            str_mbean = 'java.lang:type=GarbageCollector,name=' + gc_name
            valid = jolokiaclient.request(type='read',
                                          mbean=str_mbean,
                                          attribute='Valid')
            if valid['status'] == 200 and valid['value'] == True:
                str_attribute = 'CollectionTime,CollectionCount'
                gc_values = jolokiaclient.request(type='read',
                                                  mbean=str_mbean,
                                                  attribute=str_attribute)
                gc_name_no_spaces = ''.join(gc_name.split())
                if gc_values['status'] == 200:
                    dict_jmx[gc_name_no_spaces + 'CollectionTime'] = round(
                        gc_values['value']['CollectionTime'] * 0.001, 2)
                    dict_jmx[gc_name_no_spaces +
                             'CollectionCount'] = gc_values['value'][
                                 'CollectionCount']

        #memoryPool Stats
        mp_names = self.get_memory_pool_names(jolokiaclient)
        for pool_name in mp_names:
            str_mbean = 'java.lang:type=MemoryPool,name=' + pool_name
            valid = jolokiaclient.request(type='read',
                                          mbean=str_mbean,
                                          attribute='Valid')
            if valid['status'] == 200 and valid['value'] == True:
                mp_values = jolokiaclient.request(type='read',
                                                  mbean=str_mbean,
                                                  attribute='Usage')
                pool_name_no_spaces = ''.join(pool_name.split())
                if mp_values['status'] == 200:
                    dict_jmx[pool_name_no_spaces + 'UsageUsed'] = round(
                        mp_values['value']['used'] / 1024.0 / 1024.0, 2)

    def get_zookeeper_info(self):
        "Getting info about zookeeper type whether it is a standalone or cluster"
        try:
            p1 = subprocess.Popen("echo srvr | nc localhost 2181",
                                  shell=True,
                                  stdout=subprocess.PIPE)
            output = p1.communicate()[0]
            if output:
                output_list = output.splitlines()
            for line in output_list:
                if "Mode" in line:
                    zootype_list = line.split(":")
                    zootype = zootype_list[1].strip()
            return zootype
        except Exception as e:
            collectd.error("Error in getting zookeeper info due to %s" %
                           str(e))
            return None

    def get_zookeeper_id(self):
        "If zookeeper type is a cluster, get its own id and set its appropriate"
        try:
            p2 = subprocess.Popen("cat /opt/kafka/data/zookeeper/myid",
                                  shell=True,
                                  stdout=subprocess.PIPE)
            output = p2.communicate()[0]
            if output:
                return output
        except Exception as e:
            collectd.error("Error in getting zookeeper info due to %s" %
                           str(e))
            return None

    def add_zookeeper_parameters(self, jolokiaClient, dict_jmx):
        "Getting info about zookeeper type whether it is a standalone or cluster"
        zookpertype = self.get_zookeeper_info()
        if zookpertype == "standalone":
            zookper = jolokiaClient.request(
                type='read',
                mbean='org.apache.ZooKeeperService:name0=StandaloneServer_port'
                + self.port)
            mbean_memory = 'org.apache.ZooKeeperService:name0=StandaloneServer_port%s,name1=InMemoryDataTree' % self.port
        else:
            zookpertype = zookpertype[0].upper() + zookpertype[1:]
            # If zookeeper type is a cluster, get its own id and set its appropriate
            zookperId = self.get_zookeeper_id()
            bean = 'org.apache.ZooKeeperService:name0=ReplicatedServer_id' + zookperId + ',name1=replica.' + zookperId + ',name2=' + zookpertype
            zookper = jolokiaClient.request(type='read', mbean=bean)
            mbean_memory = 'org.apache.ZooKeeperService:name0=ReplicatedServer_id' + zookperId + ',name1=replica.' + zookperId + \
                           ',name2=' + zookpertype + ',name3=InMemoryDataTree'

        if zookper['status'] == 200:
            dict_jmx['avgRequestLatency'] = round(
                zookper['value']['AvgRequestLatency'] * 0.001, 2)
            dict_jmx['maxSessionTimeout'] = round(
                zookper['value']['MaxSessionTimeout'] * 0.001, 2)
            dict_jmx['minSessionTimeout'] = round(
                zookper['value']['MinSessionTimeout'] * 0.001, 2)
            dict_jmx['maxClientCnxnsPerHost'] = zookper['value'][
                'MaxClientCnxnsPerHost']
            dict_jmx['numAliveConnections'] = zookper['value'][
                'NumAliveConnections']
            dict_jmx['outstandingRequests'] = zookper['value'][
                'OutstandingRequests']
            dict_jmx['packetsReceived'] = zookper['value']['PacketsReceived']
            dict_jmx['packetsSent'] = zookper['value']['PacketsSent']
            dict_jmx['zookeeperVersion'] = ((
                zookper['value']['Version']).split(","))[0]
        zookper_count = jolokiaClient.request(type='read', mbean=mbean_memory)
        if zookper_count['status'] == 200:
            dict_jmx['nodeCount'] = zookper_count['value']['NodeCount']
            dict_jmx['watchCount'] = zookper_count['value']['WatchCount']
        zookper_ephemerals = jolokiaClient.request(type='exec',
                                                   mbean=mbean_memory,
                                                   operation='countEphemerals')
        if zookper_ephemerals['status'] == 200:
            dict_jmx['countEphemerals'] = zookper_ephemerals['value']
        zookper_datasize = jolokiaClient.request(type='exec',
                                                 mbean=mbean_memory,
                                                 operation='countEphemerals')
        if zookper_datasize['status'] == 200:
            dict_jmx['approximateDataSize'] = round(
                zookper_datasize['value'] / 1024.0 / 1024.0, 2)

    def add_operating_system_parameters(self, jolokiaclient, dict_jmx):
        """Add operating system related jmx stats"""
        ops = jolokiaclient.request(type='read',
                                    mbean='java.lang:type=OperatingSystem')
        if ops['status'] == 200:
            dict_jmx['osArchitecture'] = ops['value']['Arch']
            dict_jmx['availableProcessors'] = ops['value'][
                'AvailableProcessors']
            self.handle_neg_bytes(ops['value']['CommittedVirtualMemorySize'],
                                  'committedVirtualMemorySize', dict_jmx)
            dict_jmx['freePhysicalMemorySize'] = round(
                ops['value']['FreePhysicalMemorySize'] / 1024.0 / 1024.0, 2)
            dict_jmx['freeSwapSpaceSize'] = round(
                ops['value']['FreeSwapSpaceSize'] / 1024.0 / 1024.0, 2)
            dict_jmx['maxFileDescriptors'] = ops['value'][
                'MaxFileDescriptorCount']
            dict_jmx['osName'] = ops['value']['Name']
            dict_jmx['openFileDescriptors'] = ops['value'][
                'OpenFileDescriptorCount']
            dict_jmx['processCpuLoad'] = ops['value']['ProcessCpuLoad']
            pcputime = ops['value']['ProcessCpuTime']
            if pcputime >= 0:
                pcputime = round(pcputime / 1000000000.0, 2)
            dict_jmx['processCpuTime'] = pcputime
            dict_jmx['totalPhysicalMemorySize'] = round(
                ops['value']['TotalPhysicalMemorySize'] / 1024.0 / 1024.0, 2)
            dict_jmx['totalSwapSpaceSize'] = round(
                ops['value']['TotalSwapSpaceSize'] / 1024.0 / 1024.0, 2)
            dict_jmx['osVersion'] = ops['value']['Version']
            dict_jmx['systemCpuLoad'] = ops['value']['SystemCpuLoad']
            dict_jmx['systemLoadAverage'] = ops['value']['SystemLoadAverage']

    def add_nio_parameters(self, jolokiaclient, dict_jmx):
        """Add network related jmx stats"""
        nio = jolokiaclient.request(type='read',
                                    mbean='java.nio:type=BufferPool,*',
                                    attribute='Name')
        bufferpool_names = []
        if nio['status'] == 200:
            for _, value in nio['value'].items():
                bufferpool_names.append(value['Name'])

        for poolname in bufferpool_names:
            str_mbean = 'java.nio:type=BufferPool,name=' + poolname
            poolinfo = jolokiaclient.request(type='read', mbean=str_mbean)
            if poolinfo['status'] == 200:
                dict_jmx[poolname +
                         'BufferPoolCount'] = poolinfo['value']['Count']
                self.handle_neg_bytes(poolinfo['value']['MemoryUsed'],
                                      poolname + 'BufferPoolMemoryUsed',
                                      dict_jmx)
                self.handle_neg_bytes(poolinfo['value']['TotalCapacity'],
                                      poolname + 'BufferPoolTotalCapacity',
                                      dict_jmx)

    def add_compilation_parameters(self, jolokiaclient, dict_jmx):
        """Add compilation related jmx stats"""
        compilation = jolokiaclient.request(type='read',
                                            mbean='java.lang:type=Compilation')
        if compilation['status'] == 200:
            dict_jmx['compilerName'] = compilation['value']['Name']
            dict_jmx['totalCompilationTime'] = round(
                compilation['value']['TotalCompilationTime'] * 0.001, 2)

    def add_classloading_parameters(self, jolokiaclient, dict_jmx):
        """Add classloading related jmx stats"""
        classloading = jolokiaclient.request(
            type='read', mbean='java.lang:type=ClassLoading')
        if classloading['status'] == 200:
            dict_jmx['unloadedClass'] = classloading['value'][
                'UnloadedClassCount']
            dict_jmx['loadedClass'] = classloading['value']['LoadedClassCount']
            dict_jmx['totalLoadedClass'] = classloading['value'][
                'TotalLoadedClassCount']

    def add_gc_parameters(self, jolokiaclient, dict_jmx):
        """Add garbage collector related jmx stats"""
        def memory_gc_usage(self, mempool_gc, key, gc_name, dict_jmx):
            for name, values in mempool_gc.items():
                if name in ['G1 Eden Space', 'G1 Old Gen']:
                    mp_name = ''.join(name.split())
                    self.handle_neg_bytes(values['init'],
                                          gc_name + key + mp_name + 'Init',
                                          dict_jmx)
                    self.handle_neg_bytes(values['max'],
                                          gc_name + key + mp_name + 'Max',
                                          dict_jmx)
                    dict_jmx[gc_name + key + mp_name + 'Used'] = round(
                        values['used'] / 1024.0 / 1024.0, 2)
                    dict_jmx[gc_name + key + mp_name + 'Committed'] = round(
                        values['committed'] / 1024.0 / 1024.0, 2)

        gc_names = self.get_gc_names(jolokiaclient)
        for gc_name in gc_names:
            str_mbean = 'java.lang:type=GarbageCollector,name=' + gc_name
            if_valid = jolokiaclient.request(type='read',
                                             mbean=str_mbean,
                                             attribute='Valid')
            if if_valid['status'] == 200 and if_valid['value'] == True:
                str_attribute = 'CollectionTime,CollectionCount,LastGcInfo'
                gc_values = jolokiaclient.request(type='read',
                                                  mbean=str_mbean,
                                                  attribute=str_attribute)
                gc_name_no_spaces = ''.join(gc_name.split())
                if gc_values['status'] == 200:
                    dict_jmx[gc_name_no_spaces + 'CollectionTime'] = round(
                        gc_values['value']['CollectionTime'] * 0.001, 2)
                    dict_jmx[gc_name_no_spaces +
                             'CollectionCount'] = gc_values['value'][
                                 'CollectionCount']
                    if gc_values['value']['LastGcInfo']:
                        dict_jmx[gc_name_no_spaces +
                                 'GcThreadCount'] = gc_values['value'][
                                     'LastGcInfo']['GcThreadCount']
                        dict_jmx[gc_name_no_spaces + 'StartTime'] = round(
                            gc_values['value']['LastGcInfo']['startTime'] *
                            0.001, 2)
                        dict_jmx[gc_name_no_spaces + 'EndTime'] = round(
                            gc_values['value']['LastGcInfo']['endTime'] *
                            0.001, 2)
                        dict_jmx[gc_name_no_spaces + 'Duration'] = round(
                            gc_values['value']['LastGcInfo']['duration'] *
                            0.001, 2)
                        mem_aftergc = gc_values['value']['LastGcInfo'][
                            'memoryUsageAfterGc']
                        memory_gc_usage(self, mem_aftergc, 'MemUsageAfGc',
                                        gc_name_no_spaces, dict_jmx)
                        mem_beforegc = gc_values['value']['LastGcInfo'][
                            'memoryUsageBeforeGc']
                        memory_gc_usage(self, mem_beforegc, 'MemUsageBfGc',
                                        gc_name_no_spaces, dict_jmx)

    def add_threading_parameters(self, jolokiaclient, dict_jmx):
        """Add thread related jmx stats"""
        mbean_threading = 'java.lang:type=Threading'
        thread_json = jolokiaclient.request(type='read', mbean=mbean_threading)
        if thread_json['status'] == 200:
            dict_jmx['threads'] = thread_json['value']['ThreadCount']
            dict_jmx['peakThreads'] = thread_json['value']['PeakThreadCount']
            dict_jmx['daemonThreads'] = thread_json['value'][
                'DaemonThreadCount']
            dict_jmx['totalStartedThreads'] = thread_json['value'][
                'TotalStartedThreadCount']
            if thread_json['value']['CurrentThreadCpuTimeSupported']:
                dict_jmx['currentThreadCpuTime'] = round(
                    thread_json['value']['CurrentThreadCpuTime'] /
                    1000000000.0, 2)
                dict_jmx['currentThreadUserTime'] = round(
                    thread_json['value']['CurrentThreadUserTime'] /
                    1000000000.0, 2)

    def add_memory_parameters(self, jolokiaclient, dict_jmx):
        """Add memory related jmx stats"""
        memory_json = jolokiaclient.request(type='read',
                                            mbean='java.lang:type=Memory')
        if memory_json['status'] == 200:
            heap = memory_json['value']['HeapMemoryUsage']
            self.handle_neg_bytes(heap['init'], 'heapMemoryUsageInit',
                                  dict_jmx)
            self.handle_neg_bytes(heap['max'], 'heapMemoryUsageMax', dict_jmx)
            dict_jmx['heapMemoryUsageUsed'] = round(
                heap['used'] / 1024.0 / 1024.0, 2)
            dict_jmx['heapMemoryUsageCommitted'] = round(
                heap['committed'] / 1024.0 / 1024.0, 2)

            non_heap = memory_json['value']['NonHeapMemoryUsage']
            self.handle_neg_bytes(non_heap['init'], 'nonHeapMemoryUsageInit',
                                  dict_jmx)
            self.handle_neg_bytes(non_heap['max'], 'nonHeapMemoryUsageMax',
                                  dict_jmx)
            dict_jmx['nonHeapMemoryUsageUsed'] = round(
                non_heap['used'] / 1024.0 / 1024.0, 2)
            dict_jmx['nonHeapMemoryUsageCommitted'] = round(
                non_heap['committed'] / 1024.0 / 1024.0, 2)
            dict_jmx['objectPendingFinalization'] = memory_json['value'][
                'ObjectPendingFinalizationCount']

    def add_memory_pool_parameters(self, jolokiaclient, dict_jmx):
        """Add memory pool related jmx stats"""
        mp_names = self.get_memory_pool_names(jolokiaclient)
        for pool_name in mp_names:
            str_mbean = 'java.lang:type=MemoryPool,name=' + pool_name
            if_valid = jolokiaclient.request(type='read',
                                             mbean=str_mbean,
                                             attribute='Valid')
            if if_valid['status'] == 200 and if_valid['value'] == True:
                str_attribute = 'CollectionUsage,PeakUsage,Type,Usage,CollectionUsageThresholdSupported,UsageThresholdSupported'
                mp_values = jolokiaclient.request(type='read',
                                                  mbean=str_mbean,
                                                  attribute=str_attribute)
                pool_name_no_spaces = ''.join(pool_name.split())
                if mp_values['status'] == 200:
                    coll_usage = mp_values['value']['CollectionUsage']
                    if coll_usage:
                        self.handle_neg_bytes(
                            coll_usage['max'],
                            pool_name_no_spaces + 'CollectionUsageMax',
                            dict_jmx)
                        self.handle_neg_bytes(
                            coll_usage['init'],
                            pool_name_no_spaces + 'CollectionUsageInit',
                            dict_jmx)
                        dict_jmx[pool_name_no_spaces +
                                 'CollectionUsageUsed'] = round(
                                     coll_usage['used'] / 1024.0 / 1024.0, 2)
                        dict_jmx[pool_name_no_spaces +
                                 'CollectionUsageCommitted'] = round(
                                     coll_usage['committed'] / 1024.0 / 1024.0,
                                     2)
                    usage = mp_values['value']['Usage']
                    self.handle_neg_bytes(usage['max'],
                                          pool_name_no_spaces + 'UsageMax',
                                          dict_jmx)
                    self.handle_neg_bytes(usage['init'],
                                          pool_name_no_spaces + 'UsageInit',
                                          dict_jmx)
                    dict_jmx[pool_name_no_spaces + 'UsageUsed'] = round(
                        usage['used'] / 1024.0 / 1024.0, 2)
                    dict_jmx[pool_name_no_spaces + 'UsageCommitted'] = round(
                        usage['committed'] / 1024.0 / 1024.0, 2)
                    peak_usage = mp_values['value']['PeakUsage']
                    self.handle_neg_bytes(peak_usage['max'],
                                          pool_name_no_spaces + 'PeakUsageMax',
                                          dict_jmx)
                    self.handle_neg_bytes(
                        peak_usage['init'],
                        pool_name_no_spaces + 'PeakUsageInit', dict_jmx)
                    dict_jmx[pool_name_no_spaces + 'PeakUsageUsed'] = round(
                        peak_usage['used'] / 1024.0 / 1024.0, 2)
                    dict_jmx[pool_name_no_spaces +
                             'PeakUsageCommitted'] = round(
                                 peak_usage['committed'] / 1024.0 / 1024.0, 2)
                    if mp_values['value']['CollectionUsageThresholdSupported']:
                        coll_attr = 'CollectionUsageThreshold,CollectionUsageThresholdCount,CollectionUsageThresholdExceeded'
                        coll_threshold = jolokiaclient.request(
                            type='read', mbean=str_mbean, attribute=coll_attr)
                        if coll_threshold['status'] == 200:
                            dict_jmx[pool_name_no_spaces +
                                     'CollectionUsageThreshold'] = round(
                                         coll_threshold['value']
                                         ['CollectionUsageThreshold'] /
                                         1024.0 / 1024.0, 2)
                            dict_jmx[
                                pool_name_no_spaces +
                                'CollectionUsageThresholdCount'] = coll_threshold[
                                    'value']['CollectionUsageThreshold']
                            dict_jmx[
                                pool_name_no_spaces +
                                'CollectionUsageThresholdExceeded'] = coll_threshold[
                                    'value'][
                                        'CollectionUsageThresholdExceeded']
                    if mp_values['value']['UsageThresholdSupported']:
                        usage_attr = 'UsageThreshold,UsageThresholdCount,UsageThresholdExceeded'
                        usage_threshold = jolokiaclient.request(
                            type='read', mbean=str_mbean, attribute=usage_attr)
                        if usage_threshold['status'] == 200:
                            dict_jmx[pool_name_no_spaces +
                                     'UsageThreshold'] = round(
                                         usage_threshold['value']
                                         ['UsageThreshold'] / 1024.0 / 1024.0,
                                         2)
                            dict_jmx[pool_name_no_spaces +
                                     'UsageThresholdCount'] = usage_threshold[
                                         'value']['UsageThreshold']
                            dict_jmx[
                                pool_name_no_spaces +
                                'UsageThresholdExceeded'] = usage_threshold[
                                    'value']['UsageThresholdExceeded']

    def handle_neg_bytes(self, value, resultkey, dict_jmx):
        """Condition for byte keys whose return value may be -1 if not supported."""
        if value == -1:
            dict_jmx[resultkey] = value
        else:
            dict_jmx[resultkey] = round(value / 1024.0 / 1024.0, 2)

    def add_common_params(self, doc, dict_jmx):
        """Adds TIMESTAMP, PLUGIN, PLUGITYPE to dictionary."""
        timestamp = int(round(time.time() * 1000))
        dict_jmx[TIMESTAMP] = timestamp
        dict_jmx[PLUGIN] = ZOOK_JMX
        dict_jmx[PLUGINTYPE] = doc
        dict_jmx[ACTUALPLUGINTYPE] = ZOOK_JMX
        #dict_jmx[PLUGIN_INS] = doc
        collectd.info(
            "Plugin zookeeperjmx: Added common parameters successfully for %s doctype"
            % doc)

    def get_pid_jmx_stats(self, pid, port, output):
        """Call get_jmx_parameters function for each doc_type and add dict to queue"""
        jolokiaclient = self.jclient.get_jolokia_inst(port)
        for doc in ZOOK_DOCS:
            try:
                dict_jmx = {}
                self.get_jmx_parameters(jolokiaclient, doc, dict_jmx)
                if not dict_jmx:
                    raise ValueError("No data found")

                collectd.info(
                    "Plugin zookeeperjmx: Added %s doctype information successfully for pid %s"
                    % (doc, pid))
                self.add_common_params(doc, dict_jmx)
                output.put((pid, doc, dict_jmx))
            except Exception as err:
                collectd.error(
                    "Plugin zookeeperjmx: Error in collecting stats of %s doctype: %s"
                    % (doc, str(err)))

    def run_pid_process(self, list_pid):
        """Spawn process for each pid"""
        procs = []
        output = multiprocessing.Queue()
        for pid in list_pid:
            port = self.jclient.get_jolokia_port(pid)
            if port and self.jclient.connection_available(port):
                proc = multiprocessing.Process(target=self.get_pid_jmx_stats,
                                               args=(pid, port, output))
                procs.append(proc)
                proc.start()

        for proc in procs:
            proc.join()


#       for p in procs:
#          collectd.debug("%s, %s" % (p, p.is_alive()))
        return procs, output

    def collect_jmx_data(self):
        """Collects stats and spawns process for each pids."""
        list_pid = self.jclient.get_pid()
        if not list_pid:
            collectd.error("Plugin zookeeperjmx: No %s processes are running" %
                           self.process)
            return

        procs, output = self.run_pid_process(list_pid)
        for _ in procs:
            for _ in ZOOK_DOCS:
                try:
                    pid, doc_name, doc_result = output.get_nowait()
                except Queue.Empty:
                    collectd.error(
                        "Failed to send one or more doctype document to collectd"
                    )
                    continue
                # Dispatching documentsTypes which are requetsed alone
                if doc_name in self.documentsTypes:
                    if doc_name == "zookeeperStats":
                        self.add_rate_dispatch(pid, doc_name, doc_result)
                    else:
                        self.dispatch_data(doc_name, doc_result)
        output.close()

    def dispatch_data(self, doc_name, result):
        """Dispatch data to collectd."""
        if doc_name == "zookeeperStats":
            for item in ["packetsSent", "packetsReceived"]:
                del result[item]

        collectd.info(
            "Plugin zookeeperjmx: Succesfully sent %s doctype to collectd." %
            doc_name)
        collectd.debug("Plugin zookeeperjmx: Values dispatched =%s" %
                       json.dumps(result))
        utils.dispatch(result)

    def read_temp(self):
        """Collectd first calls register_read. At that time default interval is taken,
        hence temporary function is made to call, the read callback is unregistered
        and read() is called again with interval obtained from conf by register_config callback."""
        collectd.unregister_read(self.read_temp)
        collectd.register_read(self.collect_jmx_data,
                               interval=int(self.interval))