upadated colorbox andd prod_check
This commit is contained in:
parent
50c3e1c7d7
commit
0ba0c21bb9
@ -113,6 +113,20 @@ Production monitor
|
|||||||
6. If you wish to fetch the data immediately, check the appropriate box and save
|
6. If you wish to fetch the data immediately, check the appropriate box and save
|
||||||
the settings. Good to go!
|
the settings. Good to go!
|
||||||
|
|
||||||
|
Cron setup
|
||||||
|
----------
|
||||||
|
To automatically check the site status and/or module updates on cron, you will
|
||||||
|
need to install drush and configure the following tasks in the crontab:
|
||||||
|
|
||||||
|
# Check ALL sites for updates, once a day starting at 0100H at night.
|
||||||
|
0 1 * * * /path/to/drush -r /path/to/docroot prod-monitor-updates -y --quiet
|
||||||
|
# Fetch ALL site data every five minutes (or whatever you please obviously).
|
||||||
|
0/5 * * * * /path/to/drush -r /path/to/docroot prod-monitor-fetch -y --quiet
|
||||||
|
|
||||||
|
Obviously, the time and frequency of these cron jobs is at your discretion.
|
||||||
|
Do note that, depending on the number of sites you have configured, the crons
|
||||||
|
may be running for quite some time, especially the module update checking job!
|
||||||
|
|
||||||
Upgrading
|
Upgrading
|
||||||
---------
|
---------
|
||||||
When upgrading Production monitor to a newer version, always run update.php to
|
When upgrading Production monitor to a newer version, always run update.php to
|
||||||
@ -123,9 +137,9 @@ Nagios
|
|||||||
------
|
------
|
||||||
1. Download and install the Nagios module from http://drupal.org/project/nagios
|
1. Download and install the Nagios module from http://drupal.org/project/nagios
|
||||||
as per its readme instructions
|
as per its readme instructions
|
||||||
2. Enable Nagios support in the prod_check module on /admin/settings/prod-check
|
2. Enable Nagios support in the prod_check module on /admin/config/system/prod-check
|
||||||
by ticking the appropriate box.
|
by ticking the appropriate box.
|
||||||
3. Untick the checboxes for those items you do not whish to be monitored by
|
3. Untick the checkboxes for those items you do not whish to be monitored by
|
||||||
Nagios.
|
Nagios.
|
||||||
4. Save the settings and you're good to go!
|
4. Save the settings and you're good to go!
|
||||||
|
|
||||||
@ -172,7 +186,7 @@ For Production monitor, these commands are available:
|
|||||||
$ drush prod-monitor-fetch [id]
|
$ drush prod-monitor-fetch [id]
|
||||||
$ drush prod-monitor-flush [id]
|
$ drush prod-monitor-flush [id]
|
||||||
$ drush prod-monitor-delete [id]
|
$ drush prod-monitor-delete [id]
|
||||||
$ drush prod-monitor-updates [id] (--check)
|
$ drush prod-monitor-updates [id] (--check, --security-only)
|
||||||
|
|
||||||
or their aliases:
|
or their aliases:
|
||||||
|
|
||||||
@ -180,7 +194,7 @@ or their aliases:
|
|||||||
$ drush pmon-fe [id]
|
$ drush pmon-fe [id]
|
||||||
$ drush pmon-fl [id]
|
$ drush pmon-fl [id]
|
||||||
$ drush pmon-rm [id]
|
$ drush pmon-rm [id]
|
||||||
$ drush pmon-up [id] (--check)
|
$ drush pmon-up [id] (--check, --security-only)
|
||||||
|
|
||||||
The id parameter is optional for the prod-monitor command. The best usage is to
|
The id parameter is optional for the prod-monitor command. The best usage is to
|
||||||
first get a list of sites:
|
first get a list of sites:
|
||||||
@ -200,16 +214,19 @@ You can pass multiple ID's by separating them with spaces:
|
|||||||
|
|
||||||
The prod-monitor-updates command acts on one id only!
|
The prod-monitor-updates command acts on one id only!
|
||||||
|
|
||||||
APC
|
APC/OPcache
|
||||||
---
|
-----------
|
||||||
Production Check complains about APC not being installed or misconfigured. What
|
Production Check complains about APC not being installed or misconfigured. What
|
||||||
is APC you wonder? Well, APC is an opcode caching mechanism that will pre-com-
|
is APC you wonder? Well, APC is an opcode caching mechanism that will pre-com-
|
||||||
pile PHP files and keep them stored in memory. The full manual can be found
|
pile PHP files and keep them stored in memory. The full manual can be found
|
||||||
here: http://php.net/manual/en/book.apc.php .
|
here: http://php.net/manual/en/book.apc.php .
|
||||||
For Drupal sites, it is important to tune APC in order to achieve maximum per-
|
PHP version 5.5 comes bundled with an alternative to APC named OPcache. The full
|
||||||
formance there. Drupal uses a massive amount of files and therefore you should
|
manual can be found here: http://php.net/manual/en/book.opcache.php .
|
||||||
assign a proper amount of RAM to APC. For a dedicated setup 64Mb should be
|
|
||||||
sufficient, in shared setups, you should easily double that!
|
For Drupal sites, it is important to tune APC/OPcache in order to achieve
|
||||||
|
maximum performance there. Drupal uses a massive amount of files and therefore
|
||||||
|
you should assign a proper amount of RAM to APC/OPcache. For a dedicated setup
|
||||||
|
64Mb should be sufficient, in shared setups, you will need to multiply that!
|
||||||
To tune your setup, you can use the aforementioned hidden link provided by
|
To tune your setup, you can use the aforementioned hidden link provided by
|
||||||
Production check. You can see the memory usage there, verify your settings and
|
Production check. You can see the memory usage there, verify your settings and
|
||||||
much more.
|
much more.
|
||||||
@ -219,6 +236,7 @@ extension (drupal.org CVS did not seem to accept files with .ini extension?).
|
|||||||
|
|
||||||
Note: This 'hidden link' makes use of the APC supplied PHP code and is subject
|
Note: This 'hidden link' makes use of the APC supplied PHP code and is subject
|
||||||
to the PHP license: http://www.php.net/license/3_01.txt .
|
to the PHP license: http://www.php.net/license/3_01.txt .
|
||||||
|
The OPcache variant is taken from https://github.com/rlerdorf/opcache-status .
|
||||||
|
|
||||||
|
|
||||||
Updates
|
Updates
|
||||||
@ -233,8 +251,8 @@ Cron is NOT used to do this, since we want to keep the transfer to a minimum.
|
|||||||
Hidden link
|
Hidden link
|
||||||
===========
|
===========
|
||||||
Production check adds some 'hidden links' to the site where you can check the
|
Production check adds some 'hidden links' to the site where you can check the
|
||||||
APC, Memcache and DB status of your site. These pages can be found on:
|
APC/OPcache, Memcache and DB status of your site. These pages can be found on:
|
||||||
/admin/reports/status/apc
|
/admin/reports/status/apc-opc
|
||||||
/admin/reports/status/memcache
|
/admin/reports/status/memcache
|
||||||
/admin/reports/status/database
|
/admin/reports/status/database
|
||||||
|
|
||||||
@ -251,8 +269,8 @@ The detailed report page
|
|||||||
The page is divided into 4 sections:
|
The page is divided into 4 sections:
|
||||||
|
|
||||||
- Settings: checks various Drupal settings
|
- Settings: checks various Drupal settings
|
||||||
- Server: checks that are 'outside of Drupal' such as APC and wether or not you
|
- Server: checks that are 'outside of Drupal' such as APC/OPcache and wether or
|
||||||
have removed the release note files from the root.
|
not you have removed the release note files from the root.
|
||||||
- Performance: checks relevant to the performance settings in Drupal such as
|
- Performance: checks relevant to the performance settings in Drupal such as
|
||||||
page / block caching.
|
page / block caching.
|
||||||
- Modules: checks if certain modules are on / off
|
- Modules: checks if certain modules are on / off
|
||||||
|
@ -97,8 +97,8 @@ function prod_check_settings_form($form, &$form_state) {
|
|||||||
|
|
||||||
$form['prod_check_apc'] = array(
|
$form['prod_check_apc'] = array(
|
||||||
'#type' => 'fieldset',
|
'#type' => 'fieldset',
|
||||||
'#title' => t('Advanced APC settings'),
|
'#title' => t('Advanced APC/OPcache settings'),
|
||||||
'#description' => t('These settings are used in the !link functionality.', prod_check_link_array('advanced APC', 'admin/reports/status/apc')),
|
'#description' => t('These settings are used in the !link functionality.', prod_check_link_array('advanced APC', 'admin/reports/status/apc-opc')),
|
||||||
'#collapsible' => TRUE,
|
'#collapsible' => TRUE,
|
||||||
'#collapsed' => TRUE,
|
'#collapsed' => TRUE,
|
||||||
);
|
);
|
||||||
@ -106,7 +106,7 @@ function prod_check_settings_form($form, &$form_state) {
|
|||||||
// Cache full count threshold
|
// Cache full count threshold
|
||||||
$form['prod_check_apc']['prod_check_apc_expunge'] = array(
|
$form['prod_check_apc']['prod_check_apc_expunge'] = array(
|
||||||
'#type' => 'textfield',
|
'#type' => 'textfield',
|
||||||
'#title' => t('APC cache full count threshold'),
|
'#title' => t('APC/OPcache cache full count threshold'),
|
||||||
'#default_value' => variable_get('prod_check_apc_expunge', 0),
|
'#default_value' => variable_get('prod_check_apc_expunge', 0),
|
||||||
'#size' => 2,
|
'#size' => 2,
|
||||||
'#description' => t('Issue a critical error when the cache full count is greater than the number entered here.'),
|
'#description' => t('Issue a critical error when the cache full count is greater than the number entered here.'),
|
||||||
@ -428,7 +428,7 @@ function prod_check_settings_form_validate($form, &$form_state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!is_numeric($form_state['values']['prod_check_apc_expunge'])) {
|
if (!is_numeric($form_state['values']['prod_check_apc_expunge'])) {
|
||||||
form_set_error('prod_check_apc_expunge', t('APC Cache full count threshold should be numeric!'));
|
form_set_error('prod_check_apc_expunge', t('APC/OPcache Cache full count threshold should be numeric!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($form_state['values']['prod_check_enable_nagios']) && $form_state['values']['prod_check_enable_nagios']) {
|
if (isset($form_state['values']['prod_check_enable_nagios']) && $form_state['values']['prod_check_enable_nagios']) {
|
||||||
@ -461,9 +461,11 @@ function prod_check_settings_form_submit($form, &$form_state) {
|
|||||||
case t('Save configuration'):
|
case t('Save configuration'):
|
||||||
variable_set('prod_check_sitemail', $form_state['values']['prod_check_sitemail']);
|
variable_set('prod_check_sitemail', $form_state['values']['prod_check_sitemail']);
|
||||||
// PHP errors.
|
// PHP errors.
|
||||||
|
if (module_exists('dblog')) {
|
||||||
variable_set('prod_check_dblog_php', $form_state['values']['prod_check_dblog_php']);
|
variable_set('prod_check_dblog_php', $form_state['values']['prod_check_dblog_php']);
|
||||||
variable_set('prod_check_dblog_php_threshold', $form_state['values']['prod_check_dblog_php_threshold']);
|
variable_set('prod_check_dblog_php_threshold', $form_state['values']['prod_check_dblog_php_threshold']);
|
||||||
// APC.
|
}
|
||||||
|
// APC/OPcache.
|
||||||
variable_set('prod_check_apc_expunge', $form_state['values']['prod_check_apc_expunge']);
|
variable_set('prod_check_apc_expunge', $form_state['values']['prod_check_apc_expunge']);
|
||||||
variable_set('prod_check_apcuser', $form_state['values']['prod_check_apcuser']);
|
variable_set('prod_check_apcuser', $form_state['values']['prod_check_apcuser']);
|
||||||
if (!empty($form_state['values']['prod_check_apcpass'])) {
|
if (!empty($form_state['values']['prod_check_apcpass'])) {
|
||||||
@ -1031,12 +1033,23 @@ function _prod_check_dbstatus_pgsql($db_name, $details) {
|
|||||||
/**
|
/**
|
||||||
* Integration of the APC status page.
|
* Integration of the APC status page.
|
||||||
*/
|
*/
|
||||||
function prod_check_apc() {
|
function prod_check_apc_opc() {
|
||||||
|
// APC.
|
||||||
|
if (function_exists('apc_cache_info')) {
|
||||||
define('ADMIN_USERNAME', variable_get('prod_check_apcuser', 'apc'));
|
define('ADMIN_USERNAME', variable_get('prod_check_apcuser', 'apc'));
|
||||||
define('ADMIN_PASSWORD', variable_get('prod_check_apcpass', 'password'));
|
define('ADMIN_PASSWORD', variable_get('prod_check_apcpass', 'password'));
|
||||||
include(drupal_get_path('module', 'prod_check') . '/includes/prod_check.apc.inc');
|
include(drupal_get_path('module', 'prod_check') . '/includes/prod_check.apc.inc');
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
// OPcache.
|
||||||
|
elseif (function_exists('opcache_get_status')) {
|
||||||
|
include(drupal_get_path('module', 'prod_check') . '/includes/prod_check.opcache.inc');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return t('APC nor OPcache is installed on this webserver!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration of the Memcache status page.
|
* Integration of the Memcache status page.
|
||||||
|
@ -0,0 +1,502 @@
|
|||||||
|
<?php
|
||||||
|
function opcache_get_status() {
|
||||||
|
return array (
|
||||||
|
'opcache_enabled' => true,
|
||||||
|
'cache_full' => false,
|
||||||
|
'memory_usage' =>
|
||||||
|
array (
|
||||||
|
'used_memory' => 12028872,
|
||||||
|
'free_memory' => 4235696,
|
||||||
|
'wasted_memory' => 512648,
|
||||||
|
'current_wasted_percentage' => 3.0556201934814,
|
||||||
|
),
|
||||||
|
'opcache_statistics' =>
|
||||||
|
array (
|
||||||
|
'num_cached_scripts' => 59,
|
||||||
|
'num_cached_keys' => 78,
|
||||||
|
'max_cached_keys' => 223,
|
||||||
|
'hits' => 66817,
|
||||||
|
'last_restart_time' => 0,
|
||||||
|
'misses' => 126,
|
||||||
|
'blacklist_misses' => 0,
|
||||||
|
'blacklist_miss_ratio' => 0,
|
||||||
|
'opcache_hit_rate' => 99.81178017119,
|
||||||
|
'oom_restarts' => 0,
|
||||||
|
'manual_restarts' => 0,
|
||||||
|
'hash_restarts' => 0,
|
||||||
|
),
|
||||||
|
'scripts' =>
|
||||||
|
array (
|
||||||
|
'/var/www/phpweb/manual/en/toc/faq.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/manual/en/toc/faq.inc',
|
||||||
|
'hits' => 9,
|
||||||
|
'memory_consumption' => 5680,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1363345905,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/downloads.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/downloads.php',
|
||||||
|
'hits' => 86,
|
||||||
|
'memory_consumption' => 9488,
|
||||||
|
'last_used' => 'Sat Mar 16 12:03:47 2013',
|
||||||
|
'last_used_timestamp' => 1363460627,
|
||||||
|
'timestamp' => 1355102402,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/languages.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/languages.inc',
|
||||||
|
'hits' => 5605,
|
||||||
|
'memory_consumption' => 16984,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1362994804,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/header.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/header.inc',
|
||||||
|
'hits' => 9,
|
||||||
|
'memory_consumption' => 20352,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1357938001,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/manual/en/toc/getting-started.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/manual/en/toc/getting-started.inc',
|
||||||
|
'hits' => 9,
|
||||||
|
'memory_consumption' => 1936,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1363345409,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/manual/en/faq.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/manual/en/faq.php',
|
||||||
|
'hits' => 122,
|
||||||
|
'memory_consumption' => 5152,
|
||||||
|
'last_used' => 'Sat Mar 16 12:06:15 2013',
|
||||||
|
'last_used_timestamp' => 1363460775,
|
||||||
|
'timestamp' => 1363345906,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/footer.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/footer.inc',
|
||||||
|
'hits' => 9,
|
||||||
|
'memory_consumption' => 1976,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1347648001,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/site.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/site.inc',
|
||||||
|
'hits' => 5605,
|
||||||
|
'memory_consumption' => 63488,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1354724402,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/mirrors.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/mirrors.inc',
|
||||||
|
'hits' => 5605,
|
||||||
|
'memory_consumption' => 96160,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1363419613,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/manual/en/toc/refs.basic.vartype.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/manual/en/toc/refs.basic.vartype.inc',
|
||||||
|
'hits' => 9,
|
||||||
|
'memory_consumption' => 5032,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1363345844,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/layout.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/layout.inc',
|
||||||
|
'hits' => 5605,
|
||||||
|
'memory_consumption' => 145704,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1356610801,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/sites.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/sites.php',
|
||||||
|
'hits' => 73,
|
||||||
|
'memory_consumption' => 2024,
|
||||||
|
'last_used' => 'Sat Mar 16 12:10:10 2013',
|
||||||
|
'last_used_timestamp' => 1363461010,
|
||||||
|
'timestamp' => 1354724402,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/search.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/search.php',
|
||||||
|
'hits' => 3083,
|
||||||
|
'memory_consumption' => 19728,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1347648005,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/manual/en/toc/langref.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/manual/en/toc/langref.inc',
|
||||||
|
'hits' => 49,
|
||||||
|
'memory_consumption' => 7416,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1363345411,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/manual/en/toc/index.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/manual/en/toc/index.inc',
|
||||||
|
'hits' => 132,
|
||||||
|
'memory_consumption' => 4680,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1363345409,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/docs.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/docs.php',
|
||||||
|
'hits' => 73,
|
||||||
|
'memory_consumption' => 4536,
|
||||||
|
'last_used' => 'Sat Mar 16 12:04:36 2013',
|
||||||
|
'last_used_timestamp' => 1363460676,
|
||||||
|
'timestamp' => 1347648000,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/shared-manual.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/shared-manual.inc',
|
||||||
|
'hits' => 122,
|
||||||
|
'memory_consumption' => 107688,
|
||||||
|
'last_used' => 'Sat Mar 16 12:06:15 2013',
|
||||||
|
'last_used_timestamp' => 1363460775,
|
||||||
|
'timestamp' => 1357938001,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/mozopensearch.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/mozopensearch.inc',
|
||||||
|
'hits' => 14,
|
||||||
|
'memory_consumption' => 1232,
|
||||||
|
'last_used' => 'Sat Mar 16 12:00:34 2013',
|
||||||
|
'last_used_timestamp' => 1363460434,
|
||||||
|
'timestamp' => 1347648001,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/ip-to-country.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/ip-to-country.inc',
|
||||||
|
'hits' => 5605,
|
||||||
|
'memory_consumption' => 21840,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1347648001,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/version.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/version.inc',
|
||||||
|
'hits' => 775,
|
||||||
|
'memory_consumption' => 7880,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1363321202,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/errors.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/errors.inc',
|
||||||
|
'hits' => 691,
|
||||||
|
'memory_consumption' => 59888,
|
||||||
|
'last_used' => 'Sat Mar 16 12:10:33 2013',
|
||||||
|
'last_used_timestamp' => 1363461033,
|
||||||
|
'timestamp' => 1347648001,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/countries.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/countries.inc',
|
||||||
|
'hits' => 5605,
|
||||||
|
'memory_consumption' => 31184,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1363419614,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/error.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/error.php',
|
||||||
|
'hits' => 691,
|
||||||
|
'memory_consumption' => 61952,
|
||||||
|
'last_used' => 'Sat Mar 16 12:10:33 2013',
|
||||||
|
'last_used_timestamp' => 1363461033,
|
||||||
|
'timestamp' => 1347648000,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/manual/en/toc/refs.basic.text.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/manual/en/toc/refs.basic.text.inc',
|
||||||
|
'hits' => 9,
|
||||||
|
'memory_consumption' => 3312,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1363345831,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/loadavg.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/loadavg.inc',
|
||||||
|
'hits' => 3775,
|
||||||
|
'memory_consumption' => 12184,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1354738801,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/prepend.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/prepend.inc',
|
||||||
|
'hits' => 5605,
|
||||||
|
'memory_consumption' => 23432,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1347648001,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/o.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/o.php',
|
||||||
|
'hits' => 1,
|
||||||
|
'memory_consumption' => 13424,
|
||||||
|
'last_used' => 'Sat Mar 16 18:11:21 2013',
|
||||||
|
'last_used_timestamp' => 1363482681,
|
||||||
|
'timestamp' => 1363482654,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/pregen-events.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/pregen-events.inc',
|
||||||
|
'hits' => 1141,
|
||||||
|
'memory_consumption' => 840,
|
||||||
|
'last_used' => 'Sat Mar 16 12:15:07 2013',
|
||||||
|
'last_used_timestamp' => 1363461307,
|
||||||
|
'timestamp' => 1363419615,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/opcache.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/opcache.php',
|
||||||
|
'hits' => 0,
|
||||||
|
'memory_consumption' => 13944,
|
||||||
|
'last_used' => 'Sun Mar 17 01:22:31 2013',
|
||||||
|
'last_used_timestamp' => 1363508551,
|
||||||
|
'timestamp' => 1363508542,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/manual/en/toc/refs.calendar.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/manual/en/toc/refs.calendar.inc',
|
||||||
|
'hits' => 9,
|
||||||
|
'memory_consumption' => 2264,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1363345437,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/manual/en/toc/security.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/manual/en/toc/security.inc',
|
||||||
|
'hits' => 19,
|
||||||
|
'memory_consumption' => 5352,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1363345419,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/pregen-news.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/pregen-news.inc',
|
||||||
|
'hits' => 1161,
|
||||||
|
'memory_consumption' => 57896,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1363419615,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/my.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/my.php',
|
||||||
|
'hits' => 34,
|
||||||
|
'memory_consumption' => 22640,
|
||||||
|
'last_used' => 'Sat Mar 16 12:15:15 2013',
|
||||||
|
'last_used_timestamp' => 1363461315,
|
||||||
|
'timestamp' => 1354724402,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/pregen-confs.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/pregen-confs.inc',
|
||||||
|
'hits' => 678,
|
||||||
|
'memory_consumption' => 1400,
|
||||||
|
'last_used' => 'Sat Mar 16 12:02:49 2013',
|
||||||
|
'last_used_timestamp' => 1363460569,
|
||||||
|
'timestamp' => 1363419615,
|
||||||
|
),
|
||||||
|
'/var/www/index.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/index.php',
|
||||||
|
'hits' => 1,
|
||||||
|
'memory_consumption' => 744,
|
||||||
|
'last_used' => 'Sat Mar 16 12:01:20 2013',
|
||||||
|
'last_used_timestamp' => 1363460480,
|
||||||
|
'timestamp' => 1358644238,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/index-stable.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/index-stable.php',
|
||||||
|
'hits' => 679,
|
||||||
|
'memory_consumption' => 22208,
|
||||||
|
'last_used' => 'Sat Mar 16 12:02:49 2013',
|
||||||
|
'last_used_timestamp' => 1363460569,
|
||||||
|
'timestamp' => 1347648003,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/conferences/index.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/conferences/index.php',
|
||||||
|
'hits' => 462,
|
||||||
|
'memory_consumption' => 3872,
|
||||||
|
'last_used' => 'Sat Mar 16 12:15:07 2013',
|
||||||
|
'last_used_timestamp' => 1363461307,
|
||||||
|
'timestamp' => 1347648000,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/support.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/support.php',
|
||||||
|
'hits' => 73,
|
||||||
|
'memory_consumption' => 1912,
|
||||||
|
'last_used' => 'Sat Mar 16 12:06:40 2013',
|
||||||
|
'last_used_timestamp' => 1363460800,
|
||||||
|
'timestamp' => 1347648005,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/op.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/op.php',
|
||||||
|
'hits' => 0,
|
||||||
|
'memory_consumption' => 1448,
|
||||||
|
'last_used' => 'Sun Mar 17 01:34:33 2013',
|
||||||
|
'last_used_timestamp' => 1363509273,
|
||||||
|
'timestamp' => 1363509263,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/posttohost.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/posttohost.inc',
|
||||||
|
'hits' => 342,
|
||||||
|
'memory_consumption' => 3824,
|
||||||
|
'last_used' => 'Sat Mar 16 12:09:18 2013',
|
||||||
|
'last_used_timestamp' => 1363460958,
|
||||||
|
'timestamp' => 1347648001,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/langchooser.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/langchooser.inc',
|
||||||
|
'hits' => 5605,
|
||||||
|
'memory_consumption' => 23784,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1347648001,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/manual-lookup.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/manual-lookup.inc',
|
||||||
|
'hits' => 624,
|
||||||
|
'memory_consumption' => 26648,
|
||||||
|
'last_used' => 'Sat Mar 16 12:10:33 2013',
|
||||||
|
'last_used_timestamp' => 1363461033,
|
||||||
|
'timestamp' => 1354750802,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/mailing-lists.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/mailing-lists.php',
|
||||||
|
'hits' => 342,
|
||||||
|
'memory_consumption' => 31576,
|
||||||
|
'last_used' => 'Sat Mar 16 12:09:18 2013',
|
||||||
|
'last_used_timestamp' => 1363460958,
|
||||||
|
'timestamp' => 1361200802,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/last_updated.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/last_updated.inc',
|
||||||
|
'hits' => 5605,
|
||||||
|
'memory_consumption' => 840,
|
||||||
|
'last_used' => 'Sat Mar 16 12:16:31 2013',
|
||||||
|
'last_used_timestamp' => 1363461391,
|
||||||
|
'timestamp' => 1363419675,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/include/email-validation.inc' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/include/email-validation.inc',
|
||||||
|
'hits' => 342,
|
||||||
|
'memory_consumption' => 9168,
|
||||||
|
'last_used' => 'Sat Mar 16 12:09:18 2013',
|
||||||
|
'last_used_timestamp' => 1363460958,
|
||||||
|
'timestamp' => 1362175205,
|
||||||
|
),
|
||||||
|
'/var/www/phpweb/index.php' =>
|
||||||
|
array (
|
||||||
|
'full_path' => '/var/www/phpweb/index.php',
|
||||||
|
'hits' => 679,
|
||||||
|
'memory_consumption' => 1840,
|
||||||
|
'last_used' => 'Sat Mar 16 12:02:49 2013',
|
||||||
|
'last_used_timestamp' => 1363460569,
|
||||||
|
'timestamp' => 1347648003,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function opcache_get_configuration() {
|
||||||
|
return array (
|
||||||
|
'directives' =>
|
||||||
|
array (
|
||||||
|
'opcache.enable' => true,
|
||||||
|
'opcache.enable_cli' => false,
|
||||||
|
'opcache.use_cwd' => true,
|
||||||
|
'opcache.validate_timestamps' => true,
|
||||||
|
'opcache.inherited_hack' => true,
|
||||||
|
'opcache.dups_fix' => false,
|
||||||
|
'opcache.revalidate_path' => false,
|
||||||
|
'opcache.log_verbosity_level' => 4,
|
||||||
|
'opcache.memory_consumption' => 16777216,
|
||||||
|
'opcache.interned_strings_buffer' => 8,
|
||||||
|
'opcache.max_accelerated_files' => 200,
|
||||||
|
'opcache.max_wasted_percentage' => 0.05,
|
||||||
|
'opcache.consistency_checks' => 0,
|
||||||
|
'opcache.force_restart_timeout' => 180,
|
||||||
|
'opcache.revalidate_freq' => 0,
|
||||||
|
'opcache.preferred_memory_model' => '',
|
||||||
|
'opcache.blacklist_filename' => '/etc/zo_blacklist.txt',
|
||||||
|
'opcache.max_file_size' => 0,
|
||||||
|
'opcache.error_log' => '',
|
||||||
|
'opcache.protect_memory' => false,
|
||||||
|
'opcache.save_comments' => true,
|
||||||
|
'opcache.load_comments' => true,
|
||||||
|
'opcache.fast_shutdown' => true,
|
||||||
|
'opcache.enable_file_override' => false,
|
||||||
|
'opcache.optimization_level' => 4294967295,
|
||||||
|
),
|
||||||
|
'version' =>
|
||||||
|
array (
|
||||||
|
'version' => '7.0.1-dev',
|
||||||
|
'opcache_product_name' => 'Zend Optimizer+',
|
||||||
|
),
|
||||||
|
'blacklist' =>
|
||||||
|
array (
|
||||||
|
0 => '/var/www/www.php.net/manual/es',
|
||||||
|
1 => '/var/www/www.php.net/manual/it',
|
||||||
|
2 => '/var/www/www.php.net/manual/bg',
|
||||||
|
3 => '/var/www/www.php.net/manual/fa',
|
||||||
|
4 => '/var/www/www.php.net/manual/fr',
|
||||||
|
5 => '/var/www/www.php.net/manual/kr',
|
||||||
|
6 => '/var/www/www.php.net/manual/pt_BR',
|
||||||
|
7 => '/var/www/www.php.net/manual/tr',
|
||||||
|
8 => '/var/www/www.php.net/manual/de',
|
||||||
|
9 => '/var/www/www.php.net/manual/ro',
|
||||||
|
10 => '/var/www/www.php.net/manual/ru',
|
||||||
|
11 => '/var/www/www.php.net/manual/zh',
|
||||||
|
12 => '/var/www/www.php.net/manual/ja',
|
||||||
|
13 => '/var/www/www.php.net/manual/pl',
|
||||||
|
14 => '/var/www/www.php.net/manual/sr',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,748 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Taken from https://github.com/rlerdorf/opcache-status
|
||||||
|
*/
|
||||||
|
|
||||||
|
define('THOUSAND_SEPARATOR',true);
|
||||||
|
|
||||||
|
if (!extension_loaded('Zend OPcache')) {
|
||||||
|
echo '<div style="background-color: #F2DEDE; color: #B94A48; padding: 1em;">You do not have the Zend OPcache extension loaded, sample data is being shown instead.</div>';
|
||||||
|
require 'prod_check.opcache.data_sample.inc';
|
||||||
|
}
|
||||||
|
|
||||||
|
class OpCacheDataModel
|
||||||
|
{
|
||||||
|
private $_configuration;
|
||||||
|
private $_status;
|
||||||
|
private $_d3Scripts = array();
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->_configuration = opcache_get_configuration();
|
||||||
|
$this->_status = opcache_get_status();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPageTitle()
|
||||||
|
{
|
||||||
|
return 'PHP ' . phpversion() . " with OpCache {$this->_configuration['version']['version']}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStatusDataRows()
|
||||||
|
{
|
||||||
|
$rows = array();
|
||||||
|
foreach ($this->_status as $key => $value) {
|
||||||
|
if ($key === 'scripts') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($value)) {
|
||||||
|
foreach ($value as $k => $v) {
|
||||||
|
if ($v === false) {
|
||||||
|
$value = 'false';
|
||||||
|
}
|
||||||
|
if ($v === true) {
|
||||||
|
$value = 'true';
|
||||||
|
}
|
||||||
|
if ($k === 'used_memory' || $k === 'free_memory' || $k === 'wasted_memory') {
|
||||||
|
$v = $this->_size_for_humans(
|
||||||
|
$v
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ($k === 'current_wasted_percentage' || $k === 'opcache_hit_rate') {
|
||||||
|
$v = number_format(
|
||||||
|
$v,
|
||||||
|
2
|
||||||
|
) . '%';
|
||||||
|
}
|
||||||
|
if ($k === 'blacklist_miss_ratio') {
|
||||||
|
$v = number_format($v, 2) . '%';
|
||||||
|
}
|
||||||
|
if ($k === 'start_time' || $k === 'last_restart_time') {
|
||||||
|
$v = ($v ? date(DATE_RFC822, $v) : 'never');
|
||||||
|
}
|
||||||
|
if (THOUSAND_SEPARATOR === true && is_int($v)) {
|
||||||
|
$v = number_format($v);
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = "<tr><th>$k</th><td>$v</td></tr>\n";
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($value === false) {
|
||||||
|
$value = 'false';
|
||||||
|
}
|
||||||
|
if ($value === true) {
|
||||||
|
$value = 'true';
|
||||||
|
}
|
||||||
|
$rows[] = "<tr><th>$key</th><td>$value</td></tr>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode("\n", $rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConfigDataRows()
|
||||||
|
{
|
||||||
|
$rows = array();
|
||||||
|
foreach ($this->_configuration['directives'] as $key => $value) {
|
||||||
|
if ($value === false) {
|
||||||
|
$value = 'false';
|
||||||
|
}
|
||||||
|
if ($value === true) {
|
||||||
|
$value = 'true';
|
||||||
|
}
|
||||||
|
if ($key == 'opcache.memory_consumption') {
|
||||||
|
$value = $this->_size_for_humans($value);
|
||||||
|
}
|
||||||
|
$rows[] = "<tr><th>$key</th><td>$value</td></tr>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode("\n", $rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getScriptStatusRows()
|
||||||
|
{
|
||||||
|
foreach ($this->_status['scripts'] as $key => $data) {
|
||||||
|
$dirs[dirname($key)][basename($key)] = $data;
|
||||||
|
$this->_arrayPset($this->_d3Scripts, $key, array(
|
||||||
|
'name' => basename($key),
|
||||||
|
'size' => $data['memory_consumption'],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
asort($dirs);
|
||||||
|
|
||||||
|
$basename = '';
|
||||||
|
while (true) {
|
||||||
|
if (count($this->_d3Scripts) !=1) break;
|
||||||
|
$basename .= DIRECTORY_SEPARATOR . key($this->_d3Scripts);
|
||||||
|
$this->_d3Scripts = reset($this->_d3Scripts);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->_d3Scripts = $this->_processPartition($this->_d3Scripts, $basename);
|
||||||
|
$id = 1;
|
||||||
|
|
||||||
|
$rows = array();
|
||||||
|
foreach ($dirs as $dir => $files) {
|
||||||
|
$count = count($files);
|
||||||
|
$file_plural = $count > 1 ? 's' : null;
|
||||||
|
$m = 0;
|
||||||
|
foreach ($files as $file => $data) {
|
||||||
|
$m += $data["memory_consumption"];
|
||||||
|
}
|
||||||
|
$m = $this->_size_for_humans($m);
|
||||||
|
|
||||||
|
if ($count > 1) {
|
||||||
|
$rows[] = '<tr>';
|
||||||
|
$rows[] = "<th class=\"clickable\" id=\"head-{$id}\" colspan=\"3\" onclick=\"toggleVisible('#head-{$id}', '#row-{$id}')\">{$dir} ({$count} file{$file_plural}, {$m})</th>";
|
||||||
|
$rows[] = '</tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($files as $file => $data) {
|
||||||
|
$rows[] = "<tr id=\"row-{$id}\">";
|
||||||
|
$rows[] = "<td>" . $this->_format_value($data["hits"]) . "</td>";
|
||||||
|
$rows[] = "<td>" . $this->_size_for_humans($data["memory_consumption"]) . "</td>";
|
||||||
|
$rows[] = $count > 1 ? "<td>{$file}</td>" : "<td>{$dir}/{$file}</td>";
|
||||||
|
$rows[] = '</tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
++$id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode("\n", $rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getScriptStatusCount()
|
||||||
|
{
|
||||||
|
return count($this->_status["scripts"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGraphDataSetJson()
|
||||||
|
{
|
||||||
|
$dataset = array();
|
||||||
|
$dataset['memory'] = array(
|
||||||
|
$this->_status['memory_usage']['used_memory'],
|
||||||
|
$this->_status['memory_usage']['free_memory'],
|
||||||
|
$this->_status['memory_usage']['wasted_memory'],
|
||||||
|
);
|
||||||
|
|
||||||
|
$dataset['keys'] = array(
|
||||||
|
$this->_status['opcache_statistics']['num_cached_keys'],
|
||||||
|
$this->_status['opcache_statistics']['max_cached_keys'] - $this->_status['opcache_statistics']['num_cached_keys'],
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
$dataset['hits'] = array(
|
||||||
|
$this->_status['opcache_statistics']['misses'],
|
||||||
|
$this->_status['opcache_statistics']['hits'],
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
$dataset['restarts'] = array(
|
||||||
|
$this->_status['opcache_statistics']['oom_restarts'],
|
||||||
|
$this->_status['opcache_statistics']['manual_restarts'],
|
||||||
|
$this->_status['opcache_statistics']['hash_restarts'],
|
||||||
|
);
|
||||||
|
|
||||||
|
if (THOUSAND_SEPARATOR === true) {
|
||||||
|
$dataset['TSEP'] = 1;
|
||||||
|
} else {
|
||||||
|
$dataset['TSEP'] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_encode($dataset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHumanUsedMemory()
|
||||||
|
{
|
||||||
|
return $this->_size_for_humans($this->getUsedMemory());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHumanFreeMemory()
|
||||||
|
{
|
||||||
|
return $this->_size_for_humans($this->getFreeMemory());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHumanWastedMemory()
|
||||||
|
{
|
||||||
|
return $this->_size_for_humans($this->getWastedMemory());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUsedMemory()
|
||||||
|
{
|
||||||
|
return $this->_status['memory_usage']['used_memory'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFreeMemory()
|
||||||
|
{
|
||||||
|
return $this->_status['memory_usage']['free_memory'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWastedMemory()
|
||||||
|
{
|
||||||
|
return $this->_status['memory_usage']['wasted_memory'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWastedMemoryPercentage()
|
||||||
|
{
|
||||||
|
return number_format($this->_status['memory_usage']['current_wasted_percentage'], 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getD3Scripts()
|
||||||
|
{
|
||||||
|
return $this->_d3Scripts;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function _processPartition($value, $name = null)
|
||||||
|
{
|
||||||
|
if (array_key_exists('size', $value)) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$array = array('name' => $name,'children' => array());
|
||||||
|
|
||||||
|
foreach ($value as $k => $v) {
|
||||||
|
$array['children'][] = $this->_processPartition($v, $k);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function _format_value($value)
|
||||||
|
{
|
||||||
|
if (THOUSAND_SEPARATOR === true) {
|
||||||
|
return number_format($value);
|
||||||
|
} else {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function _size_for_humans($bytes)
|
||||||
|
{
|
||||||
|
if ($bytes > 1048576) {
|
||||||
|
return sprintf('%.2f MB', $bytes / 1048576);
|
||||||
|
} else {
|
||||||
|
if ($bytes > 1024) {
|
||||||
|
return sprintf('%.2f kB', $bytes / 1024);
|
||||||
|
} else {
|
||||||
|
return sprintf('%d bytes', $bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Borrowed from Laravel
|
||||||
|
private function _arrayPset(&$array, $key, $value)
|
||||||
|
{
|
||||||
|
if (is_null($key)) return $array = $value;
|
||||||
|
$keys = explode(DIRECTORY_SEPARATOR, ltrim($key, DIRECTORY_SEPARATOR));
|
||||||
|
while (count($keys) > 1) {
|
||||||
|
$key = array_shift($keys);
|
||||||
|
if ( ! isset($array[$key]) || ! is_array($array[$key])) {
|
||||||
|
$array[$key] = array();
|
||||||
|
}
|
||||||
|
$array =& $array[$key];
|
||||||
|
}
|
||||||
|
$array[array_shift($keys)] = $value;
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$dataModel = new OpCacheDataModel();
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
width: 1024px;
|
||||||
|
margin: auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:nth-child(even) {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.capitalize {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab label {
|
||||||
|
background: #eee;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
margin-left: -1px;
|
||||||
|
position: relative;
|
||||||
|
left: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab [type=radio] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab th, .tab td {
|
||||||
|
padding: 8px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
position: absolute;
|
||||||
|
top: 28px;
|
||||||
|
left: 0;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
height: 450px;
|
||||||
|
width: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content th, .tab:nth-child(3) td {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content td {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type=radio]:checked ~ label {
|
||||||
|
background: white;
|
||||||
|
border-bottom: 1px solid white;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type=radio]:checked ~ label ~ .content {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#graph {
|
||||||
|
float: right;
|
||||||
|
width: 40%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#graph > form {
|
||||||
|
position: absolute;
|
||||||
|
right: 60px;
|
||||||
|
top: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#graph > svg {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#stats {
|
||||||
|
position: absolute;
|
||||||
|
right: 125px;
|
||||||
|
top: 145px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#stats th, #stats td {
|
||||||
|
padding: 6px 10px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#partition {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 10;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background: #ddd;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#close-partition {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 20;
|
||||||
|
right: 15px;
|
||||||
|
top: 15px;
|
||||||
|
background: #f9373d;
|
||||||
|
color: #fff;
|
||||||
|
padding: 12px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#close-partition:hover {
|
||||||
|
background: #D32F33;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#partition rect {
|
||||||
|
stroke: #fff;
|
||||||
|
fill: #aaa;
|
||||||
|
fill-opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#partition rect.parent {
|
||||||
|
cursor: pointer;
|
||||||
|
fill: steelblue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#partition text {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.0.1/d3.v3.min.js"></script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
|
||||||
|
<script>
|
||||||
|
var hidden = {};
|
||||||
|
function toggleVisible(head, row) {
|
||||||
|
if (!hidden[row]) {
|
||||||
|
d3.selectAll(row).transition().style('display', 'none');
|
||||||
|
hidden[row] = true;
|
||||||
|
d3.select(head).transition().style('color', '#ccc');
|
||||||
|
} else {
|
||||||
|
d3.selectAll(row).transition().style('display');
|
||||||
|
hidden[row] = false;
|
||||||
|
d3.select(head).transition().style('color', '#000');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<title><?php echo $dataModel->getPageTitle(); ?></title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
<h1><?php echo $dataModel->getPageTitle(); ?></h1>
|
||||||
|
|
||||||
|
<div class="tabs">
|
||||||
|
|
||||||
|
<div class="tab">
|
||||||
|
<input type="radio" id="tab-status" name="tab-group-1" checked>
|
||||||
|
<label for="tab-status">Status</label>
|
||||||
|
<div class="content">
|
||||||
|
<table>
|
||||||
|
<?php echo $dataModel->getStatusDataRows(); ?>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tab">
|
||||||
|
<input type="radio" id="tab-config" name="tab-group-1">
|
||||||
|
<label for="tab-config">Configuration</label>
|
||||||
|
<div class="content">
|
||||||
|
<table>
|
||||||
|
<?php echo $dataModel->getConfigDataRows(); ?>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tab">
|
||||||
|
<input type="radio" id="tab-scripts" name="tab-group-1">
|
||||||
|
<label for="tab-scripts">Scripts (<?php echo $dataModel->getScriptStatusCount(); ?>)</label>
|
||||||
|
<div class="content">
|
||||||
|
<table style="font-size:0.8em;">
|
||||||
|
<tr>
|
||||||
|
<th width="10%">Hits</th>
|
||||||
|
<th width="20%">Memory</th>
|
||||||
|
<th width="70%">Path</th>
|
||||||
|
</tr>
|
||||||
|
<?php echo $dataModel->getScriptStatusRows(); ?>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tab">
|
||||||
|
<input type="radio" id="tab-visualise" name="tab-group-1">
|
||||||
|
<label for="tab-visualise">Visualise Partition</label>
|
||||||
|
<div class="content"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="graph">
|
||||||
|
<form>
|
||||||
|
<label><input type="radio" name="dataset" value="memory" checked> Memory</label>
|
||||||
|
<label><input type="radio" name="dataset" value="keys"> Keys</label>
|
||||||
|
<label><input type="radio" name="dataset" value="hits"> Hits</label>
|
||||||
|
<label><input type="radio" name="dataset" value="restarts"> Restarts</label>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="stats"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="close-partition">✖ Close Visualisation</div>
|
||||||
|
<div id="partition"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var dataset = <?php echo $dataModel->getGraphDataSetJson(); ?>;
|
||||||
|
|
||||||
|
var width = 400,
|
||||||
|
height = 400,
|
||||||
|
radius = Math.min(width, height) / 2,
|
||||||
|
colours = ['#B41F1F', '#1FB437', '#ff7f0e'];
|
||||||
|
|
||||||
|
d3.scale.customColours = function() {
|
||||||
|
return d3.scale.ordinal().range(colours);
|
||||||
|
};
|
||||||
|
|
||||||
|
var colour = d3.scale.customColours();
|
||||||
|
var pie = d3.layout.pie().sort(null);
|
||||||
|
|
||||||
|
var arc = d3.svg.arc().innerRadius(radius - 20).outerRadius(radius - 50);
|
||||||
|
var svg = d3.select("#graph").append("svg")
|
||||||
|
.attr("width", width)
|
||||||
|
.attr("height", height)
|
||||||
|
.append("g")
|
||||||
|
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
|
||||||
|
|
||||||
|
var path = svg.selectAll("path")
|
||||||
|
.data(pie(dataset.memory))
|
||||||
|
.enter().append("path")
|
||||||
|
.attr("fill", function(d, i) { return colour(i); })
|
||||||
|
.attr("d", arc)
|
||||||
|
.each(function(d) { this._current = d; }); // store the initial values
|
||||||
|
|
||||||
|
d3.selectAll("input").on("change", change);
|
||||||
|
set_text("memory");
|
||||||
|
|
||||||
|
function set_text(t) {
|
||||||
|
if (t === "memory") {
|
||||||
|
d3.select("#stats").html(
|
||||||
|
"<table><tr><th style='background:#B41F1F;'>Used</th><td><?php echo $dataModel->getHumanUsedMemory()?></td></tr>"+
|
||||||
|
"<tr><th style='background:#1FB437;'>Free</th><td><?php echo $dataModel->getHumanFreeMemory()?></td></tr>"+
|
||||||
|
"<tr><th style='background:#ff7f0e;' rowspan=\"2\">Wasted</th><td><?php echo $dataModel->getHumanWastedMemory()?></td></tr>"+
|
||||||
|
"<tr><td><?php echo $dataModel->getWastedMemoryPercentage()?>%</td></tr></table>"
|
||||||
|
);
|
||||||
|
} else if (t === "keys") {
|
||||||
|
d3.select("#stats").html(
|
||||||
|
"<table><tr><th style='background:#B41F1F;'>Cached keys</th><td>"+format_value(dataset[t][0])+"</td></tr>"+
|
||||||
|
"<tr><th style='background:#1FB437;'>Free Keys</th><td>"+format_value(dataset[t][1])+"</td></tr></table>"
|
||||||
|
);
|
||||||
|
} else if (t === "hits") {
|
||||||
|
d3.select("#stats").html(
|
||||||
|
"<table><tr><th style='background:#B41F1F;'>Misses</th><td>"+format_value(dataset[t][0])+"</td></tr>"+
|
||||||
|
"<tr><th style='background:#1FB437;'>Cache Hits</th><td>"+format_value(dataset[t][1])+"</td></tr></table>"
|
||||||
|
);
|
||||||
|
} else if (t === "restarts") {
|
||||||
|
d3.select("#stats").html(
|
||||||
|
"<table><tr><th style='background:#B41F1F;'>Memory</th><td>"+dataset[t][0]+"</td></tr>"+
|
||||||
|
"<tr><th style='background:#1FB437;'>Manual</th><td>"+dataset[t][1]+"</td></tr>"+
|
||||||
|
"<tr><th style='background:#ff7f0e;'>Keys</th><td>"+dataset[t][2]+"</td></tr></table>"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function change() {
|
||||||
|
// Filter out any zero values to see if there is anything left
|
||||||
|
var remove_zero_values = dataset[this.value].filter(function(value) {
|
||||||
|
return value > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Skip if the value is undefined for some reason
|
||||||
|
if (typeof dataset[this.value] !== 'undefined' && remove_zero_values.length > 0) {
|
||||||
|
$('#graph').find('> svg').show();
|
||||||
|
path = path.data(pie(dataset[this.value])); // update the data
|
||||||
|
path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
|
||||||
|
// Hide the graph if we can't draw it correctly, not ideal but this works
|
||||||
|
} else {
|
||||||
|
$('#graph').find('> svg').hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
set_text(this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function arcTween(a) {
|
||||||
|
var i = d3.interpolate(this._current, a);
|
||||||
|
this._current = i(0);
|
||||||
|
return function(t) {
|
||||||
|
return arc(i(t));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function size_for_humans(bytes) {
|
||||||
|
if (bytes > 1048576) {
|
||||||
|
return (bytes/1048576).toFixed(2) + ' MB';
|
||||||
|
} else if (bytes > 1024) {
|
||||||
|
return (bytes/1024).toFixed(2) + ' KB';
|
||||||
|
} else return bytes + ' bytes';
|
||||||
|
}
|
||||||
|
|
||||||
|
function format_value(value) {
|
||||||
|
if (dataset["TSEP"] == 1) {
|
||||||
|
return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var w = window.innerWidth,
|
||||||
|
h = window.innerHeight,
|
||||||
|
x = d3.scale.linear().range([0, w]),
|
||||||
|
y = d3.scale.linear().range([0, h]);
|
||||||
|
|
||||||
|
var vis = d3.select("#partition")
|
||||||
|
.style("width", w + "px")
|
||||||
|
.style("height", h + "px")
|
||||||
|
.append("svg:svg")
|
||||||
|
.attr("width", w)
|
||||||
|
.attr("height", h);
|
||||||
|
|
||||||
|
var partition = d3.layout.partition()
|
||||||
|
.value(function(d) { return d.size; });
|
||||||
|
|
||||||
|
root = JSON.parse('<?php echo json_encode($dataModel->getD3Scripts()); ?>');
|
||||||
|
|
||||||
|
var g = vis.selectAll("g")
|
||||||
|
.data(partition.nodes(root))
|
||||||
|
.enter().append("svg:g")
|
||||||
|
.attr("transform", function(d) { return "translate(" + x(d.y) + "," + y(d.x) + ")"; })
|
||||||
|
.on("click", click);
|
||||||
|
|
||||||
|
var kx = w / root.dx,
|
||||||
|
ky = h / 1;
|
||||||
|
|
||||||
|
g.append("svg:rect")
|
||||||
|
.attr("width", root.dy * kx)
|
||||||
|
.attr("height", function(d) { return d.dx * ky; })
|
||||||
|
.attr("class", function(d) { return d.children ? "parent" : "child"; });
|
||||||
|
|
||||||
|
g.append("svg:text")
|
||||||
|
.attr("transform", transform)
|
||||||
|
.attr("dy", ".35em")
|
||||||
|
.style("opacity", function(d) { return d.dx * ky > 12 ? 1 : 0; })
|
||||||
|
.text(function(d) { return d.name; })
|
||||||
|
|
||||||
|
d3.select(window)
|
||||||
|
.on("click", function() { click(root); })
|
||||||
|
|
||||||
|
function click(d) {
|
||||||
|
if (!d.children) return;
|
||||||
|
|
||||||
|
kx = (d.y ? w - 40 : w) / (1 - d.y);
|
||||||
|
ky = h / d.dx;
|
||||||
|
x.domain([d.y, 1]).range([d.y ? 40 : 0, w]);
|
||||||
|
y.domain([d.x, d.x + d.dx]);
|
||||||
|
|
||||||
|
var t = g.transition()
|
||||||
|
.duration(d3.event.altKey ? 7500 : 750)
|
||||||
|
.attr("transform", function(d) { return "translate(" + x(d.y) + "," + y(d.x) + ")"; });
|
||||||
|
|
||||||
|
t.select("rect")
|
||||||
|
.attr("width", d.dy * kx)
|
||||||
|
.attr("height", function(d) { return d.dx * ky; });
|
||||||
|
|
||||||
|
t.select("text")
|
||||||
|
.attr("transform", transform)
|
||||||
|
.style("opacity", function(d) { return d.dx * ky > 12 ? 1 : 0; });
|
||||||
|
|
||||||
|
d3.event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
function transform(d) {
|
||||||
|
return "translate(8," + d.dx * ky / 2 + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
function handleVisualisationToggle(close) {
|
||||||
|
|
||||||
|
$('#partition, #close-partition').fadeToggle();
|
||||||
|
|
||||||
|
// Is the visualisation being closed? If so show the status tab again
|
||||||
|
if (close) {
|
||||||
|
|
||||||
|
$('#tab-visualise').removeAttr('checked');
|
||||||
|
$('#tab-status').trigger('click');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$('label[for="tab-visualise"], #close-partition').on('click', function() {
|
||||||
|
|
||||||
|
handleVisualisationToggle(($(this).attr('id') === 'close-partition'));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).keyup(function(e) {
|
||||||
|
|
||||||
|
if (e.keyCode == 27) handleVisualisationToggle(true);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -71,7 +71,7 @@ function my_module_additional_check($caller = 'internal') {
|
|||||||
$title = 'My modules settings';
|
$title = 'My modules settings';
|
||||||
$setting1 = t('Enable debug info');
|
$setting1 = t('Enable debug info');
|
||||||
$setting2 = t('Disable debug info');
|
$setting2 = t('Disable debug info');
|
||||||
$path = 'admin/settings/my-module-settings-page';
|
$path = 'admin/config/system/my-module-settings-page';
|
||||||
if ($caller != 'internal') {
|
if ($caller != 'internal') {
|
||||||
$path = PRODCHECK_BASEURL . $path;
|
$path = PRODCHECK_BASEURL . $path;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Simple database connection check that can be placed anywhere within a Drupal
|
||||||
|
* installation. Does NOT need to be in the root where index.php resides!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locate the actual Drupal root. Based on drush_locate_root().
|
||||||
|
*/
|
||||||
|
function locate_root() {
|
||||||
|
$drupal_root = FALSE;
|
||||||
|
|
||||||
|
$start_path = isset($_SERVER['PWD']) ? $_SERVER['PWD'] : '';
|
||||||
|
if (empty($start_path)) {
|
||||||
|
$start_path = getcwd();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array(TRUE, FALSE) as $follow_symlinks) {
|
||||||
|
$path = $start_path;
|
||||||
|
if ($follow_symlinks && is_link($path)) {
|
||||||
|
$path = realpath($path);
|
||||||
|
}
|
||||||
|
// Check the start path.
|
||||||
|
if (valid_root($path)) {
|
||||||
|
$drupal_root = $path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Move up dir by dir and check each.
|
||||||
|
while ($path = shift_path_up($path)) {
|
||||||
|
if ($follow_symlinks && is_link($path)) {
|
||||||
|
$path = realpath($path);
|
||||||
|
}
|
||||||
|
if (valid_root($path)) {
|
||||||
|
$drupal_root = $path;
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $drupal_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Based on the DrupalBoot*::valid_root() from Drush.
|
||||||
|
*/
|
||||||
|
function valid_root($path) {
|
||||||
|
if (!empty($path) && is_dir($path) && file_exists($path . '/index.php')) {
|
||||||
|
$candidate = 'includes/common.inc';
|
||||||
|
if (file_exists($path . '/' . $candidate) && file_exists($path . '/misc/drupal.js')) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Based on _drush_shift_path_up().
|
||||||
|
*/
|
||||||
|
function shift_path_up($path) {
|
||||||
|
if (empty($path)) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
$path = explode('/', $path);
|
||||||
|
// Move one directory up.
|
||||||
|
array_pop($path);
|
||||||
|
return implode('/', $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the actual database connection check.
|
||||||
|
*/
|
||||||
|
define('DRUPAL_ROOT', locate_root());
|
||||||
|
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
|
||||||
|
drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
|
||||||
|
|
||||||
|
$result = db_query('SELECT COUNT(filename) FROM {system}')->fetchField();
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
$msg = 'OK';
|
||||||
|
http_response_code(200);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
http_response_code(500);
|
||||||
|
$msg = 'NOK';
|
||||||
|
}
|
||||||
|
|
||||||
|
exit($msg);
|
@ -4,9 +4,9 @@ package = Monitoring
|
|||||||
core = 7.x
|
core = 7.x
|
||||||
configure = admin/config/system/prod-check
|
configure = admin/config/system/prod-check
|
||||||
|
|
||||||
; Information added by packaging script on 2013-11-25
|
; Information added by Drupal.org packaging script on 2015-08-04
|
||||||
version = "7.x-1.8"
|
version = "7.x-1.9"
|
||||||
core = "7.x"
|
core = "7.x"
|
||||||
project = "prod_check"
|
project = "prod_check"
|
||||||
datestamp = "1385405033"
|
datestamp = "1438700931"
|
||||||
|
|
||||||
|
@ -31,15 +31,15 @@ function prod_check_requirements($phase) {
|
|||||||
'title' => t('Production check'),
|
'title' => t('Production check'),
|
||||||
'value' => t('Site e-mail check not properly configured.'),
|
'value' => t('Site e-mail check not properly configured.'),
|
||||||
'severity' => REQUIREMENT_WARNING,
|
'severity' => REQUIREMENT_WARNING,
|
||||||
'description' => t('You have not changed the e-mail address on the prod-check !link. The Site e-mail check will not function properly. Please read the README.txt file.', prod_check_link_array('settings page', 'admin/settings/prod-check')),
|
'description' => t('You have not changed the e-mail address on the prod-check !link. The Site e-mail check will not function properly. Please read the README.txt file.', prod_check_link_array('settings page', 'admin/config/system/prod-check')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (function_exists('apc_cache_info') && variable_get('prod_check_apcpass', 'password') == 'password') {
|
if (function_exists('apc_cache_info') && variable_get('prod_check_apcpass', 'password') == 'password') {
|
||||||
$requirements['prod_check_apc'] = array(
|
$requirements['prod_check_apc_opc'] = array(
|
||||||
'title' => t('Production check'),
|
'title' => t('Production check'),
|
||||||
'value' => t('APC password not configured.'),
|
'value' => t('APC password not configured.'),
|
||||||
'severity' => REQUIREMENT_WARNING,
|
'severity' => REQUIREMENT_WARNING,
|
||||||
'description' => t('You have not !link for the APC status page. The page will function, but advanced options require that you set a password. Please read the README.txt file.', prod_check_link_array('changed the password', 'admin/settings/prod-check')),
|
'description' => t('You have not !link for the APC status page. The page will function, but advanced options require that you set a password. Please read the README.txt file.', prod_check_link_array('changed the password', 'admin/config/system/prod-check')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$nagios = variable_get('prod_check_enable_nagios', 0);
|
$nagios = variable_get('prod_check_enable_nagios', 0);
|
||||||
|
@ -43,20 +43,20 @@ function prod_check_help($path, $arg) {
|
|||||||
break;
|
break;
|
||||||
case 'admin/reports/prod-check':
|
case 'admin/reports/prod-check':
|
||||||
case 'admin/reports/prod-check/status':
|
case 'admin/reports/prod-check/status':
|
||||||
$output .= '<p>'.t('This is an overview of all checks performed by the <em>Production check</em> module and their status. You can click the links inside the report to jump to the module\'s settings page, or to go to the project page of a module, in case you need to download it for installation.').'</p>';
|
$output .= '<p>' . t("This is an overview of all checks performed by the <em>Production check</em> module and their status. You can click the links inside the report to jump to the module's settings page, or to go to the project page of a module, in case you need to download it for installation.") . '</p>';
|
||||||
break;
|
break;
|
||||||
case 'admin/config/system/prod-check':
|
case 'admin/config/system/prod-check':
|
||||||
$output .= '<p><strong>' . t('Sitemail check') . '</strong><br />';
|
$output .= '<p><strong>' . t('Sitemail check') . '</strong><br />';
|
||||||
$output .= t('The value entered here is used in a regular expression. Prod check will use it to see if the e-mail address you have entered in <em>Site information</em> is no longer a development e-mail address.') . '</p>';
|
$output .= t('The value entered here is used in a regular expression. Prod check will use it to see if the e-mail address you have entered in <em>Site information</em> is no longer a development e-mail address.') . '</p>';
|
||||||
$output .= '<p><strong>'.t('Advanced APC settings').'</strong><br />';
|
$output .= '<p><strong>' . t('Advanced APC/OPcache settings') . '</strong><br />';
|
||||||
$output .= t('Production check enables a <em>hidden</em> path where you can review your APC setup. This is absolutely unmissable if you want to properly setup APC and tune it specifically for your website.') . '</p>';
|
$output .= t('Production check enables a <em>hidden</em> path where you can review your APC setup. This is absolutely unmissable if you want to properly setup APC and tune it specifically for your website.') . '</p>';
|
||||||
$output .= '<p><strong>' . t('Enable XMLRPC API') . '</strong><br />';
|
$output .= '<p><strong>' . t('Enable XMLRPC API') . '</strong><br />';
|
||||||
$output .= t('By ticking this box, you open up the module\'s XMLRPC functions so they can be called by the <strong>Production monitor</strong> module for remote monitoring of your site. When enabling XMLRPC, you <strong>must</strong> enter an <strong>API key</strong> to secure the transfer of data. It\'s limited to 128 characters. A mixture of alphanumeric and special characters will increase security.').'</p>';
|
$output .= t("By ticking this box, you open up the module's XMLRPC functions so they can be called by the <strong>Production monitor</strong> module for remote monitoring of your site. When enabling XMLRPC, you <strong>must</strong> enter an <strong>API key</strong> to secure the transfer of data. It's limited to 128 characters. A mixture of alphanumeric and special characters will increase security.") . '</p>';
|
||||||
$output .= '<p><strong>' . t('Report module list every <em>x</em> at time <em>y</em>') . '</strong><br />';
|
$output .= '<p><strong>' . t('Report module list every <em>x</em> at time <em>y</em>') . '</strong><br />';
|
||||||
$output .= t('Select on which day of the week and at what time <em>Production check</em> is allowed to pass the module list of the site it is on to <em>Production monitor</em>. Set this carefully, as the amount data being transfered is quite big!') . '<br />';
|
$output .= t('Select on which day of the week and at what time <em>Production check</em> is allowed to pass the module list of the site it is on to <em>Production monitor</em>. Set this carefully, as the amount data being transfered is quite big!') . '<br />';
|
||||||
$output .= t('Depending on when the cron is run on the <em>Production monitor</em> site, the module list will be reported on or maybe even several hours(!) after the time given here!') . '</p>';
|
$output .= t('Depending on when the cron is run on the <em>Production monitor</em> site, the module list will be reported on or maybe even several hours(!) after the time given here!') . '</p>';
|
||||||
$output .= '<p><strong>' . t('Enable Nagios integration') . '</strong><br />';
|
$output .= '<p><strong>' . t('Enable Nagios integration') . '</strong><br />';
|
||||||
$output .= t('By ticking this box, you open up the module\'s Nagios hooks, so that it can interface with the !link module. You will obviously need to install this module next to <em>Production check</em> to enable this functionality.', prod_check_link_array('Nagios', 'http://drupal.org/project/nagios')).'<br />';
|
$output .= t("By ticking this box, you open up the module's Nagios hooks, so that it can interface with the !link module. You will obviously need to install this module next to <em>Production check</em> to enable this functionality.", prod_check_link_array('Nagios', 'http://drupal.org/project/nagios')) . '<br />';
|
||||||
$output .= t('When the checkbox is enabled, a new array of checkboxes will appear, allowing you to specify in detail what will be reported to !link.', prod_check_link_array('Nagios', 'http://drupal.org/project/nagios')) . '</p>';
|
$output .= t('When the checkbox is enabled, a new array of checkboxes will appear, allowing you to specify in detail what will be reported to !link.', prod_check_link_array('Nagios', 'http://drupal.org/project/nagios')) . '</p>';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -140,9 +140,9 @@ function prod_check_menu() {
|
|||||||
'page callback' => 'prod_check_dbstatus',
|
'page callback' => 'prod_check_dbstatus',
|
||||||
) + $admin_defaults;
|
) + $admin_defaults;
|
||||||
|
|
||||||
$items['admin/reports/status/apc'] = array(
|
$items['admin/reports/status/apc-opc'] = array(
|
||||||
'title' => 'APC',
|
'title' => 'APC/OPcache',
|
||||||
'page callback' => 'prod_check_apc',
|
'page callback' => 'prod_check_apc_opc',
|
||||||
'access callback' => 'user_access',
|
'access callback' => 'user_access',
|
||||||
) + $admin_defaults;
|
) + $admin_defaults;
|
||||||
|
|
||||||
@ -263,7 +263,7 @@ function prod_check_xmlrpc() {
|
|||||||
'prod_check.get_settings',
|
'prod_check.get_settings',
|
||||||
'prod_check_get_settings',
|
'prod_check_get_settings',
|
||||||
array('struct', 'string'),
|
array('struct', 'string'),
|
||||||
t('Returns a struct containing a form to be displayed on the prod_monitor module\'s settings page for site specific configuration.')
|
t("Returns a struct containing a form to be displayed on the prod_monitor module's settings page for site specific configuration.")
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'prod_check.get_data',
|
'prod_check.get_data',
|
||||||
@ -582,7 +582,7 @@ function _prod_check_functions() {
|
|||||||
'title' => 'Server',
|
'title' => 'Server',
|
||||||
'description' => 'Checks certain server side parameters such as APC.',
|
'description' => 'Checks certain server side parameters such as APC.',
|
||||||
'functions' => array(
|
'functions' => array(
|
||||||
'_prod_check_apc' => 'APC',
|
'_prod_check_apc_opc' => 'APC/OPcache',
|
||||||
'_prod_check_dblog_php' => 'PHP errors',
|
'_prod_check_dblog_php' => 'PHP errors',
|
||||||
'_prod_check_release_notes' => 'Release notes',
|
'_prod_check_release_notes' => 'Release notes',
|
||||||
),
|
),
|
||||||
@ -617,13 +617,14 @@ function _prod_check_functions() {
|
|||||||
// Modules
|
// Modules
|
||||||
$functions['modules'] = array(
|
$functions['modules'] = array(
|
||||||
'title' => 'Modules',
|
'title' => 'Modules',
|
||||||
'description' => 'Checks if certain modules are on or off and if they\'re properly configured.',
|
'description' => "Checks if certain modules are on or off and if they're properly configured.",
|
||||||
'functions' => array(
|
'functions' => array(
|
||||||
'_prod_check_contact' => 'Contact',
|
'_prod_check_contact' => 'Contact',
|
||||||
'_prod_check_devel' => 'Devel',
|
'_prod_check_devel' => 'Devel',
|
||||||
'_prod_check_search_config' => 'Search config',
|
'_prod_check_search_config' => 'Search config',
|
||||||
'_prod_check_update_status' => 'Update status',
|
'_prod_check_update_status' => 'Update status',
|
||||||
'_prod_check_webform' => 'Webform',
|
'_prod_check_webform' => 'Webform',
|
||||||
|
'_prod_check_mimemail' => 'Mimemail',
|
||||||
'_prod_check_missing_module_files' => 'Active modules',
|
'_prod_check_missing_module_files' => 'Active modules',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -811,22 +812,42 @@ function _prod_check_poormanscron($caller = 'internal') {
|
|||||||
// --- SERVER ---
|
// --- SERVER ---
|
||||||
|
|
||||||
// APC check
|
// APC check
|
||||||
function _prod_check_apc($caller = 'internal') {
|
function _prod_check_apc_opc($caller = 'internal') {
|
||||||
$check = array();
|
$check = array();
|
||||||
|
|
||||||
$desc_ok = $desc_nok = '';
|
$desc_ok = $desc_nok = '';
|
||||||
$title = 'APC';
|
$title = 'APC/OPcache';
|
||||||
$path = 'admin/reports/status/apc';
|
$path = 'admin/reports/status/apc-opc';
|
||||||
if ($caller != 'internal') {
|
if ($caller != 'internal') {
|
||||||
$path = PRODCHECK_BASEURL . $path;
|
$path = PRODCHECK_BASEURL . $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!function_exists('apc_cache_info')) {
|
$cache = array();
|
||||||
|
|
||||||
|
if (!function_exists('apc_cache_info') && !function_exists('opcache_get_status')) {
|
||||||
$desc_nok = t('!link does not appear to be running.', prod_check_link_array($title, $path));
|
$desc_nok = t('!link does not appear to be running.', prod_check_link_array($title, $path));
|
||||||
$val_nok = t('Disabled');
|
$val_nok = t('Disabled');
|
||||||
$error = TRUE;
|
$error = TRUE;
|
||||||
}
|
}
|
||||||
else if ($cache = @apc_cache_info('opcode')) {
|
elseif (function_exists('apc_cache_info')) {
|
||||||
|
$cache = @apc_cache_info('opcode');
|
||||||
|
}
|
||||||
|
elseif (function_exists('opcache_get_status')) {
|
||||||
|
$opc_cache = @opcache_get_status();
|
||||||
|
if ($opc_cache && $opc_cache['opcache_enabled']) {
|
||||||
|
$cache['num_hits'] = $opc_cache['opcache_statistics']['hits'];
|
||||||
|
$cache['num_misses'] = $opc_cache['opcache_statistics']['misses'];
|
||||||
|
// TODO: Should we make the sum of these two or check separately?
|
||||||
|
$cache['expunges'] = $opc_cache['opcache_statistics']['oom_restarts'] + $opc_cache['opcache_statistics']['hash_restarts'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$desc_nok = t('!link does not appear to be running.', prod_check_link_array($title, $path));
|
||||||
|
$val_nok = t('Disabled');
|
||||||
|
$error = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($cache)) {
|
||||||
$apc_expunge = variable_get('prod_check_apc_expunge', 0);
|
$apc_expunge = variable_get('prod_check_apc_expunge', 0);
|
||||||
$detailed_info = ': ' . t('hits') . ': ' . $cache['num_hits'] . ', ' . t('misses') . ': ' . $cache['num_misses'] . ', ' . t('cache full count') . ': ' . $cache['expunges'] . '.';
|
$detailed_info = ': ' . t('hits') . ': ' . $cache['num_hits'] . ', ' . t('misses') . ': ' . $cache['num_misses'] . ', ' . t('cache full count') . ': ' . $cache['expunges'] . '.';
|
||||||
if ($cache['num_misses'] >= $cache['num_hits']) {
|
if ($cache['num_misses'] >= $cache['num_hits']) {
|
||||||
@ -851,7 +872,7 @@ function _prod_check_apc($caller = 'internal') {
|
|||||||
$error = TRUE;
|
$error = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
$check['prod_check_apc'] = array(
|
$check['prod_check_apc_opc'] = array(
|
||||||
'#title' => t($title),
|
'#title' => t($title),
|
||||||
'#state' => !$error,
|
'#state' => !$error,
|
||||||
'#severity' => ($caller == 'nagios') ? NAGIOS_STATUS_CRITICAL : PROD_CHECK_REQUIREMENT_ERROR,
|
'#severity' => ($caller == 'nagios') ? NAGIOS_STATUS_CRITICAL : PROD_CHECK_REQUIREMENT_ERROR,
|
||||||
@ -1646,6 +1667,37 @@ function _prod_check_webform($caller = 'internal') {
|
|||||||
return prod_check_execute_check($check, $caller);
|
return prod_check_execute_check($check, $caller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mimemail
|
||||||
|
function _prod_check_mimemail($caller = 'internal') {
|
||||||
|
if (!module_exists('mimemail')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$check = array();
|
||||||
|
|
||||||
|
$title = 'Mimemail';
|
||||||
|
$path = 'admin/config/system/mimemail';
|
||||||
|
if ($caller != 'internal') {
|
||||||
|
$path = PRODCHECK_BASEURL . $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
$mimemail_mail = variable_get('mimemail_mail', variable_get('site_mail', ini_get('sendmail_from')));
|
||||||
|
$arguments = array('!mimemail' => $title, '%mail' => $mimemail_mail);
|
||||||
|
$check['prod_check_mimemail'] = array(
|
||||||
|
'#title' => t($title),
|
||||||
|
'#state' => $mimemail_mail != '' && !preg_match('/' . preg_quote(variable_get('prod_check_sitemail', '')) . '/i', $mimemail_mail),
|
||||||
|
'#severity' => ($caller == 'nagios') ? NAGIOS_STATUS_CRITICAL : PROD_CHECK_REQUIREMENT_ERROR,
|
||||||
|
'#value_ok' => t('!mimemail default sender e-mail address OK: %mail', $arguments),
|
||||||
|
'#value_nok' => t('!mimemail default sender e-mail address set to %mail', $arguments),
|
||||||
|
'#description_ok' => prod_check_ok_title($title, $path),
|
||||||
|
'#description_nok' => t('The !link default from e-mail address should not be a development address on production sites!', prod_check_link_array($title, $path)),
|
||||||
|
'#nagios_key' => 'MIML',
|
||||||
|
'#nagios_type' => 'state',
|
||||||
|
);
|
||||||
|
|
||||||
|
return prod_check_execute_check($check, $caller);
|
||||||
|
}
|
||||||
|
|
||||||
// Active modules
|
// Active modules
|
||||||
function _prod_check_missing_module_files($caller = 'internal') {
|
function _prod_check_missing_module_files($caller = 'internal') {
|
||||||
$missing = $total = 0;
|
$missing = $total = 0;
|
||||||
@ -1757,6 +1809,10 @@ function _prod_check_metatag($caller = 'internal') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _prod_check_page_title($caller = 'internal') {
|
function _prod_check_page_title($caller = 'internal') {
|
||||||
|
if (module_exists('metatag')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$check = array();
|
$check = array();
|
||||||
$error = FALSE;
|
$error = FALSE;
|
||||||
$pager = variable_get('page_title_pager_pattern', '');
|
$pager = variable_get('page_title_pager_pattern', '');
|
||||||
@ -1773,7 +1829,7 @@ function _prod_check_page_title($caller = 'internal') {
|
|||||||
if (!module_exists('page_title')) {
|
if (!module_exists('page_title')) {
|
||||||
$error = TRUE;
|
$error = TRUE;
|
||||||
$value_nok = t('Disabled');
|
$value_nok = t('Disabled');
|
||||||
$msg_nok = t('You have not enabled the !link module. This module can help out with problems such as pages with paging being marked as duplicate content by search engines.', prod_check_link_array($title, 'http://drupal.org/project/page_title'));
|
$msg_nok = t('You have not enabled the !link (or equivalent) module. This module can help out with problems such as pages with paging being marked as duplicate content by search engines.', prod_check_link_array($title, 'http://drupal.org/project/page_title'));
|
||||||
}
|
}
|
||||||
elseif (empty($pager)) {
|
elseif (empty($pager)) {
|
||||||
$error = TRUE;
|
$error = TRUE;
|
||||||
|
@ -4,7 +4,14 @@
|
|||||||
* Build status page.
|
* Build status page.
|
||||||
*/
|
*/
|
||||||
function prod_monitor_status($id) {
|
function prod_monitor_status($id) {
|
||||||
$site = _prod_monitor_get_site($id, TRUE);
|
$site = _prod_monitor_get_site($id, 'all');
|
||||||
|
|
||||||
|
if (!$site) {
|
||||||
|
// See https://api.drupal.org/api/drupal/includes!common.inc/function/drupal_not_found/7
|
||||||
|
return MENU_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
drupal_set_title(t('Production monitor status for') . ' ' . _prod_monitor_sanitize_url($site['url']));
|
drupal_set_title(t('Production monitor status for') . ' ' . _prod_monitor_sanitize_url($site['url']));
|
||||||
|
|
||||||
$functions = $site['settings']['functions'];
|
$functions = $site['settings']['functions'];
|
||||||
@ -42,7 +49,8 @@ function prod_monitor_status($id) {
|
|||||||
|
|
||||||
// TODO: do not use drupal_render but change this so that hook_page_alter can
|
// TODO: do not use drupal_render but change this so that hook_page_alter can
|
||||||
// be used as well.
|
// be used as well.
|
||||||
$output .= drupal_render(drupal_get_form('_prod_monitor_update_data_form', $id, $site));
|
$form = drupal_get_form('_prod_monitor_update_data_form', $id, $site);
|
||||||
|
$output .= drupal_render($form);
|
||||||
|
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
@ -51,12 +59,6 @@ function prod_monitor_status($id) {
|
|||||||
* Helper function to provide general status block on status overview page
|
* Helper function to provide general status block on status overview page
|
||||||
*/
|
*/
|
||||||
function _prod_monitor_status_general($prod_mon, $modules) {
|
function _prod_monitor_status_general($prod_mon, $modules) {
|
||||||
// TODO: Should we hide the rows for which no data is being retrieved?
|
|
||||||
$cron = t('Unknown');
|
|
||||||
if (isset($prod_mon['prod_check_cron_last'])) {
|
|
||||||
$cron = format_date($prod_mon['prod_check_cron_last'], 'large');
|
|
||||||
}
|
|
||||||
|
|
||||||
$updates = _prod_monitor_generate_updates_link($modules['id'], $modules['updates']);
|
$updates = _prod_monitor_generate_updates_link($modules['id'], $modules['updates']);
|
||||||
|
|
||||||
$output = '<h2>' . t('Overall status') . '</h2>' . "\n";
|
$output = '<h2>' . t('Overall status') . '</h2>' . "\n";
|
||||||
@ -65,16 +67,46 @@ function _prod_monitor_status_general($prod_mon, $modules) {
|
|||||||
array('data' => t('Drupal core version'), 'header' => TRUE),
|
array('data' => t('Drupal core version'), 'header' => TRUE),
|
||||||
$modules['projects']['drupal']['info']['version'],
|
$modules['projects']['drupal']['info']['version'],
|
||||||
),
|
),
|
||||||
array(
|
);
|
||||||
|
|
||||||
|
if (isset($prod_mon['prod_check_cron_last'])) {
|
||||||
|
$rows[] = array(
|
||||||
array('data' => t('Last cron run'), 'header' => TRUE),
|
array('data' => t('Last cron run'), 'header' => TRUE),
|
||||||
$cron,
|
format_date($prod_mon['prod_check_cron_last'], 'large'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add dbconnect check info if configured.
|
||||||
|
if (isset($prod_mon['prod_check_dbconnect'])) {
|
||||||
|
$dbconnect = $prod_mon['prod_check_dbconnect'];
|
||||||
|
$class = array();
|
||||||
|
$title = t('DB connection status');
|
||||||
|
if (stripos($dbconnect, '200') === FALSE) {
|
||||||
|
$class = array('error');
|
||||||
|
$title = '<strong>' . $title . '</strong>';
|
||||||
|
$dbconnect = '<strong>' . $dbconnect . '</strong>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array(
|
||||||
|
'data' => array(
|
||||||
|
array(
|
||||||
|
'data' => $title, 'header' => TRUE,
|
||||||
|
'class' => $class,
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
|
'data' => $dbconnect,
|
||||||
|
'class' => $class,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'class' => $class,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows[] = array(
|
||||||
array('data' => t('Update status'), 'header' => TRUE),
|
array('data' => t('Update status'), 'header' => TRUE),
|
||||||
$updates,
|
$updates,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
$output .= theme('table', array('header' => array(), 'rows' => $rows));
|
$output .= theme('table', array('prod_monitor_id' => 'status_general', 'header' => array(), 'rows' => $rows));
|
||||||
|
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
@ -112,7 +144,7 @@ function prod_monitor_performance($data) {
|
|||||||
drupal_set_title(t('Performance logs for') . ' ' . _prod_monitor_get_url($data['id']));
|
drupal_set_title(t('Performance logs for') . ' ' . _prod_monitor_get_url($data['id']));
|
||||||
|
|
||||||
// TODO: add 'get stats now' button.
|
// TODO: add 'get stats now' button.
|
||||||
//$site = _prod_monitor_get_site($id, TRUE);
|
//$site = _prod_monitor_get_site($id, 'all');
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'performance_data' => array(
|
'performance_data' => array(
|
||||||
@ -197,9 +229,18 @@ function prod_monitor_overview_form($form, &$form_state, $edit = FALSE) {
|
|||||||
$collapsed = FALSE;
|
$collapsed = FALSE;
|
||||||
|
|
||||||
if (!$edit) {
|
if (!$edit) {
|
||||||
|
// Button to initiate our fetch all batcher.
|
||||||
|
$form['fetch_all_submit'] = array(
|
||||||
|
'#weight' => -100,
|
||||||
|
'#type' => 'submit',
|
||||||
|
'#value' => t('Fetch all'),
|
||||||
|
'#submit' => array('prod_monitor_fetch_all_submit'),
|
||||||
|
'#limit_validation_errors' => array(),
|
||||||
|
);
|
||||||
|
|
||||||
// Add new site situation.
|
// Add new site situation.
|
||||||
$sites = _prod_monitor_get_sites();
|
$sites = _prod_monitor_get_sites();
|
||||||
$api_key = $url = '';
|
$dbconnect_path = $api_key = $url = '';
|
||||||
$options = array();
|
$options = array();
|
||||||
$button = t('Get settings');
|
$button = t('Get settings');
|
||||||
if (!empty($sites)) {
|
if (!empty($sites)) {
|
||||||
@ -211,6 +252,7 @@ function prod_monitor_overview_form($form, &$form_state, $edit = FALSE) {
|
|||||||
if (!empty($form_state['storage']['get_settings'])) {
|
if (!empty($form_state['storage']['get_settings'])) {
|
||||||
// Second step of add new site situation.
|
// Second step of add new site situation.
|
||||||
$api_key = $form_state['values']['api_key'];
|
$api_key = $form_state['values']['api_key'];
|
||||||
|
$dbconnect_path = $form_state['values']['dbconnect_path'];
|
||||||
$url = $form_state['values']['url'];
|
$url = $form_state['values']['url'];
|
||||||
$button = t('Add site');
|
$button = t('Add site');
|
||||||
$collapsed = FALSE;
|
$collapsed = FALSE;
|
||||||
@ -227,6 +269,7 @@ function prod_monitor_overview_form($form, &$form_state, $edit = FALSE) {
|
|||||||
}
|
}
|
||||||
drupal_set_title(t('Production monitor settings for !url', array('!url' => _prod_monitor_sanitize_url($url))));
|
drupal_set_title(t('Production monitor settings for !url', array('!url' => _prod_monitor_sanitize_url($url))));
|
||||||
$api_key = $site['settings']['api_key'];
|
$api_key = $site['settings']['api_key'];
|
||||||
|
$dbconnect_path = $site['settings']['dbconnect_path'];
|
||||||
$options = $site['settings']['checks'];
|
$options = $site['settings']['checks'];
|
||||||
if (isset($site['settings']['checks']['perf_data'])) {
|
if (isset($site['settings']['checks']['perf_data'])) {
|
||||||
$perf_enabled = $site['settings']['checks']['perf_data'];
|
$perf_enabled = $site['settings']['checks']['perf_data'];
|
||||||
@ -255,7 +298,7 @@ function prod_monitor_overview_form($form, &$form_state, $edit = FALSE) {
|
|||||||
|
|
||||||
$form['sites']['api_key'] = array(
|
$form['sites']['api_key'] = array(
|
||||||
'#type' => 'textfield',
|
'#type' => 'textfield',
|
||||||
'#title' => t('The website\'s API key'),
|
'#title' => t("The website's API key"),
|
||||||
'#default_value' => $api_key,
|
'#default_value' => $api_key,
|
||||||
'#description' => t('Enter the API key you have configured for this site using the <em>Production check</em> module.'),
|
'#description' => t('Enter the API key you have configured for this site using the <em>Production check</em> module.'),
|
||||||
'#size' => 60,
|
'#size' => 60,
|
||||||
@ -263,6 +306,15 @@ function prod_monitor_overview_form($form, &$form_state, $edit = FALSE) {
|
|||||||
'#required' => TRUE,
|
'#required' => TRUE,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$form['sites']['dbconnect_path'] = array(
|
||||||
|
'#type' => 'textfield',
|
||||||
|
'#title' => t('DB connect check script'),
|
||||||
|
'#default_value' => $dbconnect_path,
|
||||||
|
'#description' => t('Enter the relative path, starting from the Drupal root, to the <em>prod_check.dbconnect.php</em> on the remote site. This wil usually be something like sites/all/modules/contrib/prod_check/prod_check.dbconnect.php . <strong>Leave empty if you do not want do enable this check!</strong>'),
|
||||||
|
'#size' => 60,
|
||||||
|
'#maxlength' => 512,
|
||||||
|
);
|
||||||
|
|
||||||
// Only show on second step of add form or when editing.
|
// Only show on second step of add form or when editing.
|
||||||
if (!empty($form_state['storage']['get_settings']) || $edit) {
|
if (!empty($form_state['storage']['get_settings']) || $edit) {
|
||||||
// Get the settings from the remote site. We always do this when the form is
|
// Get the settings from the remote site. We always do this when the form is
|
||||||
@ -434,7 +486,7 @@ function _prod_monitor_overview_form_table($sites) {
|
|||||||
$rows[] = $row;
|
$rows[] = $row;
|
||||||
}
|
}
|
||||||
|
|
||||||
return theme('table', array('header' => $headers, 'rows' => $rows));
|
return theme('table', array('prod_monitor_id' => 'overview_form', 'header' => $headers, 'rows' => $rows));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -501,6 +553,8 @@ function prod_monitor_overview_form_submit($form, &$form_state) {
|
|||||||
$site->settings = serialize(
|
$site->settings = serialize(
|
||||||
array(
|
array(
|
||||||
'api_key' => $form_state['values']['api_key'],
|
'api_key' => $form_state['values']['api_key'],
|
||||||
|
// Trim spaces and / from left and right side.
|
||||||
|
'dbconnect_path' => trim($form_state['values']['dbconnect_path'], ' /'),
|
||||||
'functions' => $form_state['storage']['functions'],
|
'functions' => $form_state['storage']['functions'],
|
||||||
'checks' => $checks,
|
'checks' => $checks,
|
||||||
)
|
)
|
||||||
@ -511,8 +565,11 @@ function prod_monitor_overview_form_submit($form, &$form_state) {
|
|||||||
if ($result) {
|
if ($result) {
|
||||||
drupal_set_message(t('Website %url correctly saved.', array('%url' => $site->url)));
|
drupal_set_message(t('Website %url correctly saved.', array('%url' => $site->url)));
|
||||||
if ($form_state['values']['fetch']) {
|
if ($form_state['values']['fetch']) {
|
||||||
$site_info = _prod_monitor_get_site($site->id, TRUE);
|
$site_info = _prod_monitor_get_site($site->id, 'all');
|
||||||
|
// First: all checks.
|
||||||
_prod_monitor_retrieve_data($site->id, $site_info, TRUE);
|
_prod_monitor_retrieve_data($site->id, $site_info, TRUE);
|
||||||
|
// MUST be second because of the status update!
|
||||||
|
_prod_monitor_db_connect_check($site->id, $site_info);
|
||||||
$form_state['redirect'] = 'admin/reports/prod-monitor/site/' . $site->id;
|
$form_state['redirect'] = 'admin/reports/prod-monitor/site/' . $site->id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -523,12 +580,80 @@ function prod_monitor_overview_form_submit($form, &$form_state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit handler for the fetch all button.
|
||||||
|
*/
|
||||||
|
function prod_monitor_fetch_all_submit($form, &$form_state) {
|
||||||
|
_prod_monitor_fetch_all_data_batcher_create();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to create the batch process. Also used in Drush!
|
||||||
|
*/
|
||||||
|
function _prod_monitor_fetch_all_data_batcher_create($fetch_only = FALSE, $update_only = FALSE, $msg = TRUE) {
|
||||||
|
$title = t('Fetching all site data and checking for updates...');
|
||||||
|
|
||||||
|
if ($fetch_only) {
|
||||||
|
$title = t('Fetching all site data...');
|
||||||
|
}
|
||||||
|
if ($update_only) {
|
||||||
|
$title = t('Checking for updates...');
|
||||||
|
}
|
||||||
|
|
||||||
|
$batch = array(
|
||||||
|
'operations' => array(
|
||||||
|
array('prod_monitor_fetch_all_data_batcher', array($fetch_only, $update_only, $msg)),
|
||||||
|
),
|
||||||
|
'title' => $title,
|
||||||
|
'file' => drupal_get_path('module', 'prod_monitor') . '/includes/prod_monitor.admin.inc',
|
||||||
|
);
|
||||||
|
batch_set($batch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Batch fetching of all site info.
|
||||||
|
*/
|
||||||
|
function prod_monitor_fetch_all_data_batcher($fetch_only, $update_only, $msg, &$context) {
|
||||||
|
$sandbox = &$context['sandbox'];
|
||||||
|
if (empty($context['sandbox'])) {
|
||||||
|
$sandbox['sites'] = array_keys(_prod_monitor_get_sites());
|
||||||
|
$sandbox['count'] = count($sandbox['sites']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get site info.
|
||||||
|
$id = array_shift($sandbox['sites']);
|
||||||
|
$site_info = _prod_monitor_get_site($id, 'all');
|
||||||
|
|
||||||
|
if (!$update_only) {
|
||||||
|
// First: all checks.
|
||||||
|
_prod_monitor_retrieve_data($id, $site_info, $msg);
|
||||||
|
// MUST be second because of the status update!
|
||||||
|
_prod_monitor_db_connect_check($id, $site_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$fetch_only) {
|
||||||
|
// Module update status.
|
||||||
|
$modules = prod_monitor_load($id);
|
||||||
|
if (!empty($modules) && !empty($modules['projects'])) {
|
||||||
|
module_load_include('inc', 'prod_monitor', 'includes/prod_monitor.update');
|
||||||
|
_prod_monitor_update_refresh($id, $modules['projects'], $modules['sitekey']);
|
||||||
|
_prod_monitor_calculate_project_data($id, $modules['projects'], $modules['available']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$context['message'] = t('Updating data for %url', array('%url' => $site_info['url']));
|
||||||
|
$context['finished'] = empty($sandbox['sites']) ? 1 : (1 - count($sandbox['sites']) / $sandbox['count']);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to fetch site data
|
* Callback to fetch site data
|
||||||
*/
|
*/
|
||||||
function prod_monitor_fetch_data($id) {
|
function prod_monitor_fetch_data($id) {
|
||||||
$site_info = _prod_monitor_get_site($id, TRUE);
|
$site_info = _prod_monitor_get_site($id, 'all');
|
||||||
|
// First: all checks.
|
||||||
_prod_monitor_retrieve_data($id, $site_info, TRUE);
|
_prod_monitor_retrieve_data($id, $site_info, TRUE);
|
||||||
|
// MUST be second because of the status update!
|
||||||
|
_prod_monitor_db_connect_check($id, $site_info);
|
||||||
drupal_goto('admin/reports/prod-monitor/site/' . $id);
|
drupal_goto('admin/reports/prod-monitor/site/' . $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -634,6 +759,95 @@ function _prod_monitor_update_data_form($form, $form_state, $id, $site_info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _prod_monitor_update_data_form_submit($form, &$form_state) {
|
function _prod_monitor_update_data_form_submit($form, &$form_state) {
|
||||||
|
// First: all checks.
|
||||||
_prod_monitor_retrieve_data($form_state['values']['site_id'], $form_state['values']['site_info'], TRUE);
|
_prod_monitor_retrieve_data($form_state['values']['site_id'], $form_state['values']['site_info'], TRUE);
|
||||||
|
// MUST be second because of the status update!
|
||||||
|
_prod_monitor_db_connect_check($form_state['values']['site_id'], $form_state['values']['site_info']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for module lookup form.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function prod_monitor_module_lookup_form($form, &$form_state) {
|
||||||
|
$form = array();
|
||||||
|
|
||||||
|
// Show results.
|
||||||
|
if (isset($form_state['projects'])) {
|
||||||
|
|
||||||
|
$module = $form_state['values']['module'];
|
||||||
|
|
||||||
|
$rows = array();
|
||||||
|
foreach ($form_state['projects'] as $id => $project) {
|
||||||
|
|
||||||
|
$application = db_select('prod_monitor_sites', 'pms')->fields('pms', array('url'))->condition('id', $id)->execute()->fetchField();
|
||||||
|
$version = $project['info']['version'];
|
||||||
|
|
||||||
|
$rows[] = array(
|
||||||
|
$application,
|
||||||
|
$version,
|
||||||
|
l(t('View'), 'admin/reports/prod-monitor/site/' . $id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$form['title'] = array(
|
||||||
|
'#theme' => 'html_tag',
|
||||||
|
'#tag' => 'h2',
|
||||||
|
'#value' => t('Applications where %module is used', array('%module' => $module)),
|
||||||
|
);
|
||||||
|
$form['table'] = array(
|
||||||
|
'#theme' => 'table',
|
||||||
|
'#rows' => $rows,
|
||||||
|
'#header' => array(t('Application'), t('Version'), t('View')),
|
||||||
|
);
|
||||||
|
|
||||||
|
$form['submit'] = array(
|
||||||
|
'#type' => 'submit',
|
||||||
|
'#value' => t('Perform another lookup'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Show lookup form.
|
||||||
|
else {
|
||||||
|
$form['module'] = array(
|
||||||
|
'#type' => 'textfield',
|
||||||
|
'#title' => t('Module name'),
|
||||||
|
'#required' => TRUE,
|
||||||
|
);
|
||||||
|
$form['submit'] = array(
|
||||||
|
'#type' => 'submit',
|
||||||
|
'#value' => t('Fetch Applications'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submission handler for module lookup form
|
||||||
|
*/
|
||||||
|
function prod_monitor_module_lookup_form_submit(&$form, &$form_state) {
|
||||||
|
if (isset($form_state['values']['module'])) {
|
||||||
|
|
||||||
|
$projects = db_select('prod_monitor_site_modules', 'psm')
|
||||||
|
->fields('psm', array('id', 'projects'))
|
||||||
|
->condition('projects', '%' . db_like($form_state['values']['module']) . '%', 'LIKE')
|
||||||
|
->execute()->fetchAllAssoc('id');
|
||||||
|
|
||||||
|
$form_state['rebuild'] = TRUE;
|
||||||
|
|
||||||
|
if ($projects && !empty($projects)) {
|
||||||
|
foreach($projects as $project) {
|
||||||
|
|
||||||
|
$modules = unserialize($project->projects);
|
||||||
|
if (isset($modules[$form_state['values']['module']])) {
|
||||||
|
$form_state['projects'][$project->id] = $modules[$form_state['values']['module']];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isset($form_state['projects'])) {
|
||||||
|
drupal_set_message(t('No projects found for :module', array(':module' => $form_state['values']['module'])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unset($form_state['projects']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements hook_preprocess_prod_monitor_update_report().
|
||||||
|
*/
|
||||||
|
function prod_monitor_preprocess_prod_monitor_update_report(&$vars) {
|
||||||
|
if (is_array($vars['data'])) {
|
||||||
|
foreach (array_keys($vars['data']) as $module_id) {
|
||||||
|
|
||||||
|
// When ignoring a module, we'll give a reason.
|
||||||
|
if (isset($vars['data'][$module_id]['ignored'])) {
|
||||||
|
$vars['data'][$module_id]['reason'] = t('Being ignored');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns HTML for the project status report.
|
* Returns HTML for the project status report.
|
||||||
*
|
*
|
||||||
@ -226,7 +241,7 @@ function theme_prod_monitor_update_report($variables) {
|
|||||||
if (!empty($rows[$type_name])) {
|
if (!empty($rows[$type_name])) {
|
||||||
ksort($rows[$type_name]);
|
ksort($rows[$type_name]);
|
||||||
$output .= "\n<h3>" . $type_label . "</h3>\n";
|
$output .= "\n<h3>" . $type_label . "</h3>\n";
|
||||||
$output .= theme('table', array('header' => $header, 'rows' => $rows[$type_name], 'attributes' => array('class' => array('update'))));
|
$output .= theme('table', array('prod_monitor_id' => 'update_report', 'header' => $header, 'rows' => $rows[$type_name], 'attributes' => array('class' => array('update'))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drupal_add_css(drupal_get_path('module', 'update') . '/update.css');
|
drupal_add_css(drupal_get_path('module', 'update') . '/update.css');
|
||||||
|
@ -65,7 +65,7 @@ function _prod_monitor_update_refresh($id, $projects, $site_key) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$modules->available = serialize($available);
|
$modules->available = serialize($available);
|
||||||
watchdog('prod_monitor', 'Attempted to fetch information about all available new releases and updates for %link.', array('%link' => _prod_monitor_get_url($id)), WATCHDOG_NOTICE, l(t('view'), 'admin/reports/prod-monitor/site/'.$id.'/view/updates'));
|
watchdog('prod_monitor', 'Fetched information about all available new releases and updates for %link.', array('%link' => _prod_monitor_get_url($id)), WATCHDOG_NOTICE, l(t('view'), 'admin/reports/prod-monitor/site/' . $id . '/view/updates'));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
watchdog('prod_monitor', 'Unable to fetch any information about available new releases and updates for %link.', array('%link' => _prod_monitor_get_url($id)), WATCHDOG_ERROR, l(t('view'), 'admin/reports/prod-monitor/site/' . $id . '/view/updates'));
|
watchdog('prod_monitor', 'Unable to fetch any information about available new releases and updates for %link.', array('%link' => _prod_monitor_get_url($id)), WATCHDOG_ERROR, l(t('view'), 'admin/reports/prod-monitor/site/' . $id . '/view/updates'));
|
||||||
@ -169,6 +169,19 @@ function _prod_monitor_calculate_project_data($id, $projects, $available) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle the ignored modules.
|
||||||
|
if (($ignored = _prod_monitor_get_site_ignored($id))
|
||||||
|
&& !empty($ignored['updates'])) {
|
||||||
|
foreach ($ignored['updates'] as $project_name) {
|
||||||
|
if (isset($projects[$project_name])) {
|
||||||
|
$projects[$project_name]['ignored'] = TRUE;
|
||||||
|
$projects[$project_name]['status'] = UPDATE_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drupal_alter('prod_monitor_project_data', $id, $projects, $available);
|
||||||
|
|
||||||
// Check if we need to flag a security update warning.
|
// Check if we need to flag a security update warning.
|
||||||
// Prepare object to store generated data to DB.
|
// Prepare object to store generated data to DB.
|
||||||
$modules = new stdClass();
|
$modules = new stdClass();
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Documentation on api functions for prod_monitor.
|
||||||
|
*
|
||||||
|
* @ingroup prod_monitor
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements hook_prod_monitor_ignore().
|
||||||
|
*
|
||||||
|
* Allows modules to specify certain ignore directives, currently
|
||||||
|
* a list of modules whose update status should be ignored.
|
||||||
|
*
|
||||||
|
* @see _prod_monitor_get_site_ignored().
|
||||||
|
* @see _prod_monitor_calculate_project_data().
|
||||||
|
*/
|
||||||
|
function hook_prod_monitor_ignore($site_id) {
|
||||||
|
$ignore = array('updates' => array());
|
||||||
|
|
||||||
|
// Ignore this module (suppress warnings) because we cannot do anything
|
||||||
|
// about it's update status as it has been abandoned and we are not going
|
||||||
|
// to stop using it.
|
||||||
|
if ($site_id == 12) {
|
||||||
|
$ignore['updates'][] = 'node_embed';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ignore;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements hook_prod_monitor_project_data_alter().
|
||||||
|
*
|
||||||
|
* Allows modules to alter the data being calculated for a project.
|
||||||
|
*
|
||||||
|
* @see _prod_monitor_calculate_project_data().
|
||||||
|
*/
|
||||||
|
function hook_prod_monitor_project_data_alter($site_id, &$data, $available) {
|
||||||
|
|
||||||
|
}
|
@ -15,14 +15,15 @@ function prod_monitor_drush_command() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
$items['prod-monitor-updates'] = array(
|
$items['prod-monitor-updates'] = array(
|
||||||
'callback' => '_drush_prod_monitor_updates',
|
'callback' => 'drush_prod_monitor_updates',
|
||||||
'description' => 'Display the update module status page',
|
'description' => 'Display the update module status page',
|
||||||
'aliases' => array('pmon-up'),
|
'aliases' => array('pmon-up'),
|
||||||
'arguments' => array(
|
'arguments' => array(
|
||||||
'id' => 'ID of the site to view module updates for.',
|
'id' => 'ID of the site to view module updates for.',
|
||||||
),
|
),
|
||||||
'options' => array(
|
'options' => array(
|
||||||
'--check' => 'Check for module updates.'
|
'check' => 'Check for module updates.',
|
||||||
|
'security-only' => 'Only show modules that have security updates available.',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
$items['prod-monitor-fetch'] = array(
|
$items['prod-monitor-fetch'] = array(
|
||||||
@ -58,6 +59,22 @@ function prod_monitor_drush_command() {
|
|||||||
*/
|
*/
|
||||||
function drush_prod_monitor_fetch() {
|
function drush_prod_monitor_fetch() {
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
|
|
||||||
|
// Fetch ALL.
|
||||||
|
if (empty($args)) {
|
||||||
|
if (!drush_confirm(dt('Do you really want to fetch the data for ALL remote sites?'))) {
|
||||||
|
drush_set_error('prod_monitor', dt('Aborting.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
module_load_include('inc', 'prod_monitor', 'includes/prod_monitor.admin');
|
||||||
|
// Batch process data fetching.
|
||||||
|
_prod_monitor_fetch_all_data_batcher_create(TRUE, FALSE, FALSE);
|
||||||
|
drush_backend_batch_process();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fetch one or more sites as requested.
|
||||||
|
else {
|
||||||
foreach($args as $arg) {
|
foreach($args as $arg) {
|
||||||
$site = _prod_monitor_get_site($arg);
|
$site = _prod_monitor_get_site($arg);
|
||||||
if (!empty($site['url'])) {
|
if (!empty($site['url'])) {
|
||||||
@ -67,6 +84,7 @@ function drush_prod_monitor_fetch() {
|
|||||||
drush_print("\033[1;31m" . dt('Error:') . " \033[0m" . dt('Unable to fetch data for') . ' ' . $site['url'] . '!');
|
drush_print("\033[1;31m" . dt('Error:') . " \033[0m" . dt('Unable to fetch data for') . ' ' . $site['url'] . '!');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
_prod_monitor_db_connect_check($arg, $site);
|
||||||
drush_print(dt('Sucessfully fetched data for') . ' ' . $site['url'] . '.');
|
drush_print(dt('Sucessfully fetched data for') . ' ' . $site['url'] . '.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,6 +93,7 @@ function drush_prod_monitor_fetch() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flush data callback.
|
* Flush data callback.
|
||||||
@ -182,7 +201,7 @@ function _drush_prod_monitor_overview() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _drush_prod_monitor_detail($id) {
|
function _drush_prod_monitor_detail($id) {
|
||||||
$site = _prod_monitor_get_site($id, TRUE);
|
$site = _prod_monitor_get_site($id, 'all');
|
||||||
if (!isset($site['url'])) {
|
if (!isset($site['url'])) {
|
||||||
drush_print("\033[1;31m" . dt('Error:') . " \033[0m" . dt('No site found with ID') . ' ' . $id . '!');
|
drush_print("\033[1;31m" . dt('Error:') . " \033[0m" . dt('No site found with ID') . ' ' . $id . '!');
|
||||||
return;
|
return;
|
||||||
@ -293,12 +312,24 @@ function _drush_prod_monitor_detail($id) {
|
|||||||
/**
|
/**
|
||||||
* Update status page callback.
|
* Update status page callback.
|
||||||
*/
|
*/
|
||||||
function _drush_prod_monitor_updates() {
|
function drush_prod_monitor_updates() {
|
||||||
$id = func_get_args();
|
$id = func_get_args();
|
||||||
|
|
||||||
|
// Fetch ALL.
|
||||||
if (empty($id)) {
|
if (empty($id)) {
|
||||||
drush_set_error('prod_monitor', dt('You must provide a site ID!'));
|
if (!drush_confirm(dt('Do you really want to check ALL sites for module updates?'))) {
|
||||||
|
drush_set_error('prod_monitor', dt('Aborting.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
module_load_include('inc', 'prod_monitor', 'includes/prod_monitor.admin');
|
||||||
|
// Batch process update checking.
|
||||||
|
_prod_monitor_fetch_all_data_batcher_create(FALSE, TRUE, FALSE);
|
||||||
|
drush_backend_batch_process();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fetch the site as requested.
|
||||||
|
else {
|
||||||
$id = $id['0'];
|
$id = $id['0'];
|
||||||
|
|
||||||
// Get module info.
|
// Get module info.
|
||||||
@ -325,6 +356,8 @@ function _drush_prod_monitor_updates() {
|
|||||||
_drush_prod_monitor_update_refresh($id, $modules);
|
_drush_prod_monitor_update_refresh($id, $modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$security_only = drush_get_option('security-only');
|
||||||
|
|
||||||
$last = $modules['lastupdate'];
|
$last = $modules['lastupdate'];
|
||||||
module_load_include('inc', 'prod_monitor', 'includes/prod_monitor.update');
|
module_load_include('inc', 'prod_monitor', 'includes/prod_monitor.update');
|
||||||
$projects = _prod_monitor_calculate_project_data($id, $modules['projects'], $modules['available']);
|
$projects = _prod_monitor_calculate_project_data($id, $modules['projects'], $modules['available']);
|
||||||
@ -337,26 +370,45 @@ function _drush_prod_monitor_updates() {
|
|||||||
// Process releases, notifying user of status and building a list of proposed updates
|
// Process releases, notifying user of status and building a list of proposed updates
|
||||||
drush_include_engine('update_info', 'drupal', NULL, DRUSH_BASE_PATH . '/commands/pm/update_info');
|
drush_include_engine('update_info', 'drupal', NULL, DRUSH_BASE_PATH . '/commands/pm/update_info');
|
||||||
drush_include(DRUSH_BASE_PATH . '/commands/pm', 'updatecode.pm');
|
drush_include(DRUSH_BASE_PATH . '/commands/pm', 'updatecode.pm');
|
||||||
$updateable = pm_project_filter($projects, $rows);
|
|
||||||
|
|
||||||
// Pipe preparation
|
|
||||||
if (drush_get_context('DRUSH_PIPE')) {
|
|
||||||
$pipe = "";
|
|
||||||
foreach ($projects as $project) {
|
foreach ($projects as $project) {
|
||||||
$pipe .= $project['name']. " ";
|
// Only show security updates if the user requested it.
|
||||||
$pipe .= $project['existing_version']. " ";
|
if ($security_only && $project['status'] !== UPDATE_NOT_SECURE) {
|
||||||
$pipe .= $project['candidate_version']. " ";
|
continue;
|
||||||
$pipe .= str_replace(' ', '-', pm_update_filter($project)). "\n";
|
|
||||||
}
|
}
|
||||||
drush_print_pipe($pipe);
|
// Add color to the status.
|
||||||
// Automatically curtail update process if in pipe mode
|
$color = "\033[0m";
|
||||||
$updateable = FALSE;
|
switch ($project['status']) {
|
||||||
|
case UPDATE_CURRENT:
|
||||||
|
$color = "\033[1;32m";
|
||||||
|
break;
|
||||||
|
case UPDATE_NOT_CURRENT:
|
||||||
|
$color = "\033[1;33m";
|
||||||
|
break;
|
||||||
|
case UPDATE_NOT_SECURE:
|
||||||
|
$color = "\033[1;31m";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Translate status to readable name and fill 'candidate_version'.
|
||||||
|
$status = pm_update_filter($project);
|
||||||
|
// Generate row.
|
||||||
|
$rows[] = array(
|
||||||
|
$project['name'],
|
||||||
|
$project['existing_version'],
|
||||||
|
$project['candidate_version'],
|
||||||
|
$color . $status . "\033[0m",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
drush_print("\033[1m" . dt('Module update status for') . ' ' . $url . "\033[0m", 1);
|
drush_print("\033[1m" . dt('Module update status for') . ' ' . $url . "\033[0m", 1);
|
||||||
drush_print(dt('Update information last refreshed:') . ' ' . ($last ? format_date($last) : dt('Never')) . "\n", 1);
|
drush_print(dt('Update information last refreshed:') . ' ' . ($last ? format_date($last) : dt('Never')) . "\n", 1);
|
||||||
|
if (count($rows) > 1) {
|
||||||
drush_print_table($rows, TRUE);
|
drush_print_table($rows, TRUE);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
drush_print("\033[1m" . dt('No updates to show!') . "\033[0m", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to refresh update status data.
|
* Helper function to refresh update status data.
|
||||||
|
@ -4,9 +4,9 @@ package = Monitoring
|
|||||||
core = 7.x
|
core = 7.x
|
||||||
configure = admin/reports/prod-monitor
|
configure = admin/reports/prod-monitor
|
||||||
|
|
||||||
; Information added by packaging script on 2013-11-25
|
; Information added by Drupal.org packaging script on 2015-08-04
|
||||||
version = "7.x-1.8"
|
version = "7.x-1.9"
|
||||||
core = "7.x"
|
core = "7.x"
|
||||||
project = "prod_check"
|
project = "prod_check"
|
||||||
datestamp = "1385405033"
|
datestamp = "1438700931"
|
||||||
|
|
||||||
|
@ -149,29 +149,6 @@ function prod_monitor_schema() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of hook_requirements().
|
|
||||||
*/
|
|
||||||
function prod_monitor_requirements($phase) {
|
|
||||||
$requirements = array();
|
|
||||||
|
|
||||||
switch ($phase) {
|
|
||||||
case 'install':
|
|
||||||
if (module_exists('update')) {
|
|
||||||
$requirements['prod_monitor_update'] = array(
|
|
||||||
'title' => t('Production monitor'),
|
|
||||||
'value' => t('Update manager enabled.'),
|
|
||||||
'severity' => REQUIREMENT_ERROR,
|
|
||||||
'description' => t('You have enabled <em>Update manager</em>. You have to disable this module before enabling Production monitor!'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $requirements;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of hook_uninstall().
|
* Implementation of hook_uninstall().
|
||||||
*/
|
*/
|
||||||
@ -294,3 +271,25 @@ function prod_check_update_7103() {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add new dbconnect_path setting to database to prevent warnings.
|
||||||
|
*/
|
||||||
|
function prod_check_update_7104() {
|
||||||
|
$table = 'prod_monitor_sites';
|
||||||
|
|
||||||
|
// Fetch all settings.
|
||||||
|
$result = db_select($table, 'psm')
|
||||||
|
->fields('psm', array('id', 'settings'))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
// Update all sites to add new setting.
|
||||||
|
foreach ($result as $site) {
|
||||||
|
$settings = unserialize($site->settings);
|
||||||
|
$settings['dbconnect_path'] = '';
|
||||||
|
$site->settings = serialize($settings);
|
||||||
|
|
||||||
|
// Write to DB.
|
||||||
|
drupal_write_record($table, $site, array('id'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,9 +13,11 @@ define('PROD_MONITOR_REQUIREMENT_WARNING', 1);
|
|||||||
define('PROD_MONITOR_REQUIREMENT_ERROR', 2);
|
define('PROD_MONITOR_REQUIREMENT_ERROR', 2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We do the same here for the update module constants: redefine them so that we
|
* We don't want to load the Update module just to be able to run Production
|
||||||
* do not need to run the update module entirely!
|
* Monitor, so we copy the constants from Update. But we need to check them all
|
||||||
|
* so that we don't get notices if Update is already running.
|
||||||
*/
|
*/
|
||||||
|
if (!module_exists('update')) {
|
||||||
define('UPDATE_DEFAULT_URL', 'http://updates.drupal.org/release-history');
|
define('UPDATE_DEFAULT_URL', 'http://updates.drupal.org/release-history');
|
||||||
define('UPDATE_NOT_SECURE', 1);
|
define('UPDATE_NOT_SECURE', 1);
|
||||||
define('UPDATE_REVOKED', 2);
|
define('UPDATE_REVOKED', 2);
|
||||||
@ -28,6 +30,7 @@ define('UPDATE_NOT_FETCHED', -3);
|
|||||||
define('UPDATE_FETCH_PENDING', -4);
|
define('UPDATE_FETCH_PENDING', -4);
|
||||||
define('UPDATE_MAX_FETCH_ATTEMPTS', 2);
|
define('UPDATE_MAX_FETCH_ATTEMPTS', 2);
|
||||||
define('UPDATE_MAX_FETCH_TIME', 5);
|
define('UPDATE_MAX_FETCH_TIME', 5);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of hook_help().
|
* Implementation of hook_help().
|
||||||
@ -47,13 +50,18 @@ function prod_monitor_help($path, $arg) {
|
|||||||
// No break!
|
// No break!
|
||||||
case 'admin/reports/prod-monitor/site/%/edit':
|
case 'admin/reports/prod-monitor/site/%/edit':
|
||||||
$output .= '<p><strong>' . t('Website URL & API key') . '</strong><br />';
|
$output .= '<p><strong>' . t('Website URL & API key') . '</strong><br />';
|
||||||
$output .= t('To add a site, enter it\'s <strong>full url</strong>, including the protocol, but omitting the <em>xmlrpc.php</em> part and the <strong>API key</strong> that you have configured for it using the <strong>Production check</strong> module. Now click the <strong>Get settings</strong> button.').'<br />';
|
$output .= t("To add a site, enter it's <strong>full url</strong>, including the protocol, but omitting the <em>xmlrpc.php</em> part and the <strong>API key</strong> that you have configured for it using the <strong>Production check</strong> module. Now click the <strong>Get settings</strong> button.") . '<br />';
|
||||||
$output .= t('All of the checks that the <em>Production check</em> module can perform are fetched from the remote site and presented as an array of checkboxes. Finally you can configure what exactly you wish to monitor for this site, then hit the <strong>Add site</strong> button.') . '<br />';
|
$output .= t('All of the checks that the <em>Production check</em> module can perform are fetched from the remote site and presented as an array of checkboxes. Finally you can configure what exactly you wish to monitor for this site, then hit the <strong>Add site</strong> button.') . '<br />';
|
||||||
$output .= t('Each time you edit a site, the settings are fetched from the remote server so that any new checks that might have been added to the <em>Production check</em> module there are always up to date in the monitoring section.').'<br />'; $output .= t('<strong>Fetch data immediately</strong> does exactly what it says and fetches all the configured data from the remote site and will direct you to the report page.').'</p>';
|
$output .= t('Each time you edit a site, the settings are fetched from the remote server so that any new checks that might have been added to the <em>Production check</em> module there are always up to date in the monitoring section.') . '<br />';
|
||||||
|
$output .= t('<strong>Fetch data immediately</strong> does exactly what it says and fetches all the configured data from the remote site and will direct you to the report page.') . '</p>';
|
||||||
|
break;
|
||||||
|
case 'admin/reports/prod-monitor/module-lookup':
|
||||||
|
$output .= '<p><strong>' . t('Module name') . '</strong><br />';
|
||||||
|
$output .= t("Enter (part of) the module's machine name to see what sites are using the module.") . '<br />';
|
||||||
break;
|
break;
|
||||||
case 'admin/reports/prod-monitor/site/%':
|
case 'admin/reports/prod-monitor/site/%':
|
||||||
case 'admin/reports/prod-monitor/site/%/view':
|
case 'admin/reports/prod-monitor/site/%/view':
|
||||||
$output .= '<p>'.t('This is an overview of all checks performed by the <em>Production check</em> module and their status <strong>on the remote site</strong>. You can click the links inside the report to jump to the module\'s settings page, or to go to the project page of a module, in case you need to download it for installation.').'</p>';
|
$output .= '<p>' . t("This is an overview of all checks performed by the <em>Production check</em> module and their status <strong>on the remote site</strong>. You can click the links inside the report to jump to the module's settings page, or to go to the project page of a module, in case you need to download it for installation.") . '</p>';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return $output;
|
return $output;
|
||||||
@ -89,6 +97,25 @@ function prod_monitor_menu() {
|
|||||||
'file' => 'includes/prod_monitor.admin.inc',
|
'file' => 'includes/prod_monitor.admin.inc',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Default primary tab (callback for this is it's parent path).
|
||||||
|
$items['admin/reports/prod-monitor/overview'] = array(
|
||||||
|
'title' => 'Overview',
|
||||||
|
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||||||
|
'weight' => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
$items['admin/reports/prod-monitor/module-lookup'] = array(
|
||||||
|
'title' => 'Module lookup',
|
||||||
|
'description' => 'Searches monitored applications for module versions.',
|
||||||
|
'page callback' => 'drupal_get_form',
|
||||||
|
'page arguments' => array('prod_monitor_module_lookup_form'),
|
||||||
|
'access callback' => 'user_access',
|
||||||
|
'access arguments' => array('access production monitor'),
|
||||||
|
'type' => MENU_LOCAL_TASK,
|
||||||
|
'file' => 'includes/prod_monitor.admin.inc',
|
||||||
|
'weight' => 1,
|
||||||
|
);
|
||||||
|
|
||||||
// This hook_menu() thing, still can't fully see the logic in it. However,
|
// This hook_menu() thing, still can't fully see the logic in it. However,
|
||||||
// this here is what I want to achieve. It would be nice to see the /view/ bit
|
// this here is what I want to achieve. It would be nice to see the /view/ bit
|
||||||
// in the path dissapear, that would finish it entirely. I'll settle for this
|
// in the path dissapear, that would finish it entirely. I'll settle for this
|
||||||
@ -330,8 +357,10 @@ function prod_monitor_cron() {
|
|||||||
foreach ($sites as $id => $site_info) {
|
foreach ($sites as $id => $site_info) {
|
||||||
$elapsed = time() - $cron_start;
|
$elapsed = time() - $cron_start;
|
||||||
if ($elapsed < $time_limit) {
|
if ($elapsed < $time_limit) {
|
||||||
//TODO: add module status update check here.
|
// First: all checks.
|
||||||
_prod_monitor_retrieve_data($id, $site_info);
|
_prod_monitor_retrieve_data($id, $site_info);
|
||||||
|
// MUST be second because of the status update!
|
||||||
|
_prod_monitor_db_connect_check($id, $site_info);
|
||||||
$process++;
|
$process++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -504,6 +533,42 @@ function _prod_monitor_retrieve_data($id, $site_info, $msg = FALSE) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform separate dbconnect check. We cannot incorporate this at the side of
|
||||||
|
* prod_check as this would make no sense at all when the DB is down.
|
||||||
|
*/
|
||||||
|
function _prod_monitor_db_connect_check($id, $site_info) {
|
||||||
|
// Execute only if setup properly.
|
||||||
|
if (empty($site_info['settings']['dbconnect_path'])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the check.
|
||||||
|
$dbconnect_path = rtrim($site_info['url'], '/') . '/' . $site_info['settings']['dbconnect_path'];
|
||||||
|
$response = drupal_http_request($dbconnect_path);
|
||||||
|
if ($response->code !== '200' && $response->data !== 'OK') {
|
||||||
|
// Update status to notify the user of the problem!
|
||||||
|
$site_info['status'] = PROD_MONITOR_REQUIREMENT_ERROR;
|
||||||
|
$response->data = 'NOK';
|
||||||
|
}
|
||||||
|
|
||||||
|
// ALWAYS get stored site data as it should have been updated right before
|
||||||
|
// calling this function!
|
||||||
|
$site_data = _prod_monitor_get_site($id, 'data');
|
||||||
|
// Add data to site and save.
|
||||||
|
$site_data['data']['prod_mon']['prod_check_dbconnect'] = $response->code . ' ' . $response->data;
|
||||||
|
|
||||||
|
// Store site data
|
||||||
|
$site = new stdClass();
|
||||||
|
$site->id = $id;
|
||||||
|
if (isset($site_info['status'])) {
|
||||||
|
$site->status = $site_info['status'];
|
||||||
|
}
|
||||||
|
$site->data = serialize($site_data['data']);
|
||||||
|
$site->lastupdate = REQUEST_TIME;
|
||||||
|
$result = drupal_write_record('prod_monitor_sites', $site, array('id'));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to get all sites.
|
* Helper function to get all sites.
|
||||||
*/
|
*/
|
||||||
@ -526,7 +591,7 @@ function _prod_monitor_get_sites($start_id = FALSE) {
|
|||||||
if (!empty($row->data)) {
|
if (!empty($row->data)) {
|
||||||
foreach ($row->data as $set => $checks) {
|
foreach ($row->data as $set => $checks) {
|
||||||
foreach ($checks as $check => $results) {
|
foreach ($checks as $check => $results) {
|
||||||
$status = ($results['severity'] > $status) ? $results['severity'] : $status;
|
$status = (isset($results['severity']) && $results['severity'] > $status) ? $results['severity'] : $status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$data_status = TRUE;
|
$data_status = TRUE;
|
||||||
@ -561,21 +626,33 @@ function _prod_monitor_get_sites($start_id = FALSE) {
|
|||||||
*
|
*
|
||||||
* @param $id
|
* @param $id
|
||||||
* int site id.
|
* int site id.
|
||||||
* @param $all
|
* @param $type
|
||||||
* Boolean whether or not to return all fields or just the url and settings.
|
* String the amount of data to be returned.
|
||||||
*/
|
*/
|
||||||
function _prod_monitor_get_site($id, $all = FALSE) {
|
function _prod_monitor_get_site($id, $type = 'settings') {
|
||||||
if (!$all) {
|
switch ($type) {
|
||||||
|
case 'settings':
|
||||||
$site = db_query("SELECT url, settings FROM {prod_monitor_sites} WHERE id = :id", array(':id' => $id))->fetchAssoc();
|
$site = db_query("SELECT url, settings FROM {prod_monitor_sites} WHERE id = :id", array(':id' => $id))->fetchAssoc();
|
||||||
}
|
break;
|
||||||
else {
|
case 'all':
|
||||||
$site = db_query("SELECT * FROM {prod_monitor_sites} WHERE id = :id", array(':id' => $id))->fetchAssoc();
|
$site = db_query("SELECT * FROM {prod_monitor_sites} WHERE id = :id", array(':id' => $id))->fetchAssoc();
|
||||||
|
break;
|
||||||
|
case 'data':
|
||||||
|
$site = db_query("SELECT data FROM {prod_monitor_sites} WHERE id = :id", array(':id' => $id))->fetchAssoc();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($site)) {
|
if (!empty($site)) {
|
||||||
$site['settings'] = unserialize($site['settings']);
|
switch ($type) {
|
||||||
if ($all) {
|
case 'all':
|
||||||
$site['data'] = unserialize($site['data']);
|
$site['data'] = unserialize($site['data']);
|
||||||
|
// No break!
|
||||||
|
case 'settings':
|
||||||
|
$site['settings'] = unserialize($site['settings']);
|
||||||
|
break;
|
||||||
|
case 'data':
|
||||||
|
$site['data'] = unserialize($site['data']);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -607,6 +684,25 @@ function _prod_monitor_get_site_modules($id, $exists = FALSE) {
|
|||||||
return $modules;
|
return $modules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of ignored directives by site id.
|
||||||
|
*
|
||||||
|
* @param int $id The site id.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
* - updates array List of project names, whose update status we'll ignore.
|
||||||
|
*/
|
||||||
|
function _prod_monitor_get_site_ignored($id) {
|
||||||
|
$ignored = &drupal_static(__FUNCTION__, array());
|
||||||
|
if (!array_key_exists($id, $ignored)) {
|
||||||
|
$ignored[$id] = module_invoke_all('prod_monitor_ignore', $id) + array(
|
||||||
|
'updates' => array(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ignored[$id];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to get the module status of a site by ID.
|
* Helper function to get the module status of a site by ID.
|
||||||
*
|
*
|
||||||
|
@ -89,7 +89,7 @@ Make any CSS adjustments to your "colorbox_mycolorbox.css" file.
|
|||||||
Load images from custom links in a Colorbox:
|
Load images from custom links in a Colorbox:
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
Add the class "colorbox" to the link and point the src to the image
|
Add the class "colorbox" to the link and point its href attribute to the image
|
||||||
you want to display in the Colorbox.
|
you want to display in the Colorbox.
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,3 +27,18 @@ function hook_colorbox_settings_alter(&$settings, &$style) {
|
|||||||
$style = 'mystyle';
|
$style = 'mystyle';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to override activation of Colobox for the current URL.
|
||||||
|
*
|
||||||
|
* @param $active
|
||||||
|
* A boolean indicating whether colorbox should be active for the current
|
||||||
|
* URL or not.
|
||||||
|
*/
|
||||||
|
function hook_colorbox_active_alter(&$active) {
|
||||||
|
$path = drupal_get_path_alias($_GET['q']);
|
||||||
|
if (drupal_match_path($path, 'admin/config/colorbox_test')) {
|
||||||
|
// Enable colorbox for this URL.
|
||||||
|
$active = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
name = Colorbox
|
name = Colorbox
|
||||||
description = A light-weight, customizable lightbox plugin for jQuery 1.4.3+.
|
description = A light-weight, customizable lightbox plugin for jQuery 1.4.3+.
|
||||||
dependencies[] = libraries (2.x)
|
dependencies[] = libraries (>=2.x)
|
||||||
core = 7.x
|
core = 7.x
|
||||||
configure = admin/config/media/colorbox
|
configure = admin/config/media/colorbox
|
||||||
|
|
||||||
files[] = views/colorbox_handler_field_colorbox.inc
|
files[] = views/colorbox_handler_field_colorbox.inc
|
||||||
|
|
||||||
; Information added by Drupal.org packaging script on 2014-09-12
|
; Information added by Drupal.org packaging script on 2015-10-01
|
||||||
version = "7.x-2.8"
|
version = "7.x-2.10"
|
||||||
core = "7.x"
|
core = "7.x"
|
||||||
project = "colorbox"
|
project = "colorbox"
|
||||||
datestamp = "1410514129"
|
datestamp = "1443691449"
|
||||||
|
|
||||||
|
@ -152,6 +152,9 @@ function _colorbox_active() {
|
|||||||
}
|
}
|
||||||
$page_match = variable_get('colorbox_visibility', 0) == 0 ? !$page_match : $page_match;
|
$page_match = variable_get('colorbox_visibility', 0) == 0 ? !$page_match : $page_match;
|
||||||
|
|
||||||
|
// Allow other modules to change the state of colorbox for the current URL.
|
||||||
|
drupal_alter('colorbox_active', $page_match);
|
||||||
|
|
||||||
return $page_match;
|
return $page_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
* @ingroup themeable
|
* @ingroup themeable
|
||||||
*/
|
*/
|
||||||
function theme_colorbox_image_formatter($variables) {
|
function theme_colorbox_image_formatter($variables) {
|
||||||
|
static $gallery_token = NULL;
|
||||||
$item = $variables['item'];
|
$item = $variables['item'];
|
||||||
$entity_type = $variables['entity_type'];
|
$entity_type = $variables['entity_type'];
|
||||||
$entity = $variables['entity'];
|
$entity = $variables['entity'];
|
||||||
@ -123,6 +124,16 @@ function theme_colorbox_image_formatter($variables) {
|
|||||||
$gallery_id = '';
|
$gallery_id = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If gallery id is not empty add unique per-request token to avoid images being added manually to galleries.
|
||||||
|
if (!empty($gallery_id)) {
|
||||||
|
// Check if gallery token has alrady been set, we need to reuse the token for the whole request.
|
||||||
|
if (is_null($gallery_token)) {
|
||||||
|
// We use a short token since randomness is not critical.
|
||||||
|
$gallery_token = drupal_random_key(8);
|
||||||
|
}
|
||||||
|
$gallery_id = $gallery_id . '-' . $gallery_token;
|
||||||
|
}
|
||||||
|
|
||||||
if ($style_name = $settings['colorbox_image_style']) {
|
if ($style_name = $settings['colorbox_image_style']) {
|
||||||
$path = image_style_url($style_name, $image['path']);
|
$path = image_style_url($style_name, $image['path']);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Drupal.behaviors.initColorbox = {
|
Drupal.behaviors.initColorbox = {
|
||||||
attach: function (context, settings) {
|
attach: function (context, settings) {
|
||||||
if (!$.isFunction($.colorbox)) {
|
if (!$.isFunction($.colorbox) || typeof settings.colorbox === 'undefined') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Drupal.behaviors.initColorboxInline = {
|
Drupal.behaviors.initColorboxInline = {
|
||||||
attach: function (context, settings) {
|
attach: function (context, settings) {
|
||||||
if (!$.isFunction($.colorbox)) {
|
if (!$.isFunction($.colorbox) || typeof settings.colorbox === 'undefined') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$.urlParam = function(name, url){
|
$.urlParam = function(name, url){
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Drupal.behaviors.initColorboxLoad = {
|
Drupal.behaviors.initColorboxLoad = {
|
||||||
attach: function (context, settings) {
|
attach: function (context, settings) {
|
||||||
if (!$.isFunction($.colorbox)) {
|
if (!$.isFunction($.colorbox) || typeof settings.colorbox === 'undefined') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$.urlParams = function (url) {
|
$.urlParams = function (url) {
|
||||||
|
@ -162,10 +162,15 @@ If you would like to have the characters %5B and %5D please use the html entity
|
|||||||
$tokens = $this->get_render_tokens($this->options['alter']);
|
$tokens = $this->get_render_tokens($this->options['alter']);
|
||||||
$popup = filter_xss_admin($this->options['popup']);
|
$popup = filter_xss_admin($this->options['popup']);
|
||||||
$caption = filter_xss_admin($this->options['caption']);
|
$caption = filter_xss_admin($this->options['caption']);
|
||||||
$gallery = drupal_html_class($this->options['custom_gid']);
|
$gallery = filter_xss_admin($this->options['custom_gid']);
|
||||||
$popup = strtr($popup, $tokens);
|
$popup = strtr($popup, $tokens);
|
||||||
$caption = strtr($caption, $tokens);
|
$caption = strtr($caption, $tokens);
|
||||||
$gallery = strtr($gallery, $tokens);
|
$gallery = drupal_html_class(strtr($gallery, $tokens));
|
||||||
|
|
||||||
|
// Return nothing if popup is empty.
|
||||||
|
if (empty($popup)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$width = $this->options['width'] ? $this->options['width'] : '';
|
$width = $this->options['width'] ? $this->options['width'] : '';
|
||||||
$height = $this->options['height'] ? $this->options['height'] : '';
|
$height = $this->options['height'] ? $this->options['height'] : '';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user