D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
opt
/
saltstack
/
salt
/
lib
/
python3.10
/
site-packages
/
salt
/
utils
/
Filename :
profile.py
back
Copy
""" Decorator and functions to profile Salt using cProfile """ import datetime import logging import os import pstats import subprocess import salt.utils.files import salt.utils.hashutils import salt.utils.path import salt.utils.stringutils log = logging.getLogger(__name__) try: import cProfile HAS_CPROFILE = True except ImportError: HAS_CPROFILE = False def profile_func(filename=None): """ Decorator for adding profiling to a nested function in Salt """ def proffunc(fun): def profiled_func(*args, **kwargs): logging.info("Profiling function %s", fun.__name__) try: profiler = cProfile.Profile() retval = profiler.runcall(fun, *args, **kwargs) profiler.dump_stats(filename or "{}_func.profile".format(fun.__name__)) except OSError: logging.exception("Could not open profile file %s", filename) return retval return profiled_func return proffunc def activate_profile(test=True): pr = None if test: if HAS_CPROFILE: pr = cProfile.Profile() pr.enable() else: log.error("cProfile is not available on your platform") return pr def output_profile(pr, stats_path="/tmp/stats", stop=False, id_=None): if pr is not None and HAS_CPROFILE: try: pr.disable() if not os.path.isdir(stats_path): os.makedirs(stats_path) date = datetime.datetime.now().isoformat() if id_ is None: id_ = salt.utils.hashutils.random_hash(size=32) ficp = os.path.join(stats_path, "{}.{}.pstats".format(id_, date)) fico = os.path.join(stats_path, "{}.{}.dot".format(id_, date)) ficn = os.path.join(stats_path, "{}.{}.stats".format(id_, date)) if not os.path.exists(ficp): pr.dump_stats(ficp) with salt.utils.files.fopen(ficn, "w") as fic: pstats.Stats(pr, stream=fic).sort_stats("cumulative") log.info("PROFILING: %s generated", ficp) log.info("PROFILING (cumulative): %s generated", ficn) pyprof = salt.utils.path.which("pyprof2calltree") cmd = [pyprof, "-i", ficp, "-o", fico] if pyprof: failed = False try: pro = subprocess.Popen( cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) except OSError: failed = True if pro.returncode: failed = True if failed: log.error("PROFILING (dot problem") else: log.info("PROFILING (dot): %s generated", fico) log.trace("pyprof2calltree output:") log.trace( salt.utils.stringutils.to_str(pro.stdout.read()).strip() + salt.utils.stringutils.to_str(pro.stderr.read()).strip() ) else: log.info("You can run %s for additional stats.", cmd) finally: if not stop: pr.enable() return pr