Server IP : 184.154.167.98 / Your IP : 3.145.45.223 Web Server : Apache System : Linux pink.dnsnetservice.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 User : puertode ( 1767) PHP Version : 7.2.34 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /usr/libexec/pcp/pmdas/bcc/modules/fs/ |
Upload File : |
# # Copyright (C) 2018 Andreas Gerstmayr <andreas@gerstmayr.me> # Based on the ext4dist BCC tool by Brendan Gregg: # https://github.com/iovisor/bcc/blob/master/tools/ext4dist.py # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # """ PCP BCC PMDA ext4dist module """ # pylint: disable=invalid-name, too-many-instance-attributes from os import path from bcc import BPF from pcp.pmapi import pmUnits from cpmapi import PM_TYPE_U64, PM_SEM_COUNTER, PM_TIME_USEC from cpmda import PMDA_FETCH_NOVALUES from modules.pcpbcc import PCPBCCBase # # BPF program # bpf_src = "modules/fs/ext4dist.bpf" # # PCP BCC PMDA constants # MODULE = 'ext4dist' BASENS = 'fs.ext4.latency.' units_usecs = pmUnits(0, 1, 0, 0, PM_TIME_USEC, 0) # # PCP BCC Module # class PCPBCCModule(PCPBCCBase): """ PCP BCC ext4dist module """ def __init__(self, config, log, err, proc_refresh): """ Constructor """ PCPBCCBase.__init__(self, MODULE, config, log, err) self.pids = [] self.proc_filter = None self.proc_refresh = proc_refresh self.cache = None self.ops_addr = None self.item_identifiers = ['open', 'read', 'write', 'fsync'] for opt in self.config.options(MODULE): if opt == 'process': self.proc_filter = self.config.get(MODULE, opt) self.update_pids(self.get_proc_info(self.proc_filter)) def read_ext4_file_operations_addr(): """ Read address of ext4_file_operations symbol """ with open("/proc/kallsyms") as syms: for line in syms: addr, _size, name = line.rstrip().split(" ", 2) name = name.split("\t")[0] if name == "ext4_file_operations": return "0x" + addr return None self.ops_addr = read_ext4_file_operations_addr() if not self.ops_addr: raise RuntimeError("No ext4_file_operations in /proc/kallsyms " "(kernel not built with CONFIG_KALLSYMS_ALL).") self.log("Initialized.") # pylint: disable=bad-continuation def metrics(self): """ Get metric definitions """ for item in self.item_identifiers: self.items.append( # Name - reserved - type - semantics - units - help (BASENS + item, None, PM_TYPE_U64, PM_SEM_COUNTER, units_usecs, 'ext4' '%s latency distribution' % item), ) return True, self.items def reset_cache(self): """ Reset internal cache """ self.cache = {} def undef_cache(self): """ Undefine internal cache """ self.cache = None def compile(self): """ Compile BPF """ try: if not self.pids and self.proc_filter and not self.proc_refresh: raise RuntimeError("No process to attach found.") if not self.bpf_text: with open(path.dirname(__file__) + '/../../' + bpf_src) as src: self.bpf_text = src.read() self.bpf_text = self.bpf_text.replace("EXT4_FILE_OPERATIONS", self.ops_addr) if not self.pids and self.proc_filter and self.proc_refresh: self.log("No process to attach found, activation postponed.") return bpf_text = self.apply_pid_filter(self.bpf_text, self.pids, False) if self.debug: self.log("BPF to be compiled:\n" + bpf_text.strip()) self.reset_cache() self.bpf = BPF(text=bpf_text) # Compat: bcc < 0.6.0 (first check) if 'get_kprobe_functions' in dir(self.bpf) and \ self.get_kprobe_functions(b"ext4_file_read_iter"): self.bpf.attach_kprobe(event="ext4_file_read_iter", fn_name="trace_entry") else: self.bpf.attach_kprobe(event="generic_file_read_iter", fn_name="trace_read_entry") self.bpf.attach_kprobe(event="ext4_file_write_iter", fn_name="trace_entry") self.bpf.attach_kprobe(event="ext4_file_open", fn_name="trace_entry") self.bpf.attach_kprobe(event="ext4_sync_file", fn_name="trace_entry") self.bpf.attach_kretprobe(event="generic_file_read_iter", fn_name="trace_read_return") self.bpf.attach_kretprobe(event="ext4_file_write_iter", fn_name="trace_write_return") self.bpf.attach_kretprobe(event="ext4_file_open", fn_name="trace_open_return") self.bpf.attach_kretprobe(event="ext4_sync_file", fn_name="trace_fsync_return") self.log("Compiled.") except Exception as error: # pylint: disable=broad-except self.bpf = None self.undef_cache() self.err(str(error)) self.err("Module NOT active!") raise def refresh(self): """ Refresh BPF data """ if self.bpf is None: return None dist = self.bpf["dist"] self.insts = self.read_log2_histograms(dist, self.cache) dist.clear() return self.insts def bpfdata(self, item, inst): """ Return BPF data as PCP metric value """ try: key = self.pmdaIndom.inst_name_lookup(inst) item_identifier = self.item_identifiers[item] if item_identifier in self.cache and key in self.cache[item_identifier]: return [self.cache[item_identifier][key], 1] elif self.insts: # BCC module is ready (we have histogram buckets), # but doesn't contain the specified histogram bucket return [0, 1] else: # BCC module isn't ready yet return [PMDA_FETCH_NOVALUES, 0] except Exception: # pylint: disable=broad-except return [PMDA_FETCH_NOVALUES, 0] def label_indom(self): """ Instance domain labels """ return '{"statistic":"histogram"}' def label_instance(self, inst): """ Instances labels """ key = self.pmdaIndom.inst_name_lookup(inst) bounds = key.split('-') return '{"lower_bound":%s,"upper_bound":%s}' % (bounds[0], bounds[1])