@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Very rough cut of DarkConsole + XHProf

+2727 -59
+177
externals/xhprof/LICENSE
··· 1 + 2 + Apache License 3 + Version 2.0, January 2004 4 + http://www.apache.org/licenses/ 5 + 6 + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 + 8 + 1. Definitions. 9 + 10 + "License" shall mean the terms and conditions for use, reproduction, 11 + and distribution as defined by Sections 1 through 9 of this document. 12 + 13 + "Licensor" shall mean the copyright owner or entity authorized by 14 + the copyright owner that is granting the License. 15 + 16 + "Legal Entity" shall mean the union of the acting entity and all 17 + other entities that control, are controlled by, or are under common 18 + control with that entity. For the purposes of this definition, 19 + "control" means (i) the power, direct or indirect, to cause the 20 + direction or management of such entity, whether by contract or 21 + otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 + outstanding shares, or (iii) beneficial ownership of such entity. 23 + 24 + "You" (or "Your") shall mean an individual or Legal Entity 25 + exercising permissions granted by this License. 26 + 27 + "Source" form shall mean the preferred form for making modifications, 28 + including but not limited to software source code, documentation 29 + source, and configuration files. 30 + 31 + "Object" form shall mean any form resulting from mechanical 32 + transformation or translation of a Source form, including but 33 + not limited to compiled object code, generated documentation, 34 + and conversions to other media types. 35 + 36 + "Work" shall mean the work of authorship, whether in Source or 37 + Object form, made available under the License, as indicated by a 38 + copyright notice that is included in or attached to the work 39 + (an example is provided in the Appendix below). 40 + 41 + "Derivative Works" shall mean any work, whether in Source or Object 42 + form, that is based on (or derived from) the Work and for which the 43 + editorial revisions, annotations, elaborations, or other modifications 44 + represent, as a whole, an original work of authorship. For the purposes 45 + of this License, Derivative Works shall not include works that remain 46 + separable from, or merely link (or bind by name) to the interfaces of, 47 + the Work and Derivative Works thereof. 48 + 49 + "Contribution" shall mean any work of authorship, including 50 + the original version of the Work and any modifications or additions 51 + to that Work or Derivative Works thereof, that is intentionally 52 + submitted to Licensor for inclusion in the Work by the copyright owner 53 + or by an individual or Legal Entity authorized to submit on behalf of 54 + the copyright owner. For the purposes of this definition, "submitted" 55 + means any form of electronic, verbal, or written communication sent 56 + to the Licensor or its representatives, including but not limited to 57 + communication on electronic mailing lists, source code control systems, 58 + and issue tracking systems that are managed by, or on behalf of, the 59 + Licensor for the purpose of discussing and improving the Work, but 60 + excluding communication that is conspicuously marked or otherwise 61 + designated in writing by the copyright owner as "Not a Contribution." 62 + 63 + "Contributor" shall mean Licensor and any individual or Legal Entity 64 + on behalf of whom a Contribution has been received by Licensor and 65 + subsequently incorporated within the Work. 66 + 67 + 2. Grant of Copyright License. Subject to the terms and conditions of 68 + this License, each Contributor hereby grants to You a perpetual, 69 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 + copyright license to reproduce, prepare Derivative Works of, 71 + publicly display, publicly perform, sublicense, and distribute the 72 + Work and such Derivative Works in Source or Object form. 73 + 74 + 3. Grant of Patent License. Subject to the terms and conditions of 75 + this License, each Contributor hereby grants to You a perpetual, 76 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 + (except as stated in this section) patent license to make, have made, 78 + use, offer to sell, sell, import, and otherwise transfer the Work, 79 + where such license applies only to those patent claims licensable 80 + by such Contributor that are necessarily infringed by their 81 + Contribution(s) alone or by combination of their Contribution(s) 82 + with the Work to which such Contribution(s) was submitted. If You 83 + institute patent litigation against any entity (including a 84 + cross-claim or counterclaim in a lawsuit) alleging that the Work 85 + or a Contribution incorporated within the Work constitutes direct 86 + or contributory patent infringement, then any patent licenses 87 + granted to You under this License for that Work shall terminate 88 + as of the date such litigation is filed. 89 + 90 + 4. Redistribution. You may reproduce and distribute copies of the 91 + Work or Derivative Works thereof in any medium, with or without 92 + modifications, and in Source or Object form, provided that You 93 + meet the following conditions: 94 + 95 + (a) You must give any other recipients of the Work or 96 + Derivative Works a copy of this License; and 97 + 98 + (b) You must cause any modified files to carry prominent notices 99 + stating that You changed the files; and 100 + 101 + (c) You must retain, in the Source form of any Derivative Works 102 + that You distribute, all copyright, patent, trademark, and 103 + attribution notices from the Source form of the Work, 104 + excluding those notices that do not pertain to any part of 105 + the Derivative Works; and 106 + 107 + (d) If the Work includes a "NOTICE" text file as part of its 108 + distribution, then any Derivative Works that You distribute must 109 + include a readable copy of the attribution notices contained 110 + within such NOTICE file, excluding those notices that do not 111 + pertain to any part of the Derivative Works, in at least one 112 + of the following places: within a NOTICE text file distributed 113 + as part of the Derivative Works; within the Source form or 114 + documentation, if provided along with the Derivative Works; or, 115 + within a display generated by the Derivative Works, if and 116 + wherever such third-party notices normally appear. The contents 117 + of the NOTICE file are for informational purposes only and 118 + do not modify the License. You may add Your own attribution 119 + notices within Derivative Works that You distribute, alongside 120 + or as an addendum to the NOTICE text from the Work, provided 121 + that such additional attribution notices cannot be construed 122 + as modifying the License. 123 + 124 + You may add Your own copyright statement to Your modifications and 125 + may provide additional or different license terms and conditions 126 + for use, reproduction, or distribution of Your modifications, or 127 + for any such Derivative Works as a whole, provided Your use, 128 + reproduction, and distribution of the Work otherwise complies with 129 + the conditions stated in this License. 130 + 131 + 5. Submission of Contributions. Unless You explicitly state otherwise, 132 + any Contribution intentionally submitted for inclusion in the Work 133 + by You to the Licensor shall be under the terms and conditions of 134 + this License, without any additional terms or conditions. 135 + Notwithstanding the above, nothing herein shall supersede or modify 136 + the terms of any separate license agreement you may have executed 137 + with Licensor regarding such Contributions. 138 + 139 + 6. Trademarks. This License does not grant permission to use the trade 140 + names, trademarks, service marks, or product names of the Licensor, 141 + except as required for reasonable and customary use in describing the 142 + origin of the Work and reproducing the content of the NOTICE file. 143 + 144 + 7. Disclaimer of Warranty. Unless required by applicable law or 145 + agreed to in writing, Licensor provides the Work (and each 146 + Contributor provides its Contributions) on an "AS IS" BASIS, 147 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 + implied, including, without limitation, any warranties or conditions 149 + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 + PARTICULAR PURPOSE. You are solely responsible for determining the 151 + appropriateness of using or redistributing the Work and assume any 152 + risks associated with Your exercise of permissions under this License. 153 + 154 + 8. Limitation of Liability. In no event and under no legal theory, 155 + whether in tort (including negligence), contract, or otherwise, 156 + unless required by applicable law (such as deliberate and grossly 157 + negligent acts) or agreed to in writing, shall any Contributor be 158 + liable to You for damages, including any direct, indirect, special, 159 + incidental, or consequential damages of any character arising as a 160 + result of this License or out of the use or inability to use the 161 + Work (including but not limited to damages for loss of goodwill, 162 + work stoppage, computer failure or malfunction, or any and all 163 + other commercial damages or losses), even if such Contributor 164 + has been advised of the possibility of such damages. 165 + 166 + 9. Accepting Warranty or Additional Liability. While redistributing 167 + the Work or Derivative Works thereof, You may choose to offer, 168 + and charge a fee for, acceptance of support, warranty, indemnity, 169 + or other liability obligations and/or rights consistent with this 170 + License. However, in accepting such obligations, You may act only 171 + on Your own behalf and on Your sole responsibility, not on behalf 172 + of any other Contributor, and only if You agree to indemnify, 173 + defend, and hold each Contributor harmless for any liability 174 + incurred by, or claims asserted against, such Contributor by reason 175 + of your accepting any such warranty or additional liability. 176 + 177 + END OF TERMS AND CONDITIONS
+866
externals/xhprof/xhprof_lib.php
··· 1 + <?php 2 + // Copyright (c) 2009 Facebook 3 + // 4 + // Licensed under the Apache License, Version 2.0 (the "License"); 5 + // you may not use this file except in compliance with the License. 6 + // You may obtain a copy of the License at 7 + // 8 + // http://www.apache.org/licenses/LICENSE-2.0 9 + // 10 + // Unless required by applicable law or agreed to in writing, software 11 + // distributed under the License is distributed on an "AS IS" BASIS, 12 + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 + // See the License for the specific language governing permissions and 14 + // limitations under the License. 15 + // 16 + 17 + // 18 + // This file contains various XHProf library (utility) functions. 19 + // Do not add any display specific code here. 20 + // 21 + 22 + function xhprof_error($message) { 23 + error_log($message); 24 + } 25 + 26 + /* 27 + * The list of possible metrics collected as part of XHProf that 28 + * require inclusive/exclusive handling while reporting. 29 + * 30 + * @author Kannan 31 + */ 32 + function xhprof_get_possible_metrics() { 33 + static $possible_metrics = 34 + array("wt" => array("Wall", "microsecs", "walltime" ), 35 + "ut" => array("User", "microsecs", "user cpu time" ), 36 + "st" => array("Sys", "microsecs", "system cpu time"), 37 + "cpu" => array("Cpu", "microsecs", "cpu time"), 38 + "mu" => array("MUse", "bytes", "memory usage"), 39 + "pmu" => array("PMUse", "bytes", "peak memory usage"), 40 + "samples" => array("Samples", "samples", "cpu time")); 41 + return $possible_metrics; 42 + } 43 + 44 + /* 45 + * Get the list of metrics present in $xhprof_data as an array. 46 + * 47 + * @author Kannan 48 + */ 49 + function xhprof_get_metrics($xhprof_data) { 50 + 51 + // get list of valid metrics 52 + $possible_metrics = xhprof_get_possible_metrics(); 53 + 54 + // return those that are present in the raw data. 55 + // We'll just look at the root of the subtree for this. 56 + $metrics = array(); 57 + foreach ($possible_metrics as $metric => $desc) { 58 + if (isset($xhprof_data["main()"][$metric])) { 59 + $metrics[] = $metric; 60 + } 61 + } 62 + 63 + return $metrics; 64 + } 65 + 66 + /** 67 + * Takes a parent/child function name encoded as 68 + * "a==>b" and returns array("a", "b"). 69 + * 70 + * @author Kannan 71 + */ 72 + function xhprof_parse_parent_child($parent_child) { 73 + $ret = explode("==>", $parent_child); 74 + 75 + // Return if both parent and child are set 76 + if (isset($ret[1])) { 77 + return $ret; 78 + } 79 + 80 + return array(null, $ret[0]); 81 + } 82 + 83 + /** 84 + * Given parent & child function name, composes the key 85 + * in the format present in the raw data. 86 + * 87 + * @author Kannan 88 + */ 89 + function xhprof_build_parent_child_key($parent, $child) { 90 + if ($parent) { 91 + return $parent . "==>" . $child; 92 + } else { 93 + return $child; 94 + } 95 + } 96 + 97 + 98 + /** 99 + * Checks if XHProf raw data appears to be valid and not corrupted. 100 + * 101 + * @param int $run_id Run id of run to be pruned. 102 + * [Used only for reporting errors.] 103 + * @param array $raw_data XHProf raw data to be pruned 104 + * & validated. 105 + * 106 + * @return bool true on success, false on failure 107 + * 108 + * @author Kannan 109 + */ 110 + function xhprof_valid_run($run_id, $raw_data) { 111 + 112 + $main_info = $raw_data["main()"]; 113 + if (empty($main_info)) { 114 + xhprof_error("XHProf: main() missing in raw data for Run ID: $run_id"); 115 + return false; 116 + } 117 + 118 + // raw data should contain either wall time or samples information... 119 + if (isset($main_info["wt"])) { 120 + $metric = "wt"; 121 + } else if (isset($main_info["samples"])) { 122 + $metric = "samples"; 123 + } else { 124 + xhprof_error("XHProf: Wall Time information missing from Run ID: $run_id"); 125 + return false; 126 + } 127 + 128 + foreach ($raw_data as $info) { 129 + $val = $info[$metric]; 130 + 131 + // basic sanity checks... 132 + if ($val < 0) { 133 + xhprof_error("XHProf: $metric should not be negative: Run ID $run_id" 134 + . serialize($info)); 135 + return false; 136 + } 137 + if ($val > (86400000000)) { 138 + xhprof_error("XHProf: $metric > 1 day found in Run ID: $run_id " 139 + . serialize($info)); 140 + return false; 141 + } 142 + } 143 + return true; 144 + } 145 + 146 + 147 + /** 148 + * Return a trimmed version of the XHProf raw data. Note that the raw 149 + * data contains one entry for each unique parent/child function 150 + * combination.The trimmed version of raw data will only contain 151 + * entries where either the parent or child function is in the list 152 + * of $functions_to_keep. 153 + * 154 + * Note: Function main() is also always kept so that overall totals 155 + * can still be obtained from the trimmed version. 156 + * 157 + * @param array XHProf raw data 158 + * @param array array of function names 159 + * 160 + * @return array Trimmed XHProf Report 161 + * 162 + * @author Kannan 163 + */ 164 + function xhprof_trim_run($raw_data, $functions_to_keep) { 165 + 166 + // convert list of functions to a hash with function as the key 167 + $function_map = array_fill_keys($functions_to_keep, 1); 168 + 169 + // always keep main() as well so that overall totals can still 170 + // be computed if need be. 171 + $function_map['main()'] = 1; 172 + 173 + $new_raw_data = array(); 174 + foreach ($raw_data as $parent_child => $info) { 175 + list($parent, $child) = xhprof_parse_parent_child($parent_child); 176 + 177 + if (isset($function_map[$parent]) || isset($function_map[$child])) { 178 + $new_raw_data[$parent_child] = $info; 179 + } 180 + } 181 + 182 + return $new_raw_data; 183 + } 184 + 185 + /** 186 + * Takes raw XHProf data that was aggregated over "$num_runs" number 187 + * of runs averages/nomalizes the data. Essentially the various metrics 188 + * collected are divided by $num_runs. 189 + * 190 + * @author Kannan 191 + */ 192 + function xhprof_normalize_metrics($raw_data, $num_runs) { 193 + 194 + if (empty($raw_data) || ($num_runs == 0)) { 195 + return $raw_data; 196 + } 197 + 198 + $raw_data_total = array(); 199 + 200 + if (isset($raw_data["==>main()"]) && isset($raw_data["main()"])) { 201 + xhprof_error("XHProf Error: both ==>main() and main() set in raw data..."); 202 + } 203 + 204 + foreach ($raw_data as $parent_child => $info) { 205 + foreach ($info as $metric => $value) { 206 + $raw_data_total[$parent_child][$metric] = ($value / $num_runs); 207 + } 208 + } 209 + 210 + return $raw_data_total; 211 + } 212 + 213 + 214 + /** 215 + * Get raw data corresponding to specified array of runs 216 + * aggregated by certain weightage. 217 + * 218 + * Suppose you have run:5 corresponding to page1.php, 219 + * run:6 corresponding to page2.php, 220 + * and run:7 corresponding to page3.php 221 + * 222 + * and you want to accumulate these runs in a 2:4:1 ratio. You 223 + * can do so by calling: 224 + * 225 + * xhprof_aggregate_runs(array(5, 6, 7), array(2, 4, 1)); 226 + * 227 + * The above will return raw data for the runs aggregated 228 + * in 2:4:1 ratio. 229 + * 230 + * @param object $xhprof_runs_impl An object that implements 231 + * the iXHProfRuns interface 232 + * @param array $runs run ids of the XHProf runs.. 233 + * @param array $wts integral (ideally) weights for $runs 234 + * @param string $source source to fetch raw data for run from 235 + * @param bool $use_script_name If true, a fake edge from main() to 236 + * to __script::<scriptname> is introduced 237 + * in the raw data so that after aggregations 238 + * the script name is still preserved. 239 + * 240 + * @return array Return aggregated raw data 241 + * 242 + * @author Kannan 243 + */ 244 + function xhprof_aggregate_runs($xhprof_runs_impl, $runs, 245 + $wts, $source="phprof", 246 + $use_script_name=false) { 247 + 248 + $raw_data_total = null; 249 + $raw_data = null; 250 + $metrics = array(); 251 + 252 + $run_count = count($runs); 253 + $wts_count = count($wts); 254 + 255 + if (($run_count == 0) || 256 + (($wts_count > 0) && ($run_count != $wts_count))) { 257 + return array('description' => 'Invalid input..', 258 + 'raw' => null); 259 + } 260 + 261 + $bad_runs = array(); 262 + foreach($runs as $idx => $run_id) { 263 + 264 + $raw_data = $xhprof_runs_impl->get_run($run_id, $source, $description); 265 + 266 + // use the first run to derive what metrics to aggregate on. 267 + if ($idx == 0) { 268 + foreach ($raw_data["main()"] as $metric => $val) { 269 + if ($metric != "pmu") { 270 + // for now, just to keep data size small, skip "peak" memory usage 271 + // data while aggregating. 272 + // The "regular" memory usage data will still be tracked. 273 + if (isset($val)) { 274 + $metrics[] = $metric; 275 + } 276 + } 277 + } 278 + } 279 + 280 + if (!xhprof_valid_run($run_id, $raw_data)) { 281 + $bad_runs[] = $run_id; 282 + continue; 283 + } 284 + 285 + if ($use_script_name) { 286 + $page = $description; 287 + 288 + // create a fake function '__script::$page', and have and edge from 289 + // main() to '__script::$page'. We will also need edges to transfer 290 + // all edges originating from main() to now originate from 291 + // '__script::$page' to all function called from main(). 292 + // 293 + // We also weight main() ever so slightly higher so that 294 + // it shows up above the new entry in reports sorted by 295 + // inclusive metrics or call counts. 296 + if ($page) { 297 + foreach($raw_data["main()"] as $metric => $val) { 298 + $fake_edge[$metric] = $val; 299 + $new_main[$metric] = $val + 0.00001; 300 + } 301 + $raw_data["main()"] = $new_main; 302 + $raw_data[xhprof_build_parent_child_key("main()", 303 + "__script::$page")] 304 + = $fake_edge; 305 + } else { 306 + $use_script_name = false; 307 + } 308 + } 309 + 310 + // if no weights specified, use 1 as the default weightage.. 311 + $wt = ($wts_count == 0) ? 1 : $wts[$idx]; 312 + 313 + // aggregate $raw_data into $raw_data_total with appropriate weight ($wt) 314 + foreach ($raw_data as $parent_child => $info) { 315 + if ($use_script_name) { 316 + // if this is an old edge originating from main(), it now 317 + // needs to be from '__script::$page' 318 + if (substr($parent_child, 0, 9) == "main()==>") { 319 + $child =substr($parent_child, 9); 320 + // ignore the newly added edge from main() 321 + if (substr($child, 0, 10) != "__script::") { 322 + $parent_child = xhprof_build_parent_child_key("__script::$page", 323 + $child); 324 + } 325 + } 326 + } 327 + 328 + if (!isset($raw_data_total[$parent_child])) { 329 + foreach ($metrics as $metric) { 330 + $raw_data_total[$parent_child][$metric] = ($wt * $info[$metric]); 331 + } 332 + } else { 333 + foreach ($metrics as $metric) { 334 + $raw_data_total[$parent_child][$metric] += ($wt * $info[$metric]); 335 + } 336 + } 337 + } 338 + } 339 + 340 + $runs_string = implode(",", $runs); 341 + 342 + if (isset($wts)) { 343 + $wts_string = "in the ratio (" . implode(":", $wts) . ")"; 344 + $normalization_count = array_sum($wts); 345 + } else { 346 + $wts_string = ""; 347 + $normalization_count = $run_count; 348 + } 349 + 350 + $run_count = $run_count - count($bad_runs); 351 + 352 + $data['description'] = "Aggregated Report for $run_count runs: ". 353 + "$runs_string $wts_string\n"; 354 + $data['raw'] = xhprof_normalize_metrics($raw_data_total, 355 + $normalization_count); 356 + $data['bad_runs'] = $bad_runs; 357 + 358 + return $data; 359 + } 360 + 361 + 362 + /** 363 + * Analyze hierarchical raw data, and compute per-function (flat) 364 + * inclusive and exclusive metrics. 365 + * 366 + * Also, store overall totals in the 2nd argument. 367 + * 368 + * @param array $raw_data XHProf format raw profiler data. 369 + * @param array &$overall_totals OUT argument for returning 370 + * overall totals for various 371 + * metrics. 372 + * @return array Returns a map from function name to its 373 + * call count and inclusive & exclusive metrics 374 + * (such as wall time, etc.). 375 + * 376 + * @author Kannan Muthukkaruppan 377 + */ 378 + function xhprof_compute_flat_info($raw_data, &$overall_totals) { 379 + 380 + global $display_calls; 381 + 382 + $metrics = xhprof_get_metrics($raw_data); 383 + 384 + $overall_totals = array( "ct" => 0, 385 + "wt" => 0, 386 + "ut" => 0, 387 + "st" => 0, 388 + "cpu" => 0, 389 + "mu" => 0, 390 + "pmu" => 0, 391 + "samples" => 0 392 + ); 393 + 394 + // compute inclusive times for each function 395 + $symbol_tab = xhprof_compute_inclusive_times($raw_data); 396 + 397 + /* total metric value is the metric value for "main()" */ 398 + foreach ($metrics as $metric) { 399 + $overall_totals[$metric] = $symbol_tab["main()"][$metric]; 400 + } 401 + 402 + /* 403 + * initialize exclusive (self) metric value to inclusive metric value 404 + * to start with. 405 + * In the same pass, also add up the total number of function calls. 406 + */ 407 + foreach ($symbol_tab as $symbol => $info) { 408 + foreach ($metrics as $metric) { 409 + $symbol_tab[$symbol]["excl_" . $metric] = $symbol_tab[$symbol][$metric]; 410 + } 411 + if ($display_calls) { 412 + /* keep track of total number of calls */ 413 + $overall_totals["ct"] += $info["ct"]; 414 + } 415 + } 416 + 417 + /* adjust exclusive times by deducting inclusive time of children */ 418 + foreach ($raw_data as $parent_child => $info) { 419 + list($parent, $child) = xhprof_parse_parent_child($parent_child); 420 + 421 + if ($parent) { 422 + foreach ($metrics as $metric) { 423 + // make sure the parent exists hasn't been pruned. 424 + if (isset($symbol_tab[$parent])) { 425 + $symbol_tab[$parent]["excl_" . $metric] -= $info[$metric]; 426 + } 427 + } 428 + } 429 + } 430 + 431 + return $symbol_tab; 432 + } 433 + 434 + /** 435 + * Hierarchical diff: 436 + * Compute and return difference of two call graphs: Run2 - Run1. 437 + * 438 + * @author Kannan 439 + */ 440 + function xhprof_compute_diff($xhprof_data1, $xhprof_data2) { 441 + global $display_calls; 442 + 443 + // use the second run to decide what metrics we will do the diff on 444 + $metrics = xhprof_get_metrics($xhprof_data2); 445 + 446 + $xhprof_delta = $xhprof_data2; 447 + 448 + foreach ($xhprof_data1 as $parent_child => $info) { 449 + 450 + if (!isset($xhprof_delta[$parent_child])) { 451 + 452 + // this pc combination was not present in run1; 453 + // initialize all values to zero. 454 + if ($display_calls) { 455 + $xhprof_delta[$parent_child] = array("ct" => 0); 456 + } else { 457 + $xhprof_delta[$parent_child] = array(); 458 + } 459 + foreach ($metrics as $metric) { 460 + $xhprof_delta[$parent_child][$metric] = 0; 461 + } 462 + } 463 + 464 + if ($display_calls) { 465 + $xhprof_delta[$parent_child]["ct"] -= $info["ct"]; 466 + } 467 + 468 + foreach ($metrics as $metric) { 469 + $xhprof_delta[$parent_child][$metric] -= $info[$metric]; 470 + } 471 + } 472 + 473 + return $xhprof_delta; 474 + } 475 + 476 + 477 + /** 478 + * Compute inclusive metrics for function. This code was factored out 479 + * of xhprof_compute_flat_info(). 480 + * 481 + * The raw data contains inclusive metrics of a function for each 482 + * unique parent function it is called from. The total inclusive metrics 483 + * for a function is therefore the sum of inclusive metrics for the 484 + * function across all parents. 485 + * 486 + * @return array Returns a map of function name to total (across all parents) 487 + * inclusive metrics for the function. 488 + * 489 + * @author Kannan 490 + */ 491 + function xhprof_compute_inclusive_times($raw_data) { 492 + global $display_calls; 493 + 494 + $metrics = xhprof_get_metrics($raw_data); 495 + 496 + $symbol_tab = array(); 497 + 498 + /* 499 + * First compute inclusive time for each function and total 500 + * call count for each function across all parents the 501 + * function is called from. 502 + */ 503 + foreach ($raw_data as $parent_child => $info) { 504 + 505 + list($parent, $child) = xhprof_parse_parent_child($parent_child); 506 + 507 + if ($parent == $child) { 508 + /* 509 + * XHProf PHP extension should never trigger this situation any more. 510 + * Recursion is handled in the XHProf PHP extension by giving nested 511 + * calls a unique recursion-depth appended name (for example, foo@1). 512 + */ 513 + xhprof_error("Error in Raw Data: parent & child are both: $parent"); 514 + return; 515 + } 516 + 517 + if (!isset($symbol_tab[$child])) { 518 + 519 + if ($display_calls) { 520 + $symbol_tab[$child] = array("ct" => $info["ct"]); 521 + } else { 522 + $symbol_tab[$child] = array(); 523 + } 524 + foreach ($metrics as $metric) { 525 + $symbol_tab[$child][$metric] = $info[$metric]; 526 + } 527 + } else { 528 + if ($display_calls) { 529 + /* increment call count for this child */ 530 + $symbol_tab[$child]["ct"] += $info["ct"]; 531 + } 532 + 533 + /* update inclusive times/metric for this child */ 534 + foreach ($metrics as $metric) { 535 + $symbol_tab[$child][$metric] += $info[$metric]; 536 + } 537 + } 538 + } 539 + 540 + return $symbol_tab; 541 + } 542 + 543 + 544 + /* 545 + * Prunes XHProf raw data: 546 + * 547 + * Any node whose inclusive walltime accounts for less than $prune_percent 548 + * of total walltime is pruned. [It is possible that a child function isn't 549 + * pruned, but one or more of its parents get pruned. In such cases, when 550 + * viewing the child function's hierarchical information, the cost due to 551 + * the pruned parent(s) will be attributed to a special function/symbol 552 + * "__pruned__()".] 553 + * 554 + * @param array $raw_data XHProf raw data to be pruned & validated. 555 + * @param double $prune_percent Any edges that account for less than 556 + * $prune_percent of time will be pruned 557 + * from the raw data. 558 + * 559 + * @return array Returns the pruned raw data. 560 + * 561 + * @author Kannan 562 + */ 563 + function xhprof_prune_run($raw_data, $prune_percent) { 564 + 565 + $main_info = $raw_data["main()"]; 566 + if (empty($main_info)) { 567 + xhprof_error("XHProf: main() missing in raw data"); 568 + return false; 569 + } 570 + 571 + // raw data should contain either wall time or samples information... 572 + if (isset($main_info["wt"])) { 573 + $prune_metric = "wt"; 574 + } else if (isset($main_info["samples"])) { 575 + $prune_metric = "samples"; 576 + } else { 577 + xhprof_error("XHProf: for main() we must have either wt " 578 + ."or samples attribute set"); 579 + return false; 580 + } 581 + 582 + // determine the metrics present in the raw data.. 583 + $metrics = array(); 584 + foreach ($main_info as $metric => $val) { 585 + if (isset($val)) { 586 + $metrics[] = $metric; 587 + } 588 + } 589 + 590 + $prune_threshold = (($main_info[$prune_metric] * $prune_percent) / 100.0); 591 + 592 + init_metrics($raw_data, null, null, false); 593 + $flat_info = xhprof_compute_inclusive_times($raw_data); 594 + 595 + foreach ($raw_data as $parent_child => $info) { 596 + 597 + list($parent, $child) = xhprof_parse_parent_child($parent_child); 598 + 599 + // is this child's overall total from all parents less than threshold? 600 + if ($flat_info[$child][$prune_metric] < $prune_threshold) { 601 + unset($raw_data[$parent_child]); // prune the edge 602 + } else if ($parent && 603 + ($parent != "__pruned__()") && 604 + ($flat_info[$parent][$prune_metric] < $prune_threshold)) { 605 + 606 + // Parent's overall inclusive metric is less than a threshold. 607 + // All edges to the parent node will get nuked, and this child will 608 + // be a dangling child. 609 + // So instead change its parent to be a special function __pruned__(). 610 + $pruned_edge = xhprof_build_parent_child_key("__pruned__()", $child); 611 + 612 + if (isset($raw_data[$pruned_edge])) { 613 + foreach ($metrics as $metric) { 614 + $raw_data[$pruned_edge][$metric]+=$raw_data[$parent_child][$metric]; 615 + } 616 + } else { 617 + $raw_data[$pruned_edge] = $raw_data[$parent_child]; 618 + } 619 + 620 + unset($raw_data[$parent_child]); // prune the edge 621 + } 622 + } 623 + 624 + return $raw_data; 625 + } 626 + 627 + 628 + /** 629 + * Set one key in an array and return the array 630 + * 631 + * @author Kannan 632 + */ 633 + function xhprof_array_set($arr, $k, $v) { 634 + $arr[$k] = $v; 635 + return $arr; 636 + } 637 + 638 + /** 639 + * Removes/unsets one key in an array and return the array 640 + * 641 + * @author Kannan 642 + */ 643 + function xhprof_array_unset($arr, $k) { 644 + unset($arr[$k]); 645 + return $arr; 646 + } 647 + 648 + /** 649 + * Type definitions for URL params 650 + */ 651 + define('XHPROF_STRING_PARAM', 1); 652 + define('XHPROF_UINT_PARAM', 2); 653 + define('XHPROF_FLOAT_PARAM', 3); 654 + define('XHPROF_BOOL_PARAM', 4); 655 + 656 + 657 + /** 658 + * Internal helper function used by various 659 + * xhprof_get_param* flavors for various 660 + * types of parameters. 661 + * 662 + * @param string name of the URL query string param 663 + * 664 + * @author Kannan 665 + */ 666 + function xhprof_get_param_helper($param) { 667 + $val = null; 668 + if (isset($_GET[$param])) 669 + $val = $_GET[$param]; 670 + else if (isset($_POST[$param])) { 671 + $val = $_POST[$param]; 672 + } 673 + return $val; 674 + } 675 + 676 + /** 677 + * Extracts value for string param $param from query 678 + * string. If param is not specified, return the 679 + * $default value. 680 + * 681 + * @author Kannan 682 + */ 683 + function xhprof_get_string_param($param, $default = '') { 684 + $val = xhprof_get_param_helper($param); 685 + 686 + if ($val === null) 687 + return $default; 688 + 689 + return $val; 690 + } 691 + 692 + /** 693 + * Extracts value for unsigned integer param $param from 694 + * query string. If param is not specified, return the 695 + * $default value. 696 + * 697 + * If value is not a valid unsigned integer, logs error 698 + * and returns null. 699 + * 700 + * @author Kannan 701 + */ 702 + function xhprof_get_uint_param($param, $default = 0) { 703 + $val = xhprof_get_param_helper($param); 704 + 705 + if ($val === null) 706 + $val = $default; 707 + 708 + // trim leading/trailing whitespace 709 + $val = trim($val); 710 + 711 + // if it only contains digits, then ok.. 712 + if (ctype_digit($val)) { 713 + return $val; 714 + } 715 + 716 + xhprof_error("$param is $val. It must be an unsigned integer."); 717 + return null; 718 + } 719 + 720 + 721 + /** 722 + * Extracts value for a float param $param from 723 + * query string. If param is not specified, return 724 + * the $default value. 725 + * 726 + * If value is not a valid unsigned integer, logs error 727 + * and returns null. 728 + * 729 + * @author Kannan 730 + */ 731 + function xhprof_get_float_param($param, $default = 0) { 732 + $val = xhprof_get_param_helper($param); 733 + 734 + if ($val === null) 735 + $val = $default; 736 + 737 + // trim leading/trailing whitespace 738 + $val = trim($val); 739 + 740 + // TBD: confirm the value is indeed a float. 741 + if (true) // for now.. 742 + return (float)$val; 743 + 744 + xhprof_error("$param is $val. It must be a float."); 745 + return null; 746 + } 747 + 748 + /** 749 + * Extracts value for a boolean param $param from 750 + * query string. If param is not specified, return 751 + * the $default value. 752 + * 753 + * If value is not a valid unsigned integer, logs error 754 + * and returns null. 755 + * 756 + * @author Kannan 757 + */ 758 + function xhprof_get_bool_param($param, $default = false) { 759 + $val = xhprof_get_param_helper($param); 760 + 761 + if ($val === null) 762 + $val = $default; 763 + 764 + // trim leading/trailing whitespace 765 + $val = trim($val); 766 + 767 + switch (strtolower($val)) { 768 + case '0': 769 + case '1': 770 + $val = (bool)$val; 771 + break; 772 + case 'true': 773 + case 'on': 774 + case 'yes': 775 + $val = true; 776 + break; 777 + case 'false': 778 + case 'off': 779 + case 'no': 780 + $val = false; 781 + break; 782 + default: 783 + xhprof_error("$param is $val. It must be a valid boolean string."); 784 + return null; 785 + } 786 + 787 + return $val; 788 + 789 + } 790 + 791 + /** 792 + * Initialize params from URL query string. The function 793 + * creates globals variables for each of the params 794 + * and if the URL query string doesn't specify a particular 795 + * param initializes them with the corresponding default 796 + * value specified in the input. 797 + * 798 + * @params array $params An array whose keys are the names 799 + * of URL params who value needs to 800 + * be retrieved from the URL query 801 + * string. PHP globals are created 802 + * with these names. The value is 803 + * itself an array with 2-elems (the 804 + * param type, and its default value). 805 + * If a param is not specified in the 806 + * query string the default value is 807 + * used. 808 + * @author Kannan 809 + */ 810 + function xhprof_param_init($params) { 811 + /* Create variables specified in $params keys, init defaults */ 812 + foreach ($params as $k => $v) { 813 + switch ($v[0]) { 814 + case XHPROF_STRING_PARAM: 815 + $p = xhprof_get_string_param($k, $v[1]); 816 + break; 817 + case XHPROF_UINT_PARAM: 818 + $p = xhprof_get_uint_param($k, $v[1]); 819 + break; 820 + case XHPROF_FLOAT_PARAM: 821 + $p = xhprof_get_float_param($k, $v[1]); 822 + break; 823 + case XHPROF_BOOL_PARAM: 824 + $p = xhprof_get_bool_param($k, $v[1]); 825 + break; 826 + default: 827 + xhprof_error("Invalid param type passed to xhprof_param_init: " 828 + . $v[0]); 829 + exit(); 830 + } 831 + 832 + // create a global variable using the parameter name. 833 + $GLOBALS[$k] = $p; 834 + } 835 + } 836 + 837 + 838 + /** 839 + * Given a partial query string $q return matching function names in 840 + * specified XHProf run. This is used for the type ahead function 841 + * selector. 842 + * 843 + * @author Kannan 844 + */ 845 + function xhprof_get_matching_functions($q, $xhprof_data) { 846 + 847 + $matches = array(); 848 + 849 + foreach ($xhprof_data as $parent_child => $info) { 850 + list($parent, $child) = xhprof_parse_parent_child($parent_child); 851 + if (stripos($parent, $q) !== false) { 852 + $matches[$parent] = 1; 853 + } 854 + if (stripos($child, $q) !== false) { 855 + $matches[$child] = 1; 856 + } 857 + } 858 + 859 + $res = array_keys($matches); 860 + 861 + // sort it so the answers are in some reliable order... 862 + asort($res); 863 + 864 + return ($res); 865 + } 866 +
+33 -15
src/__celerity_resource_map__.php
··· 7 7 */ 8 8 9 9 celerity_register_resource_map(array( 10 + 'aphront-dark-console-css' => 11 + array( 12 + 'uri' => '/res/ac3fc983/rsrc/css/aphront/dark-console.css', 13 + 'type' => 'css', 14 + 'requires' => 15 + array( 16 + ), 17 + 'disk' => '/rsrc/css/aphront/dark-console.css', 18 + ), 10 19 'aphront-dialog-view-css' => 11 20 array( 12 21 'uri' => '/res/a05107ae/rsrc/css/aphront/dialog-view.css', ··· 54 63 ), 55 64 'aphront-table-view-css' => 56 65 array( 57 - 'uri' => '/res/52b0191f/rsrc/css/aphront/table-view.css', 66 + 'uri' => '/res/de3a1e4c/rsrc/css/aphront/table-view.css', 58 67 'type' => 'css', 59 68 'requires' => 60 69 array( ··· 215 224 ), 216 225 'disk' => '/rsrc/css/core/syntax.css', 217 226 ), 227 + 'javelin-behavior-dark-console' => 228 + array( 229 + 'uri' => '/res/453503f4/rsrc/js/application/core/behavior-dark-console.js', 230 + 'type' => 'js', 231 + 'requires' => 232 + array( 233 + ), 234 + 'disk' => '/rsrc/js/application/core/behavior-dark-console.js', 235 + ), 218 236 'javelin-behavior-aphront-basic-tokenizer' => 219 237 array( 220 238 'uri' => '/res/8317d761/rsrc/js/application/core/behavior-tokenizer.js', ··· 237 255 ), 238 256 'javelin-behavior-differential-edit-inline-comments' => 239 257 array( 240 - 'uri' => '/res/be5ed33e/rsrc/js/application/differential/behavior-edit-inline-comments.js', 258 + 'uri' => '/res/f5b54891/rsrc/js/application/differential/behavior-edit-inline-comments.js', 241 259 'type' => 'js', 242 260 'requires' => 243 261 array( ··· 340 358 ), array ( 341 359 'packages' => 342 360 array ( 343 - '4bb7e37f' => 361 + 'c5efa388' => 344 362 array ( 345 363 'name' => 'core.pkg.css', 346 364 'symbols' => ··· 357 375 9 => 'aphront-typeahead-control-css', 358 376 10 => 'phabricator-directory-css', 359 377 ), 360 - 'uri' => '/res/pkg/4bb7e37f/core.pkg.css', 378 + 'uri' => '/res/pkg/c5efa388/core.pkg.css', 361 379 'type' => 'css', 362 380 ), 363 381 'f399aad7' => ··· 377 395 ), 378 396 'reverse' => 379 397 array ( 380 - 'phabricator-core-css' => '4bb7e37f', 381 - 'phabricator-core-buttons-css' => '4bb7e37f', 382 - 'phabricator-standard-page-view' => '4bb7e37f', 383 - 'aphront-dialog-view-css' => '4bb7e37f', 384 - 'aphront-form-view-css' => '4bb7e37f', 385 - 'aphront-panel-view-css' => '4bb7e37f', 386 - 'aphront-side-nav-view-css' => '4bb7e37f', 387 - 'aphront-table-view-css' => '4bb7e37f', 388 - 'aphront-tokenizer-control-css' => '4bb7e37f', 389 - 'aphront-typeahead-control-css' => '4bb7e37f', 390 - 'phabricator-directory-css' => '4bb7e37f', 398 + 'phabricator-core-css' => 'c5efa388', 399 + 'phabricator-core-buttons-css' => 'c5efa388', 400 + 'phabricator-standard-page-view' => 'c5efa388', 401 + 'aphront-dialog-view-css' => 'c5efa388', 402 + 'aphront-form-view-css' => 'c5efa388', 403 + 'aphront-panel-view-css' => 'c5efa388', 404 + 'aphront-side-nav-view-css' => 'c5efa388', 405 + 'aphront-table-view-css' => 'c5efa388', 406 + 'aphront-tokenizer-control-css' => 'c5efa388', 407 + 'aphront-typeahead-control-css' => 'c5efa388', 408 + 'phabricator-directory-css' => 'c5efa388', 391 409 'differential-core-view-css' => 'f399aad7', 392 410 'differential-changeset-view-css' => 'f399aad7', 393 411 'differential-revision-detail-css' => 'f399aad7',
+22
src/__phutil_library_map__.php
··· 68 68 'ConduitAPI_file_upload_Method' => 'applications/conduit/method/file/upload', 69 69 'ConduitAPI_user_find_Method' => 'applications/conduit/method/user/find', 70 70 'ConduitException' => 'applications/conduit/protocol/exception', 71 + 'DarkConsole' => 'aphront/console/api', 72 + 'DarkConsoleController' => 'aphront/console/controller', 73 + 'DarkConsoleCore' => 'aphront/console/core', 74 + 'DarkConsoleErrorLogPlugin' => 'aphront/console/plugin/errorlog', 75 + 'DarkConsolePlugin' => 'aphront/console/plugin/base', 76 + 'DarkConsoleRequestPlugin' => 'aphront/console/plugin/request', 77 + 'DarkConsoleServicesPlugin' => 'aphront/console/plugin/services', 78 + 'DarkConsoleXHProfPlugin' => 'aphront/console/plugin/xhprof', 79 + 'DarkConsoleXHProfPluginAPI' => 'aphront/console/plugin/xhprof/api', 71 80 'DifferentialAction' => 'applications/differential/constants/action', 72 81 'DifferentialAddCommentView' => 'applications/differential/view/addcomment', 73 82 'DifferentialCCWelcomeMail' => 'applications/differential/mail/ccwelcome', ··· 181 190 'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/base', 182 191 'PhabricatorUser' => 'applications/people/storage/user', 183 192 'PhabricatorUserDAO' => 'applications/people/storage/base', 193 + 'PhabricatorXHProfController' => 'applications/xhprof/controller/base', 194 + 'PhabricatorXHProfProfileController' => 'applications/xhprof/controller/profile', 195 + 'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/symbol', 196 + 'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/toplevel', 184 197 ), 185 198 'function' => 186 199 array( ··· 249 262 'ConduitAPI_differential_setdiffproperty_Method' => 'ConduitAPIMethod', 250 263 'ConduitAPI_file_upload_Method' => 'ConduitAPIMethod', 251 264 'ConduitAPI_user_find_Method' => 'ConduitAPIMethod', 265 + 'DarkConsoleController' => 'AliteController', 266 + 'DarkConsoleErrorLogPlugin' => 'DarkConsolePlugin', 267 + 'DarkConsoleRequestPlugin' => 'DarkConsolePlugin', 268 + 'DarkConsoleServicesPlugin' => 'DarkConsolePlugin', 269 + 'DarkConsoleXHProfPlugin' => 'DarkConsolePlugin', 252 270 'DifferentialAddCommentView' => 'AphrontView', 253 271 'DifferentialCCWelcomeMail' => 'DifferentialReviewRequestMail', 254 272 'DifferentialChangeset' => 'DifferentialDAO', ··· 343 361 'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController', 344 362 'PhabricatorUser' => 'PhabricatorUserDAO', 345 363 'PhabricatorUserDAO' => 'PhabricatorLiskDAO', 364 + 'PhabricatorXHProfController' => 'PhabricatorController', 365 + 'PhabricatorXHProfProfileController' => 'PhabricatorXHProfController', 366 + 'PhabricatorXHProfProfileSymbolView' => 'AphrontView', 367 + 'PhabricatorXHProfProfileTopLevelView' => 'AphrontView', 346 368 ), 347 369 'requires_interface' => 348 370 array(
+9
src/aphront/applicationconfiguration/AphrontApplicationConfiguration.php
··· 24 24 private $request; 25 25 private $host; 26 26 private $path; 27 + private $console; 27 28 28 29 abstract public function getApplicationName(); 29 30 abstract public function getURIMap(); ··· 37 38 38 39 final public function getRequest() { 39 40 return $this->request; 41 + } 42 + 43 + final public function getConsole() { 44 + return $this->console; 40 45 } 41 46 42 47 final public function buildController() { ··· 72 77 73 78 final public function getPath() { 74 79 return $this->path; 80 + } 81 + 82 + final public function willBuildRequest() { 83 + $this->console = new DarkConsoleCore(); 75 84 } 76 85 77 86 }
+1
src/aphront/applicationconfiguration/__init__.php
··· 6 6 7 7 8 8 9 + phutil_require_module('phabricator', 'aphront/console/core'); 9 10 phutil_require_module('phabricator', 'aphront/mapper'); 10 11 11 12 phutil_require_module('phutil', 'symbols');
+21
src/aphront/console/api/DarkConsole.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + class DarkConsole { 20 + 21 + }
+10
src/aphront/console/api/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + 10 + phutil_require_source('DarkConsole.php');
+100
src/aphront/console/controller/DarkConsoleController.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + class DarkConsoleController extends AliteController { 20 + 21 + protected $op; 22 + protected $data; 23 + 24 + public function __construct(AliteRequest $request, array $params) { 25 + parent::__construct($request); 26 + 27 + validate_parameter_list( 28 + $params, 29 + array( 30 + ), 31 + $ops = array( 32 + 'tab' => true, 33 + 'toggle' => true, 34 + 'visible' => true, 35 + 'plugin' => true, 36 + 37 + 'etc' => true, 38 + )); 39 + 40 + foreach (array_keys($ops) as $op) { 41 + if (isset($params[$op])) { 42 + $this->op = $op; 43 + break; 44 + } 45 + } 46 + $this->data = $params; 47 + } 48 + 49 + public function getShortControllerName() { 50 + return 'DarkConsole'; 51 + } 52 + 53 + public function shouldPreflush() { 54 + return false; 55 + } 56 + 57 + public function process() { 58 + $request = $this->getRequest(); 59 + 60 + if (!$this->op) { 61 + $this->op = 'toggle'; 62 + } 63 + 64 + $coredata = $request->getCoreData(); 65 + $console = $coredata->getConsole(); 66 + 67 + if ($request->isAsync()) { 68 + $return = null; 69 + } else { 70 + $return = '/'; 71 + } 72 + 73 + 74 + switch ($this->op) { 75 + case 'toggle': 76 + $enabled = $coredata->didToggleDarkConsole(); 77 + if ($enabled) { 78 + if (!$console) { 79 + $console = new DarkConsoleCore($coredata); 80 + } 81 + $console->setConsoleSetting( 82 + DarkConsoleCore::SETTING_VISIBLE, 83 + true); 84 + } 85 + break; 86 + case 'tab': 87 + $console->setConsoleSetting( 88 + DarkConsoleCore::SETTING_TAB, 89 + $request->getStr('tab')); 90 + break; 91 + case 'visible': 92 + $console->setConsoleSetting( 93 + DarkConsoleCore::SETTING_VISIBLE, 94 + !$console->getConsoleSetting(DarkConsoleCore::SETTING_VISIBLE)); 95 + break; 96 + } 97 + // return <alite:redirect uri={$return} />; 98 + } 99 + 100 + }
+12
src/aphront/console/controller/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'aphront/console/core'); 10 + 11 + 12 + phutil_require_source('DarkConsoleController.php');
+186
src/aphront/console/core/DarkConsoleCore.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + final class DarkConsoleCore { 20 + 21 + const PLUGIN_ERRORLOG = 'ErrorLog'; 22 + const PLUGIN_SERVICES = 'Services'; 23 + const PLUGIN_XHPROF = 'XHProf'; 24 + const PLUGIN_REQUEST = 'Request'; 25 + 26 + public static function getPlugins() { 27 + return array( 28 + self::PLUGIN_ERRORLOG, 29 + self::PLUGIN_REQUEST, 30 + self::PLUGIN_SERVICES, 31 + self::PLUGIN_XHPROF, 32 + ); 33 + } 34 + 35 + private $plugins = array(); 36 + private $settings; 37 + private $coredata; 38 + 39 + public function setConsoleSetting($key, $value) { 40 + /* 41 + $guard = new WriteOnHttpGet(); 42 + $okay = user_set_pref( 43 + $this->getCoreData()->getViewerContext()->getUserID(), 44 + self::APPLICATION_ID, 45 + $key, 46 + $value); 47 + $guard->release(); 48 + if (!$okay) { 49 + throw new Exception('Failed to set preference setting.'); 50 + } 51 + */ 52 + } 53 + 54 + public function getConsoleSetting($key) { 55 + // $viewer_id = $this->getCoreData()->getViewerContext()->getUserID(); 56 + // return idx(idx($this->settings[$viewer_id], $key), 'value'); 57 + return true; 58 + } 59 + 60 + public function getPlugin($plugin_name) { 61 + return idx($this->plugins, $plugin_name); 62 + } 63 + 64 + public function __construct() { 65 + 66 + /* 67 + $this->settings = users_multiget_prefs_info( 68 + array($coredata->getViewerContext()->getUserID()), 69 + self::APPLICATION_ID); 70 + 71 + $disabled = $this->getConsoleSetting(self::SETTING_PLUGINS); 72 + $disabled = array_flip(explode(',', $disabled)); 73 + */ 74 + foreach (self::getPlugins() as $plugin_name) { 75 + $plugin = self::newPlugin($plugin_name); 76 + if ($plugin->isPermanent() || !isset($disabled[$plugin_name])) { 77 + if ($plugin->shouldStartup()) { 78 + $plugin->didStartup(); 79 + $plugin->setConsoleCore($this); 80 + $this->plugins[$plugin_name] = $plugin; 81 + } 82 + } 83 + } 84 + } 85 + 86 + public static function newPlugin($plugin) { 87 + $class = 'DarkConsole'.$plugin.'Plugin'; 88 + PhutilSymbolLoader::loadClass($class); 89 + return newv($class, array()); 90 + } 91 + 92 + public function getEnabledPlugins() { 93 + return $this->plugins; 94 + } 95 + 96 + public function render(AphrontRequest $request) { 97 + 98 + $plugins = $this->getEnabledPlugins(); 99 + 100 + foreach ($plugins as $plugin) { 101 + $plugin->setRequest($request); 102 + $plugin->willShutdown(); 103 + } 104 + 105 + foreach ($plugins as $plugin) { 106 + $plugin->didShutdown(); 107 + } 108 + 109 + foreach ($plugins as $plugin) { 110 + $plugin->setData($plugin->generateData()); 111 + } 112 + 113 + $selected = 'XHProf';//true;//$this->getConsoleSetting(DarkConsoleCore::SETTING_TAB); 114 + $visible = true;//$this->getConsoleSetting(DarkConsoleCore::SETTING_VISIBLE); 115 + 116 + if (!isset($plugins[$selected])) { 117 + $selected = key($plugins); 118 + } 119 + 120 + $tabs = array(); 121 + foreach ($plugins as $key => $plugin) { 122 + $tabs[$key] = array( 123 + 'name' => $plugin->getName(), 124 + 'panel' => $plugin->render(), 125 + ); 126 + } 127 + 128 + $tabs_markup = array(); 129 + $panel_markup = array(); 130 + foreach ($tabs as $key => $data) { 131 + $is_selected = ($key == $selected); 132 + if ($is_selected) { 133 + $style = null; 134 + $tabclass = 'dark-console-tab-selected'; 135 + } else { 136 + $style = 'display: none;'; 137 + $tabclass = null; 138 + } 139 + 140 + $tabs_markup[] = javelin_render_tag( 141 + 'a', 142 + array( 143 + 'class' => "dark-console-tab {$tabclass}", 144 + 'sigil' => 'dark-console-tab', 145 + 'meta' => array( 146 + 'key' => $key, 147 + ), 148 + ), 149 + (string)$data['name']); 150 + 151 + $panel_markup[] = javelin_render_tag( 152 + 'div', 153 + array( 154 + 'class' => 'dark-console-panel', 155 + 'style' => $style, 156 + 'sigil' => 'dark-console-panel', 157 + 'meta' => array( 158 + 'key' => $key, 159 + ), 160 + ), 161 + (string)$data['panel']); 162 + } 163 + 164 + $console = javelin_render_tag( 165 + 'table', 166 + array( 167 + 'class' => 'dark-console', 168 + 'sigil' => 'dark-console', 169 + 'meta' => array( 170 + 'visible' => true, 171 + ), 172 + 'style' => '', 173 + ), 174 + '<tr>'. 175 + '<th class="dark-console-tabs">'. 176 + implode("\n", $tabs_markup). 177 + '</th>'. 178 + '<td>'.implode("\n", $panel_markup).'</td>'. 179 + '</tr>'); 180 + 181 + Javelin::initBehavior('dark-console'); 182 + 183 + return "\n\n\n\n".$console."\n\n\n\n"; 184 + } 185 + } 186 +
+16
src/aphront/console/core/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'infrastructure/javelin/api'); 10 + phutil_require_module('phabricator', 'infrastructure/javelin/markup'); 11 + 12 + phutil_require_module('phutil', 'symbols'); 13 + phutil_require_module('phutil', 'utils'); 14 + 15 + 16 + phutil_require_source('DarkConsoleCore.php');
+88
src/aphront/console/plugin/base/DarkConsolePlugin.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + abstract class DarkConsolePlugin { 20 + 21 + private $data; 22 + private $request; 23 + private $core; 24 + 25 + abstract public function getName(); 26 + abstract public function getDescription(); 27 + abstract public function render(); 28 + 29 + public function __construct() { 30 + 31 + } 32 + 33 + public function setConsoleCore(DarkConsoleCore $core) { 34 + $this->core = $core; 35 + return $this; 36 + } 37 + 38 + public function getConsoleCore() { 39 + return $this->core; 40 + } 41 + 42 + public function generateData() { 43 + return null; 44 + } 45 + 46 + public function setData($data) { 47 + $this->data = $data; 48 + return $this; 49 + } 50 + 51 + public function getData() { 52 + return $this->data; 53 + } 54 + 55 + public function setRequest($request) { 56 + $this->request = $request; 57 + return $this; 58 + } 59 + 60 + public function getRequest() { 61 + return $this->request; 62 + } 63 + 64 + public function isPermanent() { 65 + return false; 66 + } 67 + 68 + public function shouldStartup() { 69 + return true; 70 + } 71 + 72 + public function didStartup() { 73 + return null; 74 + } 75 + 76 + public function willShutdown() { 77 + return null; 78 + } 79 + 80 + public function didShutdown() { 81 + return null; 82 + } 83 + 84 + public function processRequest() { 85 + return null; 86 + } 87 + 88 + }
+10
src/aphront/console/plugin/base/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + 10 + phutil_require_source('DarkConsolePlugin.php');
+129
src/aphront/console/plugin/errorlog/DarkConsoleErrorLogPlugin.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + class DarkConsoleErrorLogPlugin extends DarkConsolePlugin { 20 + 21 + public function getName() { 22 + $count = count($this->getData()); 23 + 24 + /* 25 + if ($count) { 26 + return 27 + <x:frag> 28 + <span style="color: #ff0000;">&bull;</span> Error Log ({$count}) 29 + </x:frag>; 30 + } 31 + 32 + */ 33 + return 'Error Log'; 34 + } 35 + 36 + 37 + public function getDescription() { 38 + return 'Shows errors and warnings.'; 39 + } 40 + 41 + 42 + public function generateData() { 43 + /* 44 + $stub = tabconsole(); 45 + if (!$stub) { 46 + return array(); 47 + } 48 + 49 + $errors = $stub->getErrors(); 50 + 51 + $data = array(); 52 + foreach ($errors as $error) { 53 + if (is_array($error)) { 54 + list($err, $trace) = $error; 55 + $trace = implode("\n", $trace); 56 + } else { 57 + $err = $error->getMessage(); 58 + $trace = $error->getTraceAsString(); 59 + } 60 + $data[] = array( 61 + 'error' => $err, 62 + 'trace' => $trace, 63 + ); 64 + } 65 + return $data; 66 + */ 67 + } 68 + 69 + 70 + public function render() { 71 + 72 + return '!!'; 73 + /* 74 + $data = $this->getData(); 75 + if (!$data) { 76 + return 77 + <x:frag> 78 + <div class="mu">No errors.</div> 79 + </x:frag>; 80 + } 81 + 82 + $markup = <table class="LConsoleErrors" />; 83 + $alt = false; 84 + foreach ($data as $error) { 85 + $row = <tr class={$alt ? 'alt' : null} />; 86 + 87 + $text = $error['error']; 88 + $text = preg_replace('/\(in .* on line \d+\)$/', '', trim($text)); 89 + 90 + $trace = $error['trace']; 91 + $trace = explode("\n", $trace); 92 + if (!$trace) { 93 + $trace = array('unknown@0@unknown'); 94 + } 95 + 96 + foreach ($trace as $idx => $traceline) { 97 + list($file, $line, $where) = array_merge( 98 + explode('@', $traceline), 99 + array('?', '?', '?')); 100 + if ($where == 'DarkConsole->addError' || 101 + $where == 'debug_rlog') { 102 + unset($trace[$idx]); 103 + } 104 + } 105 + 106 + $row->appendChild(<th rowspan={count($trace)}>{$text}</th>); 107 + 108 + foreach ($trace as $traceline) { 109 + list($file, $line, $where) = array_merge( 110 + explode('@', $traceline), 111 + array('?', '?', '?')); 112 + $row->appendChild(<td>{$file}:{$line}</td>); 113 + $row->appendChild(<td>{$where}()</td>); 114 + $markup->appendChild($row); 115 + $row = <tr class={$alt ? 'alt' : null} />; 116 + } 117 + 118 + $alt = !$alt; 119 + } 120 + 121 + return 122 + <x:frag> 123 + <h1>Errors</h1> 124 + <div class="LConsoleErrors">{$markup}</div> 125 + </x:frag>; 126 + */ 127 + } 128 + 129 + }
+12
src/aphront/console/plugin/errorlog/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'aphront/console/plugin/base'); 10 + 11 + 12 + phutil_require_source('DarkConsoleErrorLogPlugin.php');
+72
src/aphront/console/plugin/request/DarkConsoleRequestPlugin.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + class DarkConsoleRequestPlugin extends DarkConsolePlugin { 20 + 21 + public function getName() { 22 + return 'Request'; 23 + } 24 + 25 + public function getDescription() { 26 + return 'Information about $_REQUEST and $_SERVER.'; 27 + } 28 + 29 + public function generateData() { 30 + return array( 31 + 'Request' => $_REQUEST, 32 + 'Server' => $_SERVER, 33 + ); 34 + } 35 + 36 + public function render() { 37 + 38 + $data = $this->getData(); 39 + 40 + $sections = array( 41 + 'Basics' => array( 42 + 'Host' => $data['Server']['SERVER_ADDR'], 43 + 'Hostname' => gethostbyaddr($data['Server']['SERVER_ADDR']), 44 + ), 45 + ); 46 + 47 + $sections = array_merge($sections, $data); 48 + 49 + /* 50 + $out = <x:frag />; 51 + foreach ($sections as $header => $map) { 52 + $list = <table class="LConsoleRequestDict" />; 53 + foreach ($map as $key => $value) { 54 + if (!is_scalar($value)) { 55 + $value = fb_json_encode($value); 56 + } 57 + $value = <text wrap="80">{$value}</text>; 58 + $list->appendChild( 59 + <tr><th>{$key}</th><td>{$value}</td></tr>); 60 + } 61 + $out->appendChild( 62 + <x:frag> 63 + <h1>{$header}</h1> 64 + {$list} 65 + </x:frag>); 66 + } 67 + 68 + return $out; 69 + */ 70 + return "REQUEST"; 71 + } 72 + }
+12
src/aphront/console/plugin/request/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'aphront/console/plugin/base'); 10 + 11 + 12 + phutil_require_source('DarkConsoleRequestPlugin.php');
+39
src/aphront/console/plugin/services/DarkConsoleServicesPlugin.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + class DarkConsoleServicesPlugin extends DarkConsolePlugin { 20 + 21 + protected $observations; 22 + 23 + public function getName() { 24 + return 'Services'; 25 + } 26 + 27 + public function getDescription() { 28 + return 'Information about services.'; 29 + } 30 + 31 + public function willShutdown() { 32 + // $this->observations = cacheobserver(); 33 + } 34 + 35 + public function render() { 36 + return '!'; 37 + } 38 + } 39 +
+12
src/aphront/console/plugin/services/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'aphront/console/plugin/base'); 10 + 11 + 12 + phutil_require_source('DarkConsoleServicesPlugin.php');
+112
src/aphront/console/plugin/xhprof/DarkConsoleXHProfPlugin.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + class DarkConsoleXHProfPlugin extends DarkConsolePlugin { 20 + 21 + protected $xhprofID; 22 + protected $xhprofData; 23 + 24 + public function getName() { 25 + $run = $this->getData(); 26 + 27 + if ($run) { 28 + return '<span style="color: #ff00ff;">&bull;</span> XHProf'; 29 + } 30 + 31 + return 'XHProf'; 32 + } 33 + 34 + public function getDescription() { 35 + return 'Provides detailed PHP profiling information through XHProf.'; 36 + } 37 + 38 + public function generateData() { 39 + return $this->xhprofID; 40 + } 41 + 42 + public function getXHProfRunID() { 43 + return $this->xhprofID; 44 + } 45 + 46 + public function render() { 47 + if (!DarkConsoleXHProfPluginAPI::isProfilerAvailable()) { 48 + return 49 + '<p>The "xhprof" PHP extension is not available. Install xhprof '. 50 + 'to enable the XHProf plugin.'; 51 + } 52 + 53 + return '...'; 54 + } 55 + 56 + } 57 + /* 58 + 59 + public function render() { 60 + $run = $this->getData(); 61 + 62 + if ($run) { 63 + $uri = 'http://www.intern.facebook.com/intern/phprof/?run='.$run; 64 + return 65 + <x:frag> 66 + <h1>XHProf Results</h1> 67 + <div class="XHProfPlugin"> 68 + <a href={$uri} target="_blank" class="XHProfPlugin">Permalink</a> 69 + <iframe src={$uri} width="100%" height="600" /> 70 + </div> 71 + </x:frag>; 72 + } 73 + 74 + $uri = URI::getRequestURI(); 75 + return 76 + <x:frag> 77 + <h1>XHProf</h1> 78 + <form action={$uri} method="get" class="EnableFeature"> 79 + <fieldset> 80 + <legend>Enable Profiling</legend> 81 + <p>Profiling was not enabled for this request. Click the button 82 + below to rerun the request with profiling enabled.</p> 83 + <button type="submit" name="_profile_" value="all" 84 + style="margin: 2px 1em; width: 75%;"> 85 + Profile Page (With Includes) 86 + </button> 87 + <button type="submit" name="_profile_" value="exec" 88 + style="margin: 2px 1em; width: 75%;"> 89 + Profile Page (No Includes) 90 + </button> 91 + </fieldset> 92 + </form> 93 + </x:frag>; 94 + } 95 + 96 + public function willShutdown() { 97 + if (empty($_REQUEST['_profile_']) || 98 + $_REQUEST['_profile_'] != 'complete') { 99 + require_module('profiling/phprof/bootstrap'); 100 + $this->xhprofData = FB_HotProfiler::stop_hotprofiler(); 101 + } 102 + } 103 + 104 + public function didShutdown() { 105 + if ($this->xhprofData) { 106 + require_module_lazy('profiling/phprof'); 107 + $this->xhprofID = phprof_save_run($this->xhprofData); 108 + } 109 + } 110 + 111 + } 112 + */
+13
src/aphront/console/plugin/xhprof/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'aphront/console/plugin/base'); 10 + phutil_require_module('phabricator', 'aphront/console/plugin/xhprof/api'); 11 + 12 + 13 + phutil_require_source('DarkConsoleXHProfPlugin.php');
+84
src/aphront/console/plugin/xhprof/api/DarkConsoleXHProfPluginAPI.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + final class DarkConsoleXHProfPluginAPI { 20 + 21 + private static $profilerStarted; 22 + 23 + public static function isProfilerAvailable() { 24 + return extension_loaded('xhprof'); 25 + } 26 + 27 + public static function includeXHProfLib() { 28 + // TODO: this is incredibly stupid, but we may not have Phutil metamodule 29 + // stuff loaded yet so we can't just phutil_get_library_root() our way 30 + // to victory. 31 + $root = __FILE__; 32 + for ($ii = 0; $ii < 7; $ii++) { 33 + $root = dirname($root); 34 + } 35 + 36 + require_once $root.'/externals/xhprof/xhprof_lib.php'; 37 + } 38 + 39 + public static function hookProfiler($section) { 40 + if (empty($_REQUEST['__profile__'])) { 41 + return; 42 + } 43 + 44 + if ($section != $_REQUEST['__profile__']) { 45 + return; 46 + } 47 + 48 + if (!self::isProfilerAvailable()) { 49 + return; 50 + } 51 + 52 + if (self::$profilerStarted) { 53 + return; 54 + } 55 + 56 + self::startProfiler(); 57 + self::$profilerStarted = true; 58 + } 59 + 60 + public static function startProfiler() { 61 + self::includeXHProfLib(); 62 + xhprof_enable(); 63 + } 64 + 65 + public static function stopProfiler() { 66 + if (self::$profilerStarted) { 67 + $data = xhprof_disable(); 68 + $data = serialize($data); 69 + $file_class = 'PhabricatorFile'; 70 + PhutilSymbolLoader::loadClass($file_class); 71 + $file = call_user_func( 72 + array($file_class, 'newFromFileData'), 73 + $data, 74 + array( 75 + 'mime-type' => 'application/xhprof', 76 + 'name' => 'profile.xhprof', 77 + )); 78 + return $file->getPHID(); 79 + } else { 80 + return null; 81 + } 82 + } 83 + 84 + }
+12
src/aphront/console/plugin/xhprof/api/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phutil', 'symbols'); 10 + 11 + 12 + phutil_require_source('DarkConsoleXHProfPluginAPI.php');
+7
src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php
··· 125 125 '$' => 'PhabricatorFacebookAuthController', 126 126 'diagnose/$' => 'PhabricatorFacebookAuthDiagnosticsController', 127 127 ), 128 + 129 + '/xhprof/' => array( 130 + 'profile/(?<phid>[^/]+)/$' => 'PhabricatorXHProfProfileController', 131 + ), 128 132 ); 129 133 } 130 134 131 135 public function buildRequest() { 132 136 $request = new AphrontRequest($this->getHost(), $this->getPath()); 133 137 $request->setRequestData($_GET + $_POST); 138 + $request->setApplicationConfiguration($this); 134 139 return $request; 135 140 } 136 141 ··· 146 151 '</div>'; 147 152 148 153 $view = new PhabricatorStandardPageView(); 154 + $view->setRequest($this->getRequest()); 149 155 $view->appendChild($content); 150 156 151 157 $response = new AphrontWebpageResponse(); ··· 181 187 182 188 $view = new PhabricatorStandardPageView(); 183 189 $view->setTitle('404 Not Found'); 190 + $view->setRequest($this->getRequest()); 184 191 $view->appendChild($failure); 185 192 186 193 $response = new AphrontWebpageResponse();
+10 -8
src/aphront/request/AphrontRequest.php
··· 30 30 private $requestData; 31 31 private $user; 32 32 private $env; 33 + private $applicationConfiguration; 33 34 34 - final public function setEnvConfig(array $conf) { 35 - $this->env = $conf; 36 - return $this; 35 + final public function __construct($host, $path) { 36 + $this->host = $host; 37 + $this->path = $path; 37 38 } 38 39 39 - final public function getEnvConfig($key, $default = null) { 40 - return idx($this->env, $key, $default); 40 + final public function setApplicationConfiguration( 41 + $application_configuration) { 42 + $this->applicationConfiguration = $application_configuration; 43 + return $this; 41 44 } 42 45 43 - final public function __construct($host, $path) { 44 - $this->host = $host; 45 - $this->path = $path; 46 + final public function getApplicationConfiguration() { 47 + return $this->applicationConfiguration; 46 48 } 47 49 48 50 final public function setRequestData(array $request_data) {
+3 -3
src/applications/differential/controller/changesetview/DifferentialChangesetViewController.php
··· 54 54 55 55 $parser = new DifferentialChangesetParser(); 56 56 $parser->setChangeset($changeset); 57 - 57 + 58 58 $phids = array(); 59 59 $inlines = $this->loadInlineComments($id, $author_phid); 60 60 foreach ($inlines as $inline) { ··· 62 62 $phids[$inline->getAuthorPHID()] = true; 63 63 } 64 64 $phids = array_keys($phids); 65 - 65 + 66 66 $handles = id(new PhabricatorObjectHandleData($phids)) 67 67 ->loadHandles(); 68 68 $parser->setHandles($handles); 69 - 69 + 70 70 $factory = new DifferentialMarkupEngineFactory(); 71 71 $engine = $factory->newDifferentialCommentMarkupEngine(); 72 72 $parser->setMarkupEngine($engine);
+3
src/applications/differential/controller/changesetview/__init__.php
··· 10 10 phutil_require_module('phabricator', 'aphront/response/ajax'); 11 11 phutil_require_module('phabricator', 'applications/differential/controller/base'); 12 12 phutil_require_module('phabricator', 'applications/differential/parser/changeset'); 13 + phutil_require_module('phabricator', 'applications/differential/parser/markup'); 13 14 phutil_require_module('phabricator', 'applications/differential/storage/changeset'); 15 + phutil_require_module('phabricator', 'applications/differential/storage/inlinecomment'); 14 16 phutil_require_module('phabricator', 'applications/differential/view/changesetdetailview'); 17 + phutil_require_module('phabricator', 'applications/phid/handle/data'); 15 18 phutil_require_module('phabricator', 'infrastructure/javelin/api'); 16 19 17 20 phutil_require_module('phutil', 'utils');
+2 -2
src/applications/differential/controller/inlinecommentedit/DifferentialInlineCommentEditController.php
··· 62 62 63 63 $factory = new DifferentialMarkupEngineFactory(); 64 64 $engine = $factory->newDifferentialCommentMarkupEngine(); 65 - 65 + 66 66 $phids = array($user->getPHID()); 67 - 67 + 68 68 $handles = id(new PhabricatorObjectHandleData($phids)) 69 69 ->loadHandles(); 70 70
+2
src/applications/differential/controller/inlinecommentedit/__init__.php
··· 9 9 phutil_require_module('phabricator', 'aphront/response/ajax'); 10 10 phutil_require_module('phabricator', 'aphront/response/dialog'); 11 11 phutil_require_module('phabricator', 'applications/differential/controller/base'); 12 + phutil_require_module('phabricator', 'applications/differential/parser/markup'); 12 13 phutil_require_module('phabricator', 'applications/differential/storage/inlinecomment'); 13 14 phutil_require_module('phabricator', 'applications/differential/view/inlinecomment'); 15 + phutil_require_module('phabricator', 'applications/phid/handle/data'); 14 16 phutil_require_module('phabricator', 'view/dialog'); 15 17 16 18 phutil_require_module('phutil', 'utils');
+3 -3
src/applications/differential/parser/changeset/DifferentialChangesetParser.php
··· 41 41 protected $subparser; 42 42 protected $oldChangesetID = null; 43 43 protected $noHighlight; 44 - 44 + 45 45 private $handles; 46 46 47 47 const CACHE_VERSION = 4; ··· 92 92 $this->filetype = end(explode('.', $filename)); 93 93 } 94 94 } 95 - 95 + 96 96 public function setHandles(array $handles) { 97 97 $this->handles = $handles; 98 98 return $this; 99 99 } 100 - 100 + 101 101 public function setMarkupEngine(PhutilMarkupEngine $engine) { 102 102 $this->markupEngine = $engine; 103 103 return $this;
+1
src/applications/differential/parser/changeset/__init__.php
··· 12 12 phutil_require_module('phabricator', 'applications/differential/constants/changetype'); 13 13 phutil_require_module('phabricator', 'applications/differential/storage/changeset'); 14 14 phutil_require_module('phabricator', 'applications/differential/storage/diff'); 15 + phutil_require_module('phabricator', 'applications/differential/view/inlinecomment'); 15 16 phutil_require_module('phabricator', 'applications/files/uri'); 16 17 phutil_require_module('phabricator', 'infrastructure/javelin/markup'); 17 18 phutil_require_module('phabricator', 'storage/queryfx');
+14 -14
src/applications/differential/view/inlinecomment/DifferentialInlineCommentView.php
··· 38 38 $this->buildScaffolding = $scaffold; 39 39 return $this; 40 40 } 41 - 41 + 42 42 public function setHandles(array $handles) { 43 43 $this->handles = $handles; 44 44 return $this; 45 45 } 46 - 46 + 47 47 public function setMarkupEngine(PhutilMarkupEngine $engine) { 48 48 $this->markupEngine = $engine; 49 49 return $this; 50 50 } 51 51 52 52 public function render() { 53 - 53 + 54 54 $inline = $this->inlineComment; 55 - 55 + 56 56 $start = $inline->getLineNumber(); 57 57 $length = $inline->getLineLength(); 58 58 if ($length) { ··· 61 61 } else { 62 62 $line = 'Line '.number_format($start); 63 63 } 64 - 64 + 65 65 $metadata = array( 66 66 'number' => $inline->getLineNumber(), 67 67 'length' => $inline->getLineLength(), 68 68 'on_right' => $this->onRight, // TODO 69 69 ); 70 - 70 + 71 71 $sigil = 'differential-inline-comment'; 72 - 72 + 73 73 $links = 'xxx'; 74 74 $content = $inline->getContent(); 75 75 $handles = $this->handles; 76 - 76 + 77 77 if ($links) { 78 - $links = 78 + $links = 79 79 '<span class="differential-inline-comment-links">'. 80 80 $links. 81 81 '</span>'; 82 82 } 83 - 83 + 84 84 $content = $this->markupEngine->markupText($content); 85 - 85 + 86 86 $markup = javelin_render_tag( 87 87 'div', 88 88 array( ··· 96 96 $handles[$inline->getAuthorPHID()]->renderLink(). 97 97 '</div>'. 98 98 $content); 99 - 99 + 100 100 return $this->scaffoldMarkup($markup); 101 101 } 102 102 ··· 104 104 if (!$this->buildScaffolding) { 105 105 return $markup; 106 106 } 107 - 107 + 108 108 if ($this->onRight) { 109 109 return 110 110 '<table>'. ··· 127 127 '</table>'; 128 128 } 129 129 } 130 - 130 + 131 131 }
+1
src/applications/differential/view/inlinecomment/__init__.php
··· 6 6 7 7 8 8 9 + phutil_require_module('phabricator', 'infrastructure/javelin/markup'); 9 10 phutil_require_module('phabricator', 'view/base'); 10 11 11 12
+11 -7
src/applications/files/storage/file/PhabricatorFile.php
··· 104 104 $file->setStorageFormat(self::STORAGE_FORMAT_RAW); 105 105 $file->setStorageHandle($blob->getID()); 106 106 107 - try { 108 - $tmp = new TempFile(); 109 - Filesystem::writeFile($tmp, $data); 110 - list($stdout) = execx('file -b --mime %s', $tmp); 111 - $file->setMimeType($stdout); 112 - } catch (Exception $ex) { 113 - // Be robust here since we don't really care that much about mime types. 107 + if (isset($params['mime-type'])) { 108 + $file->setMimeType($params['mime-type']); 109 + } else { 110 + try { 111 + $tmp = new TempFile(); 112 + Filesystem::writeFile($tmp, $data); 113 + list($stdout) = execx('file -b --mime %s', $tmp); 114 + $file->setMimeType($stdout); 115 + } catch (Exception $ex) { 116 + // Be robust here since we don't really care that much about mime types. 117 + } 114 118 } 115 119 116 120 $file->save();
+34
src/applications/xhprof/controller/base/PhabricatorXHProfController.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + abstract class PhabricatorXHProfController extends PhabricatorController { 20 + 21 + public function buildStandardPageResponse($view, array $data) { 22 + $page = $this->buildStandardPageView(); 23 + 24 + $page->setApplicationName('XHProf'); 25 + $page->setBaseURI('/xhprof/'); 26 + $page->setTitle(idx($data, 'title')); 27 + $page->setGlyph("\xE2\x98\x84"); 28 + $page->appendChild($view); 29 + 30 + $response = new AphrontWebpageResponse(); 31 + return $response->setContent($page->render()); 32 + } 33 + 34 + }
+15
src/applications/xhprof/controller/base/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'aphront/response/webpage'); 10 + phutil_require_module('phabricator', 'applications/base/controller/base'); 11 + 12 + phutil_require_module('phutil', 'utils'); 13 + 14 + 15 + phutil_require_source('PhabricatorXHProfController.php');
+63
src/applications/xhprof/controller/profile/PhabricatorXHProfProfileController.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + class PhabricatorXHProfProfileController 20 + extends PhabricatorXHProfController { 21 + 22 + private $phid; 23 + 24 + public function willProcessRequest(array $data) { 25 + $this->phid = $data['phid']; 26 + } 27 + 28 + public function processRequest() { 29 + 30 + $file = id(new PhabricatorFile())->loadOneWhere( 31 + 'phid = %s', 32 + $this->phid); 33 + 34 + if (!$file) { 35 + return new Aphront404Response(); 36 + } 37 + 38 + $data = $file->loadFileData(); 39 + $data = unserialize($data); 40 + if (!$data) { 41 + throw new Exception("Failed to unserialize XHProf profile!"); 42 + } 43 + 44 + $request = $this->getRequest(); 45 + $symbol = $request->getStr('symbol'); 46 + 47 + if ($symbol) { 48 + $view = new PhabricatorXHProfProfileSymbolView(); 49 + $view->setProfileData($data); 50 + $view->setSymbol($symbol); 51 + } else { 52 + $view = new PhabricatorXHProfProfileTopLevelView(); 53 + $view->setProfileData($data); 54 + $view->setLimit(100); 55 + } 56 + 57 + return $this->buildStandardPageResponse( 58 + $view, 59 + array( 60 + 'title' => 'Profile', 61 + )); 62 + } 63 + }
+18
src/applications/xhprof/controller/profile/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'aphront/response/404'); 10 + phutil_require_module('phabricator', 'applications/files/storage/file'); 11 + phutil_require_module('phabricator', 'applications/xhprof/controller/base'); 12 + phutil_require_module('phabricator', 'applications/xhprof/view/symbol'); 13 + phutil_require_module('phabricator', 'applications/xhprof/view/toplevel'); 14 + 15 + phutil_require_module('phutil', 'utils'); 16 + 17 + 18 + phutil_require_source('PhabricatorXHProfProfileController.php');
+163
src/applications/xhprof/view/symbol/PhabricatorXHProfProfileSymbolView.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + class PhabricatorXHProfProfileSymbolView extends AphrontView { 20 + 21 + private $profileData; 22 + private $baseURI; 23 + private $symbol; 24 + 25 + public function setProfileData(array $data) { 26 + $this->profileData = $data; 27 + return $this; 28 + } 29 + 30 + public function setBaseURI($uri) { 31 + $this->baseURI = $uri; 32 + return $this; 33 + } 34 + 35 + public function setSymbol($symbol) { 36 + $this->symbol = $symbol; 37 + return $this; 38 + } 39 + 40 + public function render() { 41 + DarkConsoleXHProfPluginAPI::includeXHProfLib(); 42 + 43 + $data = $this->profileData; 44 + 45 + $GLOBALS['display_calls'] = true; 46 + $totals = array(); 47 + $flat = xhprof_compute_flat_info($data, $totals); 48 + unset($GLOBALS['display_calls']); 49 + 50 + $symbol = $this->symbol; 51 + 52 + $children = array(); 53 + $parents = array(); 54 + foreach ($this->profileData as $key => $counters) { 55 + list($parent, $child) = explode('==>', $key, 2); 56 + if ($parent == $symbol) { 57 + $children[$key] = $child; 58 + } else if ($child == $symbol) { 59 + $parents[$key] = $parent; 60 + } 61 + } 62 + 63 + $base_uri = $this->baseURI; 64 + 65 + $rows = array(); 66 + $rows[] = array( 67 + 'Metrics for this Call', 68 + '', 69 + '', 70 + '', 71 + '', 72 + '', 73 + ); 74 + $rows[] = array( 75 + phutil_render_tag( 76 + 'a', 77 + array( 78 + 'href' => $base_uri.'?symbol='.$symbol, 79 + ), 80 + phutil_escape_html($symbol)), 81 + $flat[$symbol]['ct'], 82 + $flat[$symbol]['wt'], 83 + '', 84 + $flat[$symbol]['excl_wt'], 85 + '', 86 + ); 87 + 88 + $rows[] = array( 89 + 'Parent Calls', 90 + '', 91 + '', 92 + '', 93 + '', 94 + '', 95 + ); 96 + foreach ($parents as $key => $name) { 97 + $rows[] = array( 98 + phutil_render_tag( 99 + 'a', 100 + array( 101 + 'href' => $base_uri.'?symbol='.$name, 102 + ), 103 + phutil_escape_html($name)), 104 + $data[$key]['ct'], 105 + $data[$key]['wt'], 106 + '', 107 + $data[$key]['wt'], 108 + '', 109 + ); 110 + } 111 + 112 + 113 + $rows[] = array( 114 + 'Child Calls', 115 + '', 116 + '', 117 + '', 118 + '', 119 + '', 120 + ); 121 + foreach ($children as $key => $name) { 122 + $rows[] = array( 123 + phutil_render_tag( 124 + 'a', 125 + array( 126 + 'href' => $base_uri.'?symbol='.$name, 127 + ), 128 + phutil_escape_html($name)), 129 + $data[$key]['ct'], 130 + $data[$key]['wt'], 131 + '', 132 + $data[$key]['wt'], 133 + '', 134 + ); 135 + } 136 + 137 + $table = new AphrontTableView($rows); 138 + $table->setHeaders( 139 + array( 140 + 'Symbol', 141 + 'Count', 142 + 'Incl Wall Time', 143 + '%', 144 + 'Excl Wall Time', 145 + '%', 146 + )); 147 + $table->setColumnClasses( 148 + array( 149 + 'wide pri', 150 + 'n', 151 + 'n', 152 + 'n', 153 + 'n', 154 + 'n', 155 + )); 156 + 157 + $panel = new AphrontPanelView(); 158 + $panel->setHeader('XHProf Profile'); 159 + $panel->appendChild($table); 160 + 161 + return $panel->render(); 162 + } 163 + }
+17
src/applications/xhprof/view/symbol/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'aphront/console/plugin/xhprof/api'); 10 + phutil_require_module('phabricator', 'view/base'); 11 + phutil_require_module('phabricator', 'view/control/table'); 12 + phutil_require_module('phabricator', 'view/layout/panel'); 13 + 14 + phutil_require_module('phutil', 'markup'); 15 + 16 + 17 + phutil_require_source('PhabricatorXHProfProfileSymbolView.php');
+124
src/applications/xhprof/view/toplevel/PhabricatorXHProfProfileTopLevelView.php
··· 1 + <?php 2 + 3 + /* 4 + * Copyright 2011 Facebook, Inc. 5 + * 6 + * Licensed under the Apache License, Version 2.0 (the "License"); 7 + * you may not use this file except in compliance with the License. 8 + * You may obtain a copy of the License at 9 + * 10 + * http://www.apache.org/licenses/LICENSE-2.0 11 + * 12 + * Unless required by applicable law or agreed to in writing, software 13 + * distributed under the License is distributed on an "AS IS" BASIS, 14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 + * See the License for the specific language governing permissions and 16 + * limitations under the License. 17 + */ 18 + 19 + class PhabricatorXHProfProfileTopLevelView extends AphrontView { 20 + 21 + private $profileData; 22 + private $limit; 23 + private $baseURI; 24 + 25 + public function setProfileData(array $data) { 26 + $this->profileData = $data; 27 + return $this; 28 + } 29 + 30 + public function setLimit($limit) { 31 + $this->limit = $limit; 32 + return $this; 33 + } 34 + 35 + public function setBaseURI($uri) { 36 + $this->baseURI = $uri; 37 + return $this; 38 + } 39 + 40 + public function render() { 41 + DarkConsoleXHProfPluginAPI::includeXHProfLib(); 42 + 43 + $GLOBALS['display_calls'] = true; 44 + $totals = array(); 45 + $flat = xhprof_compute_flat_info($this->profileData, $totals); 46 + unset($GLOBALS['display_calls']); 47 + 48 + $aggregated = array(); 49 + foreach ($flat as $call => $counters) { 50 + $agg_call = reset(explode('@', $call, 2)); 51 + if (empty($aggregated[$agg_call])) { 52 + $aggregated[$agg_call] = $counters; 53 + } else { 54 + foreach ($aggregated[$agg_call] as $key => $val) { 55 + if ($key != 'wt') { 56 + $aggregated[$agg_call][$key] += $counters[$key]; 57 + } 58 + } 59 + } 60 + } 61 + $flat = $aggregated; 62 + 63 + $flat = isort($flat, 'wt'); 64 + $flat = array_reverse($flat); 65 + 66 + $rows = array(); 67 + $rows[] = array( 68 + 'Total', 69 + number_format($totals['ct']), 70 + number_format($totals['wt']).' us', 71 + '100.0%', 72 + number_format($totals['wt']).' us', 73 + '100.0%', 74 + ); 75 + 76 + if ($this->limit) { 77 + $flat = array_slice($flat, 0, $this->limit); 78 + } 79 + 80 + $base_uri = $this->baseURI; 81 + 82 + foreach ($flat as $call => $counters) { 83 + $rows[] = array( 84 + phutil_render_tag( 85 + 'a', 86 + array( 87 + 'href' => $base_uri.'?symbol='.$call, 88 + ), 89 + phutil_escape_html($call)), 90 + number_format($counters['ct']), 91 + number_format($counters['wt']).' us', 92 + sprintf('%.1f%%', 100 * $counters['wt'] / $totals['wt']), 93 + number_format($counters['excl_wt']).' us', 94 + sprintf('%.1f%%', 100 * $counters['excl_wt'] / $totals['wt']), 95 + ); 96 + } 97 + 98 + $table = new AphrontTableView($rows); 99 + $table->setHeaders( 100 + array( 101 + 'Symbol', 102 + 'Count', 103 + 'Incl Wall Time', 104 + '%', 105 + 'Excl Wall Time', 106 + '%', 107 + )); 108 + $table->setColumnClasses( 109 + array( 110 + 'wide pri', 111 + 'n', 112 + 'n', 113 + 'n', 114 + 'n', 115 + 'n', 116 + )); 117 + 118 + $panel = new AphrontPanelView(); 119 + $panel->setHeader('XHProf Profile'); 120 + $panel->appendChild($table); 121 + 122 + return $panel->render(); 123 + } 124 + }
+18
src/applications/xhprof/view/toplevel/__init__.php
··· 1 + <?php 2 + /** 3 + * This file is automatically generated. Lint this module to rebuild it. 4 + * @generated 5 + */ 6 + 7 + 8 + 9 + phutil_require_module('phabricator', 'aphront/console/plugin/xhprof/api'); 10 + phutil_require_module('phabricator', 'view/base'); 11 + phutil_require_module('phabricator', 'view/control/table'); 12 + phutil_require_module('phabricator', 'view/layout/panel'); 13 + 14 + phutil_require_module('phutil', 'markup'); 15 + phutil_require_module('phutil', 'utils'); 16 + 17 + 18 + phutil_require_source('PhabricatorXHProfProfileTopLevelView.php');
+2 -2
src/storage/lisk/dao/LiskDAO.php
··· 718 718 $map[$key] = qsprintf($conn, '%C = %ns', $key, $value); 719 719 } 720 720 $map = implode(', ', $map); 721 - 721 + 722 722 if ($use_locks) { 723 723 $conn->query( 724 724 'UPDATE %T SET %Q, version = version + 1 WHERE %C = %d AND %C = %d', ··· 814 814 $conn = $this->getConnection('w'); 815 815 816 816 $columns = array_keys($data); 817 - 817 + 818 818 foreach ($data as $key => $value) { 819 819 $data[$key] = qsprintf($conn, '%ns', $value); 820 820 }
+11 -3
src/view/page/base/AphrontPageView.php
··· 40 40 protected function getTail() { 41 41 return ''; 42 42 } 43 - 43 + 44 44 protected function willRenderPage() { 45 45 return; 46 46 } 47 47 48 + protected function willSendResponse($response) { 49 + return $response; 50 + } 51 + 48 52 public function render() { 49 - 53 + 50 54 $this->willRenderPage(); 51 55 52 56 $title = $this->getTitle(); ··· 54 58 $body = $this->getBody(); 55 59 $tail = $this->getTail(); 56 60 57 - return <<<EOHTML 61 + $response = <<<EOHTML 58 62 <!DOCTYPE html> 59 63 <html> 60 64 <head> ··· 68 72 </html> 69 73 70 74 EOHTML; 75 + 76 + $response = $this->willSendResponse($response); 77 + return $response; 78 + 71 79 } 72 80 73 81 }
+30
src/view/page/standard/PhabricatorStandardPageView.php
··· 65 65 66 66 67 67 protected function willRenderPage() { 68 + 69 + if (!$this->getRequest()) { 70 + throw new Exception( 71 + "You must set the Request to render a PhabricatorStandardPageView."); 72 + } 73 + 74 + $console = $this->getRequest()->getApplicationConfiguration()->getConsole(); 75 + 68 76 require_celerity_resource('phabricator-core-css'); 69 77 require_celerity_resource('phabricator-core-buttons-css'); 70 78 require_celerity_resource('phabricator-standard-page-view'); ··· 72 80 require_celerity_resource('javelin-lib-dev'); 73 81 require_celerity_resource('javelin-workflow-dev'); 74 82 83 + if ($console) { 84 + require_celerity_resource('aphront-dark-console-css'); 85 + Javelin::initBehavior( 86 + 'dark-console', 87 + array( 88 + 'uri' => '/~/', 89 + )); 90 + } 91 + 75 92 $this->bodyContent = $this->renderChildren(); 76 93 } 77 94 ··· 94 111 return $this->glyph; 95 112 } 96 113 114 + protected function willSendResponse($response) { 115 + $console = $this->getRequest()->getApplicationConfiguration()->getConsole(); 116 + if ($console) { 117 + $response = str_replace( 118 + '<darkconsole />', 119 + $console->render($this->getRequest()), 120 + $response); 121 + } 122 + return $response; 123 + } 124 + 97 125 protected function getBody() { 126 + $console = $this->getRequest()->getApplicationConfiguration()->getConsole(); 98 127 99 128 $tabs = array(); 100 129 foreach ($this->tabs as $name => $tab) { ··· 142 171 } 143 172 144 173 return 174 + ($console ? '<darkconsole />' : null). 145 175 '<div class="phabricator-standard-page">'. 146 176 '<div class="phabricator-standard-header">'. 147 177 '<div class="phabricator-login-details">'.
+1
src/view/page/standard/__init__.php
··· 7 7 8 8 9 9 phutil_require_module('phabricator', 'infrastructure/celerity/api'); 10 + phutil_require_module('phabricator', 'infrastructure/javelin/api'); 10 11 phutil_require_module('phabricator', 'view/page/base'); 11 12 12 13 phutil_require_module('phutil', 'markup');
+17
webroot/index.php
··· 34 34 phutil_require_module('phabricator', 'infrastructure/env'); 35 35 PhabricatorEnv::setEnvConfig($conf); 36 36 37 + phutil_require_module('phabricator', 'aphront/console/plugin/xhprof/api'); 38 + DarkConsoleXHProfPluginAPI::hookProfiler('all'); 39 + 37 40 $host = $_SERVER['HTTP_HOST']; 38 41 $path = $_REQUEST['__path__']; 39 42 ··· 51 54 52 55 $application->setHost($host); 53 56 $application->setPath($path); 57 + $application->willBuildRequest(); 54 58 $request = $application->buildRequest(); 55 59 $application->setRequest($request); 56 60 list($controller, $uri_data) = $application->buildController(); ··· 83 87 list($header, $value) = $header; 84 88 header("{$header}: {$value}"); 85 89 } 90 + 91 + if (isset($_REQUEST['__profile__']) && 92 + ($_REQUEST['__profile__'] == 'all')) { 93 + $profile = DarkConsoleXHProfPluginAPI::stopProfiler(); 94 + $profile = print_r($profile, true); 95 + if (strpos($response_string, '<body>') !== false) { 96 + $response_string = str_replace( 97 + '<body>', 98 + '<body>'.$profile, 99 + $response_string); 100 + } 101 + } 102 + 86 103 echo $response_string; 87 104 88 105
+46
webroot/rsrc/css/aphront/dark-console.css
··· 1 + /** 2 + * @provides aphront-dark-console-css 3 + */ 4 + 5 + .dark-console { 6 + background: #555555; 7 + color: #eeeeee; 8 + width: 100%; 9 + font-family: "Verdana"; 10 + font-size: 11px; 11 + border-bottom: 2px solid #000000; 12 + position: relative; 13 + z-index: 1; 14 + } 15 + 16 + .dark-console-tabs { 17 + width: 180px; 18 + background: #222222; 19 + border-right: 1px solid #888888; 20 + padding: 2.5em 0em; 21 + } 22 + 23 + 24 + a.dark-console-tab { 25 + padding: .75em 12px; 26 + text-align: right; 27 + background: #444444; 28 + position: relative; 29 + border: 1px solid #666666; 30 + border-width: 1px 0; 31 + border-right-color: #888888; 32 + margin-bottom: 2px; 33 + display: block; 34 + color: #cccccc; 35 + } 36 + 37 + a.dark-console-tab-selected { 38 + margin-right: -1px; 39 + padding-right: 13px; 40 + background: #555555; 41 + border-color: #888888; 42 + border-right-color: #555555; 43 + color: #eeeeee; 44 + } 45 + 46 +
+6
webroot/rsrc/css/aphront/table-view.css
··· 64 64 font-size: 10px; 65 65 } 66 66 67 + .aphront-table-view td.n { 68 + font-family: "Monaco", monospace; 69 + font-size: 10px; 70 + text-align: right; 71 + } 72 + 67 73 .aphront-table-view tr.no-data td { 68 74 padding: 1em; 69 75 text-align: center;
+55
webroot/rsrc/js/application/core/behavior-dark-console.js
··· 1 + /** 2 + * @provides javelin-behavior-dark-console 3 + */ 4 + 5 + JX.behavior('dark-console', function() { 6 + JX.Stratcom.listen( 7 + 'click', 8 + ['dark-console', 'dark-console-tab'], 9 + function(e) { 10 + var console = e.getNode('dark-console'); 11 + var tabs = JX.DOM.scry(console, 'a', 'dark-console-tab'); 12 + var panels = JX.DOM.scry(console, 'div', 'dark-console-panel'); 13 + var target = e.getTarget(); 14 + for (var ii = 0; ii < tabs.length; ii++) { 15 + JX.DOM.alterClass( 16 + tabs[ii], 17 + 'dark-console-tab-selected', 18 + tabs[ii] == target); 19 + (tabs[ii] != target ? JX.DOM.hide : JX.DOM.show)(panels[ii]); 20 + } 21 + /* 22 + new JX.Request(e.getNodeData('dark-console').uri, JX.bag) 23 + .setData({tab: e.getNodeData('dark-console-tab').key}) 24 + .send(); 25 + */ 26 + }); 27 + 28 + JX.Stratcom.listen( 29 + 'keypress', 30 + null, 31 + function(e) { 32 + var raw = e.getRawEvent(); 33 + if ((String.fromCharCode(raw.charCode).charAt(0) == '`') && 34 + !raw.shiftKey && 35 + !raw.metaKey) { 36 + 37 + if (JX.Stratcom.pass()) { 38 + return; 39 + } 40 + 41 + var console = JX.DOM.find(document.body, 'table', 'dark-console'); 42 + var data = JX.Stratcom.getData(console); 43 + data.visible = !data.visible; 44 + if (data.visible) { 45 + JX.DOM.show(console); 46 + } else { 47 + JX.DOM.hide(console); 48 + } 49 + 50 + // new JX.Request(data.uri, JX.bag) 51 + // .setData({visible: data.visible}) 52 + // .send(); 53 + } 54 + }); 55 + });
+2 -2
webroot/rsrc/js/application/differential/behavior-edit-inline-comments.js
··· 56 56 function isOnRight(node) { 57 57 return node.parentNode.firstChild != node; 58 58 } 59 - 59 + 60 60 function isNewFile(node) { 61 61 var data = JX.Stratcom.getData(root); 62 62 return isOnRight(node) || (data.left != data.right); ··· 142 142 number: o, 143 143 length: len, 144 144 is_new: isNewFile(target) ? 1 : 0, 145 - on_right: isOnRight(target) ? 1 : 0 145 + on_right: isOnRight(target) ? 1 : 0 146 146 }; 147 147 148 148 workflow = true;