19531d0eb9852b98e5735c999de8d683889c59fd
[yaffs-website] / vendor / drush / drush / src / Commands / core / XhprofCommands.php
1 <?php
2
3 namespace Drush\Commands\core;
4
5 use Consolidation\AnnotatedCommand\AnnotationData;
6 use Consolidation\AnnotatedCommand\CommandData;
7 use Drush\Drush;
8 use Symfony\Component\Console\Input\InputInterface;
9 use Drush\Commands\DrushCommands;
10
11 /**
12  * Class XhprofCommands
13  * @package Drush\Commands\core
14  *
15  * Supports profiling Drush commands using either XHProf or Tideways XHProf.
16  *
17  * Note that XHProf is only compatible with PHP 5.6. For PHP 7+, you must use
18  * the Tideways XHProf fork. The Tideways XHProf extension recently underwent a
19  * major refactor; Drush is only compatible with the newer version.
20  * @see https://tideways.com/profiler/blog/releasing-new-tideways-xhprof-extension
21  *
22  * @todo Remove support for XHProf extension once PHP 5.6 is EOL.
23  */
24 class XhprofCommands extends DrushCommands
25 {
26
27     const XH_PROFILE_MEMORY = false;
28     const XH_PROFILE_CPU = false;
29     const XH_PROFILE_BUILTINS = true;
30
31
32   // @todo Add a command for launching the built-in web server pointing to the HTML site of xhprof.
33   // @todo Write a topic explaining how to use this.
34
35     /**
36      * @hook option *
37      *
38      * @option xh-link URL to your XHProf report site.
39      */
40     public function optionsetXhProf($options = ['xh-link' => self::REQ])
41     {
42     }
43
44     /**
45      * Enable profiling via XHProf
46      *
47      * @hook post-command *
48      */
49     public function xhprofPost($result, CommandData $commandData)
50     {
51         if (self::xhprofIsEnabled()) {
52             $namespace = 'Drush';
53             $run_id = self::xhprofFinishRun($namespace);
54             $url = Drush::config()->get('xh.link') . '/index.php?run=' . urlencode($run_id) . '&source=' . urlencode($namespace);
55             $this->logger()->notice(dt('XHProf run saved. View report at !url', ['!url' => $url]));
56         }
57     }
58
59     /**
60      * Enable profiling via XHProf
61      *
62      * @hook init *
63      */
64     public function xhprofInitialize(InputInterface $input, AnnotationData $annotationData)
65     {
66         if (self::xhprofIsEnabled()) {
67             $config = Drush::config()->get('xh');
68             $flags = self::xhprofFlags($config);
69             self::xhprofEnable($flags);
70         }
71     }
72
73     public static function xhprofIsEnabled()
74     {
75         if (Drush::config()->get('xh.link')) {
76             if (!extension_loaded('xhprof') && !extension_loaded('tideways_xhprof')) {
77                 if (extension_loaded('tideways')) {
78                     throw new \Exception(dt('You are using an older incompatible version of the tideways extension. Please upgrade to the new tideways_xhprof extension.'));
79                 } else {
80                     throw new \Exception(dt('You must enable the xhprof or tideways_xhprof PHP extensions in your CLI PHP in order to profile.'));
81                 }
82             }
83             return true;
84         }
85         return false;
86     }
87
88     /**
89      * Determines flags.
90      *
91      * TODO: Make these work for Tideways as well.
92      */
93     public static function xhprofFlags(array $config)
94     {
95         $flags = 0;
96         if (!(isset($config['profile-builtins']) ? $config['profile-builtins']: self::XH_PROFILE_BUILTINS)) {
97             $flags |= XHPROF_FLAGS_NO_BUILTINS;
98         }
99         if (isset($config['profile-cpu']) ? $config['profile-cpu'] : self::XH_PROFILE_CPU) {
100             $flags |= XHPROF_FLAGS_CPU;
101         }
102         if (isset($config['profile-memory']) ? $config['profile-memory'] : self::XH_PROFILE_MEMORY) {
103             $flags |= XHPROF_FLAGS_MEMORY;
104         }
105         return $flags;
106     }
107
108     /**
109      * Enable profiling.
110      */
111     public static function xhprofEnable($flags)
112     {
113         if (extension_loaded('tideways_xhprof')) {
114             \tideways_xhprof_enable(TIDEWAYS_XHPROF_FLAGS_MEMORY | TIDEWAYS_XHPROF_FLAGS_CPU);
115         } else {
116             \xhprof_enable($flags);
117         }
118     }
119
120     /**
121      * Disable profiling and save results.
122      */
123     public function xhprofFinishRun($namespace)
124     {
125         if (extension_loaded('tideways_xhprof')) {
126             $data = \tideways_xhprof_disable();
127             $dir = $this->getConfig()->tmp();
128             $run_id = uniqid();
129             file_put_contents($dir . DIRECTORY_SEPARATOR . $run_id . '.' . $namespace . '.xhprof', serialize($data));
130             return $run_id;
131         } else {
132             $xhprof_data = \xhprof_disable();
133             $xhprof_runs = new \XHProfRuns_Default();
134             return $xhprof_runs->save_run($xhprof_data, $namespace);
135         }
136     }
137 }