source: trunk/htdocs/diagnosis/index.php @ 1099

Last change on this file since 1099 was 1099, checked in by moo, 21 months ago

refactor: move lang files to sub folder

  • Property svn:eol-style set to native
File size: 10.7 KB
RevLine 
[1089]1<?php
2
3include "../common/common.php";
[1099]4include get_language_file("./lang");
5
[1092]6$knownUnstablePhpVersions = array(
7        array('=', '5.3.14', 'random corrupt memory on high concurrent'),
8        );
[1089]9
10$module = "diagnosis";
11
12$notes = array();
[1092]13$activeNote = null;
14function checking($item) // {{{
[1089]15{
[1092]16    global $activeNote;
17    $activeNote = array('item' => $item);
18}
19// }}}
20function result($type, $result, $suggestion = "") // {{{
21{
22    global $notes, $activeNote;
[1089]23    $notes[] = array(
24            'type' => $type
[1092]25            , 'result' => ($type != 'skipped' && !$suggestion ? "OK. " : "") . $result
[1089]26            , 'suggestion' => $suggestion
[1092]27            ) + $activeNote;
[1089]28}
[1090]29// }}}
[1089]30function getCacheInfos() // {{{
31{
32    $phpCacheCount = xcache_count(XC_TYPE_PHP);
33    $varCacheCount = xcache_count(XC_TYPE_VAR);
34
35    $cacheInfos = array();
36    for ($i = 0; $i < $phpCacheCount; $i ++) {
37        $cacheInfo = xcache_info(XC_TYPE_PHP, $i);
38        $cacheInfo['type'] = XC_TYPE_PHP;
39        $cacheInfos[] = $cacheInfo;
40    }
41
42    for ($i = 0; $i < $varCacheCount; $i ++) {
43        $cacheInfo = xcache_info(XC_TYPE_VAR, $i);
44        $cacheInfo['type'] = XC_TYPE_VAR;
45        $cacheInfos[] = $cacheInfo;
46    }
47    return $cacheInfos;
48}
[1090]49// }}}
[1092]50function getIniFileInfo() // {{{
51{
[1090]52    ob_start();
53    phpinfo(INFO_GENERAL);
54    $info = ob_get_clean();
55    ob_start();
56    if (preg_match_all("!<tr>[^<]*<td[^>]*>[^<]*(?:Configuration|ini|Server API)[^<]*</td>[^<]*<td[^>]*>[^<]*</td>[^<]*</tr>!s", $info, $m)) {
[1092]57        $iniInfo = '<table class="phpinfo">'
58            . implode('', $m[0])
59            . '</table>';
[1090]60    }
[1092]61    else {
62        $iniInfo = '';
63    }
64    $loadedIni = '';
65    $iniDirectory = '';
[1090]66    if (preg_match('!<td class="v">(.*?\\.ini)!', $info, $m)) {
[1092]67        $loadedIni = $m[1];
[1090]68    }
69    else if (preg_match('!Configuration File \\(php.ini\\) Path *</td><td class="v">([^<]+)!', $info, $m)) {
[1092]70        $iniDirectory = $m[1];
[1090]71    }
[1092]72    return array($loadedIni, $iniDirectory, $iniInfo);
73}
74// }}}
75
76$xcacheLoaded = extension_loaded('XCache');
77checking(_T("XCache extension")); // {{{
78if (!$xcacheLoaded) {
79    list($loadedIni, $iniDirectory, $iniInfo) = getIniFileInfo();
80    if ($loadedIni) {
81        echo sprintf(_T("Add extension=xcache.so (or xcache.dll) in %s"), $loadedIni);
82    }
83    else if (preg_match('!Configuration File \\(php.ini\\) Path *</td><td class="v">([^<]+)!', $info, $m)) {
84        echo sprintf(_T("Please put a php.ini in %s and add extension=xcache.so (or xcache.dll) in it"), $iniDirectory);
85    }
[1090]86    else {
[1092]87        echo _T("Cannot detect ini location");
[1090]88    }
[1092]89    echo _T(" (See above)");
90    result("error", _T('Not loaded'), ob_get_clean());
[1090]91}
92else {
[1092]93    result("info", _T('Loaded'));
94}
95// }}}
96if ($xcacheLoaded) { // {{{ load XCache summary
[1090]97    $cacheInfos = getCacheInfos();
[1089]98
[1092]99    $ooms = 0;
100    $errors = 0;
101    $disabled = 0;
102    $compiling = 0;
103    $readonlyProtection = false;
104    $phpCacheCount = xcache_count(XC_TYPE_PHP);
105    $phpCached = 0;
106    $varCached = 0;
[1090]107    foreach ($cacheInfos as $cacheInfo) {
[1092]108        $ooms += $cacheInfo['ooms'];
109        $errors += $cacheInfo['errors'];
110        $disabled += $cacheInfo['disabled'] ? 1 : 0;
111        if ($cacheInfo['type'] == XC_TYPE_PHP) {
112            $compiling += $cacheInfo['compiling'] ? 1 : 0;
113            $phpCached += $cacheInfo['cached'];
[1090]114        }
[1092]115        if ($cacheInfo['type'] == XC_TYPE_VAR && $cacheInfo['cached']) {
116            $varCached += $cacheInfo['cached'];
117        }
118        if ($cacheInfo['can_readonly']) {
119            $readonlyProtection = true;
120        }
[1090]121    }
[1092]122}
123// }}}
124checking(_T("Enabling PHP Cacher")); // {{{
125if (!$xcacheLoaded) {
126    result("skipped", "XCache not loaded");
127}
128else if (!ini_get("xcache.size")) {
129    result(
130        "error"
131        , _T("Not enabled: Website is not accelerated by XCache")
132        , _T("Set xcache.size to non-zero, set xcache.cacher = On")
133        );
134}
135else if (!$phpCached) {
136    result(
137        "error"
138        , _T("No php script cached: Website is not accelerated by XCache")
139        , _T("Set xcache.cacher = On")
140        );
141}
142else {
143    result("info", _T('Enabled'));
144}
145// }}}
146checking(_T("PHP Compile Time Error")); // {{{
147if (!$xcacheLoaded) {
148    result("skipped", "XCache not loaded");
149}
150else if (!$phpCacheCount) {
151    result("skipped", "XCache PHP cacher not enabled");
152}
153else if ($errors) {
154    result(
155        "warning"
156        , _T("Error happened when compiling at least one of your PHP code")
157        , _T("This usually means there is syntax error in your PHP code. Enable PHP error_log to see what parser error is it, fix your code")
158        );
159}
160else {
161    result("info", _T('No error happened'));
162}
163// }}}
164checking(_T("Busy Compiling")); // {{{
165if (!$xcacheLoaded) {
166    result("skipped", "XCache not loaded");
167}
168else if (!$phpCacheCount) {
169    result("skipped", "XCache PHP cacher not enabled");
170}
171else if ($compiling) {
172    result(
173        "warning"
174        , _T("Cache marked as busy for compiling")
175        , _T("It's ok if this status don't stay for long. Otherwise, it could be a sign of PHP crash/coredump, report to XCache devs")
176        );
177}
178else {
179    result("info", _T('Idle'));
180}
181// }}}
182checking(_T("Enabling VAR Cacher")); // {{{
183if (!$xcacheLoaded) {
184    result("skipped", "XCache not loaded");
185}
186else if (!ini_get("xcache.var_size")) {
187    result(
188        "error"
189        , _T("Not enabled: code that use xcache var cacher fall back to other backend")
190        , _T("Set xcache.var_size to non-zero")
191        );
192}
193else {
194    result("info", _T('Enabled'));
195
196    checking(_T("Using VAR Cacher")); // {{{
197    if ($varCached) {
198        result(
[1089]199            "warning"
[1092]200            , _T("No variable data cached")
201            , _T("Var Cacher won't work simply by enabling it."
202                . " PHP code must call XCache APIs like xcache_set() to use it as cache backend. 3rd party web apps may come with XCache support, config it to use XCache as cachign backend")
[1089]203            );
204    }
[1090]205    else {
[1092]206        result("info", _T('Cache in use'));
[1090]207    }
[1092]208    // }}}
209}
210// }}}
211checking(_T("Cache Size")); // {{{
212if (!$xcacheLoaded) {
213    result("skipped", "XCache not loaded");
214}
215else if ($ooms) {
216    result(
217        "warning"
218        , _T("Out of memory happened when trying to write to cache")
219        , _T("Increase xcache.size and/or xcache.var_size")
220        );
221}
222else {
223    result("info", _T('Enough'));
224}
225// }}}
226checking(_T("Slots")); // {{{
227$slotsTooBig = null;
228$slotsTooSmall = null;
229foreach ($cacheInfos as $cacheInfo) {
230    if ($cacheInfo['size'] < '1024000' && $cacheInfo['slots'] >= '8192') {
231        $slotsTooBig = $cacheInfo['type'];
232        break;
233    }
234    if ($cacheInfo['slots'] < $cacheInfo['cached'] / 2) {
235        $slotsTooSmall = $cacheInfo['type'];
236        break;
237    }
238}
239if (isset($slotsTooBig)) {
240    $prefix = $slotsTooBig == XC_TYPE_PHP ? '' : 'var_';
241    result(
242        "warning"
243        , _T("Slots value too big")
244        , sprintf(_T("A very small value is set to %s value and leave %s value is too big.\n"
245            . "Decrease %s if small cache is really what you want"), "xcache.{$prefix}size", "xcache.{$prefix}slots", "xcache.{$prefix}slots")
246        );
247}
248else if (isset($slotsTooSmall)) {
249    $prefix = $slotsTooSmall == XC_TYPE_PHP ? '' : 'var_';
250    result(
251        "warning"
252        , _T("Slots value too small")
253        , sprintf(_T("So many item are cached. Increase %s to a more proper value"), "xcache.{$prefix}slots")
254        );
255}
256else {
257    result("info", _T('Looks good'));
258}
259// }}}
260checking(_T("Cache Status")); // {{{
261if (!$xcacheLoaded) {
262    result("skipped", "XCache not loaded");
263}
264else if ($disabled) {
265    result(
266        "warning"
267        , _T("At least one of the caches is disabled. ")
268            . (ini_get("xcache.crash_on_coredump") ? _T("It was disabled by PHP crash/coredump handler or You disabled it manually") : _T('You disabled it manually'))
269        , _T("Enable the cache.")
270            . (ini_get("xcache.crash_on_coredump") ? " " . _T("If it was caused by PHP crash/coredump, report to XCache devs") : "")
271        );
272}
273else {
274    result("info", _T('Idle'));
275}
276// }}}
[1089]277
[1092]278checking(_T("Coredump Directory")); // {{{
279if (!$xcacheLoaded) {
280    result("skipped", "XCache not loaded");
281}
282else if (!ini_get("xcache.coredump_directory")) {
283    result("info"
284            , _T("Not enabled")
285            , _T("Enable coredump to know your PHP crash. It can also be enabled in fpm other than in XCache")
286            );
287}
288else if (ini_get("xcache.coredump_directory")) {
289    $coreDir = ini_get("xcache.coredump_directory");
290    if (substr($coreDir, -1) != DIRECTORY_SEPARATOR) {
291        $coreDir .= DIRECTORY_SEPARATOR;
[1090]292    }
[1092]293    $coreFiles = glob($coreDir . "core*");
294    if ($coreFiles) {
295        result("error"
296                , _T("Core files found:\n") . implode("\n", $coreFiles)
297                , _T("Disable XCache PHP Cacher (xcache.size=0), remove the core file(s). If core file appears again, report call stack backtrace in the core to XCache devs")
298                );
299    }
300    else {
301        result("info"
302                , _T("Enabled")
303                , sprintf(_T("You can see core files if PHP crash in %s if PHP crash"), ini_get("xcache.coredump_directory"))
304                );
305    }
306}
307// }}}
308checking(_T("Readonly Protection")); // {{{
309if (!$xcacheLoaded) {
310    result("skipped", "XCache not loaded");
311}
[1093]312else if (ini_get("xcache.readonly_protection") && !$readonlyProtection) {
[1092]313    result(
314        "error"
315        , _T("Set to enabled but not available")
316        , _T("Use xcache.mmap_path other than /dev/zero")
317        );
318}
319else {
320    result(
321        "info"
322        , $readonlyProtection ? _T("Enabled") : _T("Disabled")
323        , _T("Enable readonly_protection == --performance & ++stability. "
324            . "Disable readonly_protection == ++performance & --stability")
325        );
326}
327// }}}
328checking(_T("XCache modules")); // {{{
329if (!$xcacheLoaded) {
330    result("skipped", "XCache not loaded");
331}
332else {
333    $xcacheModules = explode(" ", XCACHE_MODULES);
334    $unexpectedModules = array_intersect($xcacheModules, array("coverager", "disassembler"));
335    if ($unexpectedModules) {
336        result(
[1089]337            "warning"
[1092]338            , implode("\n", $unexpectedModules)
339            , _T("Acceptable. Module(s) listed above are built into XCache but not for production server\n"
340                . "Leave it as is if you're feeling good.\n"
341                . "Re-configure XCache with the above module(s) disabled if you're strict with server security.")
[1089]342            );
343    }
[1090]344    else {
[1092]345        result("info", _T('Idle'));
[1090]346    }
[1092]347}
348// }}}
349checking(_T("XCache test setting")); // {{{
350if (!$xcacheLoaded) {
351    result("skipped", "XCache not loaded");
352}
353else if ((int) ini_get('xcache.test') == 1) {
354    result(
355        "warning"
356        , _T("Enabled")
357        , _T("xcache.test is for testing only, not for server. set it to off")
358        );
359}
360else {
361    result("info", _T('Disabled'));
362}
363// }}}
364checking(_T("PHP Version")); // {{{
365$phpVersion = phpversion();
366$unstablePhpVersionReason = null;
367foreach ($knownUnstablePhpVersions as $knownUnstablePhpVersion) {
368    list($compareOp, $unstablePhpVersion, $reason) = $knownUnstablePhpVersion;
369    if ($compareOp) {
370        $isUnstable = version_compare($phpVersion, $unstablePhpVersion, $compareOp);
[1090]371    }
[1092]372    else {
373        $isUnstable = substr($phpVersion, 0, strlen($unstablePhpVersion)) == $unstablePhpVersion;
[1090]374    }
[1089]375
[1092]376    if ($isUnstable) {
377        $unstablePhpVersionReason = $reason;
378        break;
[1090]379    }
[1089]380}
[1092]381if ($unstablePhpVersionReason) {
382    result("error"
383            , _T("The version of PHP you're using is known to be unstable: ") . $unstablePhpVersionReason
384            , _T("Upgrade to new version of PHP"));
[1089]385}
[1092]386else {
387    result("info", _T("Looks good"));
[1089]388}
[1092]389// }}}
390checking(_T("Extension Compatibility")); // {{{
391$loadedZendExtensions = get_loaded_extensions(true);
392if (array_search("Zend Optimizer", $loadedZendExtensions) !== false) {
393    result(
394        "warning"
395        , _T("Zend Optimizer loaded")
396        , _T("Optimizer feature of 'Zend Optimizer' is disabled by XCache due to compatibility reason; the Loader of it is still available, encoded files are still supported")
397        );
[1089]398}
[1092]399// }}}
[1089]400
401include "./diagnosis.tpl.php";
402
Note: See TracBrowser for help on using the repository browser.