def collect(self): procs = self.all_procs() self.zm = sh.zone_map(sh.zoneadm()) self.ct_map = sh.contract_map() for m in ('pr_stime', 'pr_utime', 'pr_ttime', 'pr_rtime', 'pr_tftime', 'pr_dftime', 'pr_kftime', 'pr_ltime', 'pr_slptime', 'pr_wtime', 'pr_stoptime'): if sh.wanted(m, self.config['fields']) and \ self.config['as_pc_delta'] == True: self.cpu_time(procs, m) for m in ('pr_rssize', 'pr_size'): if sh.wanted(m, self.config['fields']): for p in self.leaderboard(procs, m, self.config['top_x']): if p['val'] > 0: self.publish('memory.%s.%s' % (m, p['name']), (p['val'] * 1024), point_tags={'pid': p['pid'], 'zone': p['zone'], 'svc': self.svc_tag(p['ctid'])}) for m in ('pr_pctmem', 'pr_pctcpu'): if sh.wanted(m, self.config['fields']): for p in self.leaderboard(procs, m, self.config['top_x']): if p['val'] > 0: self.publish('memory.%s.%s' % (m, p['name']), sh.bpc_to_pc(p['val']), point_tags={'pid': p['pid'], 'zone': p['zone'], 'svc': self.svc_tag(p['ctid'])})
def collect(self): procs = self.all_procs() self.zm = sh.zone_map(sh.zoneadm()) self.ct_map = sh.contract_map() for m in ('pr_stime', 'pr_utime', 'pr_ttime', 'pr_rtime', 'pr_tftime', 'pr_dftime', 'pr_kftime', 'pr_ltime', 'pr_slptime', 'pr_wtime', 'pr_stoptime'): if sh.wanted(m, self.config['fields']) and \ self.config['as_pc_delta'] == True: self.cpu_time(procs, m) for m in ('pr_rssize', 'pr_size'): if sh.wanted(m, self.config['fields']): for p in self.leaderboard(procs, m, self.config['top_x']): if p['val'] > 0: self.publish('memory.%s.%s' % (m, p['name']), (p['val'] * 1024), point_tags={ 'pid': p['pid'], 'zone': p['zone'], 'svc': self.svc_tag(p['ctid']) }) for m in ('pr_pctmem', 'pr_pctcpu'): if sh.wanted(m, self.config['fields']): for p in self.leaderboard(procs, m, self.config['top_x']): if p['val'] > 0: self.publish('memory.%s.%s' % (m, p['name']), sh.bpc_to_pc(p['val']), point_tags={ 'pid': p['pid'], 'zone': p['zone'], 'svc': self.svc_tag(p['ctid']) })
def ns_and_pc(self, cpu_id, data): """ In addition to sending raw metrics through, we can calculate rates and percentages of the time spent in each possible CPU state. :param cpu_id: the number of the CPU kstat instance (int) :param data: kstat data for this CPU (dict) :returns: void """ st = data['snaptime'] if cpu_id not in self.last_values['cpu'].keys(): self.last_values['cpu'][cpu_id] = {} try: st_delta = st - self.last_values['cpu'][cpu_id]['st'] except: self.log.debug('cannot calculate snaptime delta') self.last_values['cpu'][cpu_id]['st'] = st for m in data: if not m.startswith('cpu_nsec'): continue metric_name = sub('_', '.', m[4:]) try: delta = data[m] - self.last_values['cpu'][cpu_id][m] # The delta is the time in this state since the last # snapshot if sh.wanted(metric_name, self.config['as_nsec_delta']): self.publish('%d.%s' % (cpu_id, metric_name), delta) # We now have the number of nanoseconds spent in # this state since the last snapshot. So, we can # create a %age, if the user wants it. pc_metric_name = sub('nsec', 'pc', metric_name) if sh.wanted(pc_metric_name, self.config['as_pc_delta']): pc_in_state = delta / float(st_delta) * 100 self.publish('%d.%s' % (cpu_id, pc_metric_name), pc_in_state, precision=3) except: self.log.debug('cannot calculate %s delta' % m) self.last_values['cpu'][cpu_id][m] = data[m]
def collect(self): svcs = self.process_data(self.svcs()) for zone, data in svcs.items(): if not sh.wanted(zone, self.config['zones']): continue if zone == '__local__' or zone == 'global': prefix = '' else: prefix = 'ngz.%s.' % zone for state, count in data.items(): if sh.wanted(state, self.config['states']): self.publish(prefix + state, count)
def collect(self): cpu_t = sh.get_kstat('cpu::sys') per_cpu = self.split_stats(cpu_t) num_cpus = self.vcpus() if sh.wanted('vcpus', self.config['fields']): self.publish('global.vcpus', num_cpus) if sh.wanted('speed', self.config['fields']): self.publish('global.clock_speed', self.clock_speed()) for n in range(0, num_cpus): self.publish('%d.cpuinfo.current_speed' % n, self.cpu_stat('current_clock_Hz', n)) if sh.wanted('state', self.config['fields']): for n in range(0, num_cpus): states = sh.get_kstat( 'cpu_info:%d:cpu_info%d' % (n, n), terse=True) for s in ('cstate', 'pstate'): self.publish('%d.cpuinfo.current_%s' % (n, s), float(states['current_%s' % s])) # If we want rate metrics, call the method which does that, # and remove the things it uses from the kstat list. This # needs to be done for each CPU. if self.config['as_pc_delta'] or self.config['as_nsec_delta']: for cpu, k in per_cpu.items(): self.ns_and_pc(cpu, k) per_cpu[cpu] = {k: per_cpu[cpu][k] for k in per_cpu[cpu] if not k.startswith('cpu_nsec')} for cpu, kstats in per_cpu.items(): kstats.pop('snaptime', None) kstats.pop('crtime', None) for k, v in kstats.items(): if sh.wanted(k, self.config['fields']): self.publish('%d.sys.%s' % (cpu, k), v)
def collect(self): if self.config['sn_tag']: point_tags = self.disk_tags() for k, v in self.kstats().items(): dev, stat = self.get_devs(k) if not sh.wanted(dev, self.config['devices'], regex=True): continue if not sh.wanted(stat, self.config['fields']): continue if self.config['sn_tag'] and dev in point_tags.keys(): self.publish('%s.%s' % (dev, stat), v, point_tags=point_tags[dev]) else: self.publish('%s.%s' % (dev, stat), v)
def collect(self): counts = ['filesystem', 'snapshot', 'volume'] for pool, data in self.zpool_dict().items(): for count in counts: if sh.wanted(count, self.config['count']): self.publish('%s.count.%s' % (pool, count), self.count_items(pool, count)) for k, v in data.items(): if not sh.wanted(k, self.config['fields']): continue if k in ('size', 'alloc', 'free', 'expandsz'): self.publish('%s.%s' % (pool, k), sh.bytify(v)) elif v.endswith('%') or v.endswith('x'): self.publish('%s.%s' % (pool, k), float(v[:-1])) elif k == 'health': self.publish('%s.health' % pool, self.health_as_int(v))
def collect(self): counts = ['filesystem', 'snapshot', 'volume'] for pool, data in self.zpool_dict().items(): for count in counts: if sh.wanted(count, self.config['count']): self.publish('%s.count.%s' % (pool, count), self.count_items(pool, count)) for k, v in data.items(): if not sh.wanted(k, self.config['fields']): continue if k in ('size', 'alloc', 'free', 'expandsz'): self.publish('%s.%s' % (pool, k), sh.bytify(v)) elif v.endswith('%') or v.endswith('x'): self.publish('%s.%s' % (pool, k), float(v[:-1])) elif k == 'health': self.publish('%s.health' % pool, self.health_as_int(v))
def collect_vminfo(self, pgs): """ Collect and present metrics from the 'vminfo' kstat. These are in pages, and they need to be converted into rates. :param pgs: the system page size. (int) """ for k, v in sh.get_kstat('unix:0:vminfo', terse=True, no_times=True).items(): if sh.wanted(k, self.config['vminfo_fields']): self.publish('vminfo.%s' % k, self.derivative(k, v) * pgs)
def collect(self): self._fs_list = self.zfs_list() for fs in self._fs_list: if sh.wanted(fs, self.config['datasets'], regex=self.config['regex']): if sh.wanted('filesystem', self.config['counts']): self.publish('count.%s.filesystem' % sh.to_metric(fs), self.num_children(fs)) for t in ('volume', 'snapshot'): if sh.wanted(t, self.config['counts']): self.publish('count.%s.%s' % (sh.to_metric(fs), t), self.num_obj(fs, t)) for k, v in self.get_all(fs).items(): if sh.wanted(k, self.config['fields']): self.publish('dataset.%s.%s' % (sh.to_metric(fs), k), v)
def collect_vminfo(self, pgs): """ Collect and present metrics from the 'vminfo' kstat. These are in pages, and they need to be converted into rates. :param pgs: the system page size. (int) """ for k, v in sh.get_kstat('unix:0:vminfo', terse=True, no_times=True).items(): if sh.wanted(k, self.config['vminfo_fields']): self.publish('vminfo.%s' % k, self.derivative(k, v) * pgs)
def collect(self): self._fs_list = self.zfs_list() for fs in self._fs_list: if sh.wanted(fs, self.config['datasets'], regex=self.config['regex']): if sh.wanted('filesystem', self.config['counts']): self.publish('count.%s.filesystem' % sh.to_metric(fs), self.num_children(fs)) for t in ('volume', 'snapshot'): if sh.wanted(t, self.config['counts']): self.publish('count.%s.%s' % (sh.to_metric(fs), t), self.num_obj(fs, t)) for k, v in self.get_all(fs).items(): if sh.wanted(k, self.config['fields']): self.publish('dataset.%s.%s' % (sh.to_metric(fs), k), v)
def collect_in_and_out(self, ks, ptn, prefix): """ A bit of a shot-in-the-dark, which I *think* will provide useful information. Pulls all paging or swapping ins-and-outs out of the cpu::vm kstats and presents them. Has the ability to aggregate or present on a per-CPU basis. :param ks: the raw cpu::vm kstats as collected by sunos_helpers::get_kstats() (dict) :param ptn: the pattern to match in the kstats ('pg' or 'swap') (string) :param prefix: the string with which to prefix each metric. Also used in the class config variable names. ('paging' or 'swapping'. (string) :returns: void """ sums = {} fields = self.config['%s_fields' % prefix] for k, v in { k: v for (k, v) in ks.items() if k.endswith('%sin' % ptn) or k.endswith('%sout' % ptn) }.items(): c = k.split(':') if self.config['per_cpu_%s' % prefix] is True and sh.wanted( k, fields): self.publish('%s.cpu.%s.%s' % (prefix, c[1], c[3]), v) else: if c[3] not in sums: sums[c[3]] = 0 sums[c[3]] += v for k, v in sums.items(): if sh.wanted(k, fields): self.publish('%s.%s' % (prefix, k), v)
def collect_in_and_out(self, ks, ptn, prefix): """ A bit of a shot-in-the-dark, which I *think* will provide useful information. Pulls all paging or swapping ins-and-outs out of the cpu::vm kstats and presents them. Has the ability to aggregate or present on a per-CPU basis. :param ks: the raw cpu::vm kstats as collected by sunos_helpers::get_kstats() (dict) :param ptn: the pattern to match in the kstats ('pg' or 'swap') (string) :param prefix: the string with which to prefix each metric. Also used in the class config variable names. ('paging' or 'swapping'. (string) :returns: void """ sums = {} fields = self.config['%s_fields' % prefix] for k, v in {k: v for (k, v) in ks.items() if k.endswith('%sin' % ptn) or k.endswith('%sout' % ptn)}.items(): c = k.split(':') if self.config['per_cpu_%s' % prefix] is True and sh.wanted( k, fields): self.publish('%s.cpu.%s.%s' % (prefix, c[1], c[3]), v) else: if c[3] not in sums: sums[c[3]] = 0 sums[c[3]] += v for k, v in sums.items(): if sh.wanted(k, fields): self.publish('%s.%s' % (prefix, k), v)
def collect_swap_cmd(self): """ Shells out to /usr/sbin/swap and sends the results as metrics. Converts to bytes from kB. Not smart, so if the output of the command changes, this will break. """ info = re.match( 'total: (\d+)k [\w ]* \+ (\d+)k.*= (\d+)k used, (\d+)k.*$', sh.run_cmd('/usr/sbin/swap -s')) for i, metric in enumerate( ['allocated', 'reserved', 'used', 'available']): if sh.wanted(metric, self.config['swap_fields']): self.publish('swap.%s' % metric, int(info.group(i + 1)) * 1024)
def collect_swap_cmd(self): """ Shells out to /usr/sbin/swap and sends the results as metrics. Converts to bytes from kB. Not smart, so if the output of the command changes, this will break. """ info = re.match( 'total: (\d+)k [\w ]* \+ (\d+)k.*= (\d+)k used, (\d+)k.*$', sh.run_cmd('/usr/sbin/swap -s')) for i, metric in enumerate(['allocated', 'reserved', 'used', 'available']): if sh.wanted(metric, self.config['swap_fields']): self.publish('swap.%s' % metric, int(info.group(i + 1)) * 1024)
def collect(self): for k, v in self.kstats().items(): mod, inst, dev, name = k.split(':') if (sh.wanted(dev, self.config['devices'], regex=True)): self.publish('%s.%s' % (dev, name), v)
def test_wanted(self): want = ['cmdk0', 'cmdk2'] self.assertFalse(sh.wanted('__all__', want)) self.assertTrue(sh.wanted('anything', '__all__')) self.assertFalse(sh.wanted('anything', '__none__')) self.assertTrue(sh.wanted('word', 'word')) self.assertTrue(sh.wanted('cmdk0', want)) self.assertFalse(sh.wanted('cmdk1', want)) self.assertFalse(sh.wanted('pen', 'pencil')) self.assertTrue(sh.wanted('cmdk0', 'cmdk\d+', regex=True)) self.assertTrue(sh.wanted('cmdk2', '^.*2$', regex=True)) want = ['cmdk[0-3]', 'did.*'] self.assertTrue(sh.wanted('cmdk1', want, regex=True)) self.assertFalse(sh.wanted('cmdk5', want, regex=True)) self.assertFalse(sh.wanted('sda', want, regex=True)) self.assertTrue(sh.wanted('did99', want, regex=True))
def test_wanted(self): want = ['cmdk0', 'cmdk2'] self.assertFalse(sh.wanted('__all__', want)) self.assertTrue(sh.wanted('anything', '__all__')) self.assertFalse(sh.wanted('anything', '__none__')) self.assertTrue(sh.wanted('word', 'word')) self.assertTrue(sh.wanted('cmdk0', want)) self.assertFalse(sh.wanted('cmdk1', want)) self.assertFalse(sh.wanted('pen', 'pencil')) self.assertTrue(sh.wanted('cmdk0', 'cmdk\d+', regex=True)) self.assertTrue(sh.wanted('cmdk2', '^.*2$', regex=True)) want = ['cmdk[0-3]', 'did.*'] self.assertTrue(sh.wanted('cmdk1', want, regex=True)) self.assertFalse(sh.wanted('cmdk5', want, regex=True)) self.assertFalse(sh.wanted('sda', want, regex=True)) self.assertTrue(sh.wanted('did99', want, regex=True))
def collect(self): for k, v in self.kstats().items(): mod, inst, dev, name = k.split(':') if (sh.wanted(dev, self.config['devices'], regex=True)): self.publish('%s.%s' % (dev, name), v)