'CPU',
'mem' => 'MEM',
'disk' => 'HDD',
);
if ( ! Settings::get_option( 'advana_server_info_cpu_enable' ) ) {
unset( $metrics['cpu'] );
}
if ( ! Settings::get_option( 'advana_server_info_mem_enable' ) ) {
unset( $metrics['mem'] );
}
if ( ! Settings::get_option( 'advana_server_info_hdd_enable' ) ) {
unset( $metrics['disk'] );
}
foreach ( $metrics as $id => $label ) {
$wp_admin_bar->add_node(
array(
'id' => "advan-usage-$id",
'title' => sprintf(
'
',
\esc_attr( $id ),
\esc_html( $label )
),
'href' => false,
'meta' => array(
'title' => $label . \esc_attr__( ' Usage', '0-day-analytics' ),
'class' => 'advan-usage-item-wrapper',
),
)
);
}
}
/**
* Render the admin page for server status.
*
* @return void
*
* @since 3.9.3
*/
public static function render_admin_page() {
$nonce = \wp_create_nonce( 'wp_rest' );
?>
$cpu,
'memory_usage' => $mem,
'disk_usage' => $disk,
'timestamp' => \current_time( 'mysql' ),
);
return new \WP_REST_Response(
array(
'success' => true,
'data' => $data,
),
200
);
}
/**
* Get the current CPU usage.
*
* @return float|null
*
* @since 3.9.3
*/
public static function get_cpu_usage() {
$os = strtolower( PHP_OS );
if ( function_exists( 'sys_getloadavg' ) ) {
$load = sys_getloadavg();
if ( is_array( $load ) && isset( $load[0] ) ) {
$cpu_count = 1;
if ( @is_readable( '/proc/cpuinfo' ) ) {
$cpu_count = (int) shell_exec( 'nproc 2>/dev/null' ) ?: 1;
} elseif ( stripos( $os, 'win' ) === 0 ) {
$cpu_count = (int) getenv( 'NUMBER_OF_PROCESSORS' ) ?: 1;
}
return round( ( $load[0] / $cpu_count ) * 100, 2 );
}
}
if ( stripos( $os, 'linux' ) === 0 && @is_readable( '/proc/stat' ) ) {
$get_cpu_stat = function () {
$data = @file( '/proc/stat' );
if ( ! $data || ! isset( $data[0] ) ) {
return null;
}
$parts = preg_split( '/\s+/', trim( $data[0] ) );
return array_slice( $parts, 1, 4 );
};
$stat1 = $get_cpu_stat();
if ( null === $stat1 ) {
return null;
}
usleep( 500000 );
$stat2 = $get_cpu_stat();
if ( null === $stat2 ) {
return null;
}
$diff = array();
for ( $i = 0; $i < 4; $i++ ) {
$diff[ $i ] = $stat2[ $i ] - $stat1[ $i ];
}
$total = array_sum( $diff );
if ( 0 == $total ) {
return null;
}
$cpu_percent = ( $total - $diff[3] ) * 100 / $total;
return round( $cpu_percent, 2 );
}
if ( stripos( $os, 'win' ) === 0 && function_exists( 'shell_exec' ) ) {
$output = @shell_exec( 'wmic cpu get loadpercentage 2>NUL' );
if ( $output ) {
preg_match_all( '/\d+/', $output, $matches );
if ( ! empty( $matches[0] ) ) {
return round( array_sum( $matches[0] ) / count( $matches[0] ), 2 );
}
}
}
if ( function_exists( 'shell_exec' ) && stripos( $os, 'linux' ) === 0 ) {
$output = @shell_exec( "top -bn1 | grep 'Cpu(s)' 2>/dev/null" );
if ( $output && preg_match( '/(\d+\.\d+)\s*id/', $output, $matches ) ) {
$idle = (float) $matches[1];
return round( 100 - $idle, 2 );
}
}
return null;
}
/**
* Get the current memory usage.
*
* @return float|null
*
* @since 3.9.3
*/
public static function get_memory_usage() {
$os = strtolower( PHP_OS );
if ( stripos( $os, 'linux' ) === 0 && @is_readable( '/proc/meminfo' ) ) {
$data = @file( '/proc/meminfo' );
$meminfo = array();
if ( false === $data ) {
return null;
}
foreach ( $data as $line ) {
[$key, $val] = explode( ':', $line );
$meminfo[ $key ] = trim( $val );
}
$total = (int) filter_var( $meminfo['MemTotal'] ?? 0, FILTER_SANITIZE_NUMBER_INT );
$free = (int) filter_var( $meminfo['MemAvailable'] ?? 0, FILTER_SANITIZE_NUMBER_INT );
if ( $total > 0 ) {
$used_percent = 100 - ( ( $free / $total ) * 100 );
return round( $used_percent, 2 );
}
}
if ( stripos( $os, 'win' ) === 0 && function_exists( 'shell_exec' ) ) {
$output = @shell_exec( 'wmic OS get FreePhysicalMemory,TotalVisibleMemorySize /Value' );
if ( $output && preg_match_all( '/(\d+)/', $output, $matches ) ) {
if ( count( $matches[0] ) >= 2 ) {
$free = (int) $matches[0][0];
$total = (int) $matches[0][1];
if ( $total > 0 ) {
$used_percent = 100 - ( ( $free / $total ) * 100 );
return round( $used_percent, 2 );
}
}
}
}
return null;
}
/**
* Check if a path is allowed by open_basedir restrictions.
*
* @param string $path The path to check.
*
* @return bool
*
* @since 4.2.0
*/
public static function is_allowed_by_open_base_dir( string $path ): bool {
$ob = ini_get( 'open_basedir' );
if ( ! $ob ) {
return true; // no restrictions.
}
$allowed = explode( PATH_SEPARATOR, $ob );
$real = @realpath( $path );
if ( false === $real ) {
return false;
}
foreach ( $allowed as $dir ) {
$dir = rtrim( $dir, '/' );
if ( strpos( $real, $dir ) === 0 ) {
return true;
}
}
return false;
}
/**
* Returns the disk usage
*
* @return int|null
*
* @since 3.9.3
*/
public static function get_disk_usage() {
$total = @disk_total_space( '/' );
if ( self::is_allowed_by_open_base_dir( '/' ) ) {
$free = @disk_free_space( '/' );
}
if ( $total && $free ) {
$used = 100 - ( ( $free / $total ) * 100 );
return round( $used, 2 );
}
return null;
}
/**
* Get system summary HTML.
*
* @param bool $include_ids Whether to include element IDs for JS updates.
*
* @return string
*
* @since 3.9.3
*/
public static function get_system_summary( $include_ids = false ) {
if ( ! Settings::get_option( 'advana_server_info_cpu_enable' ) ) {
$cpu = 0;
} else {
$cpu = self::get_cpu_usage();
}
if ( ! Settings::get_option( 'advana_server_info_mem_enable' ) ) {
$mem = 0;
} else {
$mem = self::get_memory_usage();
}
if ( ! Settings::get_option( 'advana_server_info_hdd_enable' ) ) {
$disk = 0;
} else {
$disk = self::get_disk_usage();
}
// Additional system info
$uptime = self::get_server_uptime();
$load_avg = self::get_load_average();
$php_version = PHP_VERSION;
$wp_version = get_bloginfo( 'version' );
$active_plugins = count( get_option( 'active_plugins', array() ) );
$current_theme = wp_get_theme()->get( 'Name' );
$mysql_version = self::get_mysql_version();
$swap_usage = self::get_swap_usage();
$php_memory_limits = self::get_php_memory_limits();
$database_size = self::get_database_size();
$server_timezone = self::get_server_timezone();
$wordpress_memory_usage = self::get_wordpress_memory_usage();
$php_extensions_count = self::get_php_extensions_count();
$server_architecture = self::get_server_architecture();
$total_users = self::get_total_users();
$bar_color = function ( $percent ) {
if ( $percent < 55 ) {
return '#2ecc71';
}
if ( $percent < 80 ) {
return '#e67e22';
}
return '#e74c3c';
};
ob_start();
?>
:
:
:
:
:
:
:
: %
:
:
:
:
:
:
:
= 80) return '#e74d3c86';
if(val >= 55) return '#e67d227a';
return '#05582890';
}
function updateMetric(id, val){
const color = colorForPercent(val);
const item = $('#advan-usage-item-' + id);
item.find('.advan-usage-fill').css({
height: val + '%',
background: color
});
item.find('.advan-usage-value').text(val.toFixed(0) + '%');
}
function refreshMetrics(){
$.getJSON('$ajax', {
action: 'advan_get_system_usage',
_ajax_nonce: '$nonce'
}).done(function(response){
if ( response.success ) {
updateMetric('cpu', response.data.cpu ?? 0);
updateMetric('mem', response.data.mem ?? 0);
updateMetric('disk', response.data.disk ?? 0);
}
});
}
$(document).ready(function(){
refreshMetrics();
setInterval(refreshMetrics, $secs);
});
})(jQuery);
JS;
}
/**
* Enqueue styles and scripts for admin bar.
*
* @return void
*
* @since 3.9.3
*/
public static function enqueue_styles() {
if ( ! \is_admin_bar_showing() || ! \current_user_can( 'manage_options' ) ) {
return;
}
\wp_add_inline_style( 'wp-admin', self::inline_css() );
\wp_add_inline_script( 'jquery-core', self::inline_js(), 'after' );
}
/**
* Get server uptime.
*
* @return string
*
* @since 4.4.1
*/
public static function get_server_uptime() {
if ( @is_readable( '/proc/uptime' ) ) {
$uptime = @file_get_contents( '/proc/uptime' );
if ( $uptime ) {
$uptime = explode( ' ', $uptime )[0];
return self::format_uptime( (int) $uptime );
}
}
return __( 'N/A', '0-day-analytics' );
}
/**
* Format uptime seconds into readable string.
*
* @param int $seconds Uptime in seconds.
* @return string
*
* @since 4.4.1
*/
private static function format_uptime( $seconds ) {
$days = floor( $seconds / 86400 );
$hours = floor( ( $seconds % 86400 ) / 3600 );
$minutes = floor( ( $seconds % 3600 ) / 60 );
$parts = array();
if ( $days > 0 ) {
$parts[] = sprintf( _n( '%d day', '%d days', $days, '0-day-analytics' ), $days );
}
if ( $hours > 0 ) {
$parts[] = sprintf( _n( '%d hour', '%d hours', $hours, '0-day-analytics' ), $hours );
}
if ( $minutes > 0 ) {
$parts[] = sprintf( _n( '%d minute', '%d minutes', $minutes, '0-day-analytics' ), $minutes );
}
return implode( ', ', $parts );
}
/**
* Get load average.
*
* @return array
*
* @since 4.4.1
*/
public static function get_load_average() {
if ( function_exists( 'sys_getloadavg' ) ) {
$load = sys_getloadavg();
if ( is_array( $load ) ) {
return array_map( function( $val ) {
return round( $val, 2 );
}, $load );
}
}
return array( 0, 0, 0 );
}
/**
* Get MySQL version.
*
* @return string
*
* @since 4.4.1
*/
public static function get_mysql_version() {
global $wpdb;
return $wpdb->get_var( "SELECT VERSION()" ) ?: __( 'N/A', '0-day-analytics' );
}
/**
* Get swap usage percentage.
*
* @return float|null
*
* @since 4.4.1
*/
public static function get_swap_usage() {
if ( stripos( strtolower( PHP_OS ), 'linux' ) === 0 && @is_readable( '/proc/meminfo' ) ) {
$data = @file( '/proc/meminfo' );
if ( $data ) {
$meminfo = array();
foreach ( $data as $line ) {
[ $key, $val ] = explode( ':', $line );
$meminfo[ $key ] = trim( $val );
}
$total = (int) filter_var( $meminfo['SwapTotal'] ?? 0, FILTER_SANITIZE_NUMBER_INT );
$free = (int) filter_var( $meminfo['SwapFree'] ?? 0, FILTER_SANITIZE_NUMBER_INT );
if ( $total > 0 ) {
$used_percent = 100 - ( ( $free / $total ) * 100 );
return round( $used_percent, 2 );
}
}
}
return null;
}
/**
* Get PHP memory limits.
*
* @return string
*
* @since 4.4.1
*/
public static function get_php_memory_limits() {
$memory_limit = ini_get( 'memory_limit' );
$post_max_size = ini_get( 'post_max_size' );
$upload_max_filesize = ini_get( 'upload_max_filesize' );
return sprintf(
__( 'Memory: %s, Post: %s, Upload: %s', '0-day-analytics' ),
$memory_limit,
$post_max_size,
$upload_max_filesize
);
}
/**
* Get database size in MB.
*
* @return string
*
* @since 4.4.1
*/
public static function get_database_size() {
global $wpdb;
$size = $wpdb->get_var(
"SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb
FROM information_schema.tables
WHERE table_schema = DATABASE()"
);
return $size ? $size . ' MB' : __( 'N/A', '0-day-analytics' );
}
/**
* Get server timezone.
*
* @return string
*
* @since 4.4.1
*/
public static function get_server_timezone() {
return date_default_timezone_get();
}
/**
* Get WordPress memory usage.
*
* @return string
*
* @since 4.4.1
*/
public static function get_wordpress_memory_usage() {
$wp_memory_limit = WP_MEMORY_LIMIT;
$wp_max_memory_limit = WP_MAX_MEMORY_LIMIT;
return sprintf(
__( 'WP Limit: %s, Max: %s', '0-day-analytics' ),
$wp_memory_limit,
$wp_max_memory_limit
);
}
/**
* Get PHP extensions count.
*
* @return int
*
* @since 4.4.1
*/
public static function get_php_extensions_count() {
return count( get_loaded_extensions() );
}
/**
* Get server architecture.
*
* @return string
*
* @since 4.4.1
*/
public static function get_server_architecture() {
return php_uname( 'm' );
}
/**
* Get total users.
*
* @return int
*
* @since 4.4.1
*/
public static function get_total_users() {
$user_count = count_users();
return $user_count['total_users'];
}
/**
* AJAX handler to get system usage.
*
* @return void
*
* @since 3.9.3
*/
public static function ajax_get_system_usage() {
// Verify nonce to mitigate CSRF on privileged AJAX action.
if ( ! \check_ajax_referer( 'advan-system-usage', '_ajax_nonce', false ) ) {
\wp_send_json_error( array( 'message' => __( 'Invalid request.', '0-day-analytics' ) ), 403 );
}
if ( ! \current_user_can( 'manage_options' ) ) {
\wp_send_json_error();
}
$data = array(
'cpu' => self::get_cpu_usage(),
'mem' => self::get_memory_usage(),
'disk' => self::get_disk_usage(),
);
\wp_send_json_success( $data );
}
}
}