From 0bb100a7d637ac51bcdc08f36a3fa154eeff9349 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Tue, 12 Sep 2023 17:47:52 -0300 Subject: [PATCH 1/2] Log by context and status --- classes/QueryLog.php | 218 +++++++++++++++++++++++++++++++++---------- 1 file changed, 171 insertions(+), 47 deletions(-) diff --git a/classes/QueryLog.php b/classes/QueryLog.php index 7b78b0d..f61e442 100644 --- a/classes/QueryLog.php +++ b/classes/QueryLog.php @@ -58,8 +58,36 @@ public function action_admin_init() { check_admin_referer( 'ep-debug-options' ); update_site_option( 'ep_enable_logging', (int) $_POST['ep_enable_logging'] ); + update_site_option( 'ep_query_log_by_status', sanitize_text_field( $_POST['ep_query_log_by_status'] ) ); + if ( ! empty( $_POST['ep_query_log_by_context'] ) ) { + update_site_option( 'ep_query_log_by_context', array_map( 'sanitize_text_field', $_POST['ep_query_log_by_context'] ) ); + } else { + update_site_option( 'ep_query_log_by_context', [] ); + } } else { - register_setting( 'ep-debug', 'ep_enable_logging', 'intval' ); + register_setting( + 'ep-debug', + 'ep_enable_logging', + [ 'sanitize_callback' => 'intval' ] + ); + register_setting( + 'ep-debug', + 'ep_query_log_by_status', + [ + 'type' => 'string', + 'sanitize_callback' => 'sanitize_text_field', + ] + ); + register_setting( + 'ep-debug', + 'ep_query_log_by_context', + [ + 'type' => 'array', + 'sanitize_callback' => function ( $value ) { + return ! empty( $value ) ? array_map( 'sanitize_text_field', $value ) : []; + }, + ] + ); } } @@ -147,48 +175,15 @@ public function is_bulk_index_error( $query ) { * @since 1.3 */ public function log_query( $query, $type ) { - if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { - $enabled = get_site_option( 'ep_enable_logging' ); - } else { - $enabled = get_option( 'ep_enable_logging' ); + if ( ! $this->is_enabled() ) { + return; } - if ( empty( $enabled ) ) { + if ( ! $this->should_log_by_context() ) { return; } - /** - * This filter allows you to map query types to callables. If the callable returns true, - * that query will be logged. - * - * @var array - * @since 1.3 - * @since 2.1.0 Added `bulk_index` - */ - $allowed_log_types = apply_filters( - 'ep_debug_bar_allowed_log_types', - array( - 'put_mapping' => array( $this, 'is_query_error' ), - 'delete_network_alias' => array( $this, 'is_query_error' ), - 'create_network_alias' => array( $this, 'is_query_error' ), - 'bulk_index' => array( $this, 'is_bulk_index_error' ), - 'bulk_index_posts' => array( $this, 'is_query_error' ), - 'delete_index' => array( $this, 'maybe_log_delete_index' ), - 'create_pipeline' => array( $this, 'is_query_error' ), - 'get_pipeline' => array( $this, 'is_query_error' ), - 'query' => array( $this, 'is_query_error' ), - ), - $query, - $type - ); - - if ( isset( $allowed_log_types[ $type ] ) ) { - $do_log = call_user_func( $allowed_log_types[ $type ], $query ); - - if ( ! $do_log ) { - return; - } - } else { + if ( ! $this->should_log_by_status( $query, $type ) ) { return; } @@ -217,11 +212,15 @@ public function log_query( $query, $type ) { */ public function screen_options() { if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { - $log = get_site_option( 'ep_query_log', array() ); - $enabled = get_site_option( 'ep_enable_logging' ); + $log = get_site_option( 'ep_query_log', array() ); + $enabled = get_site_option( 'ep_enable_logging' ); + $by_status = get_site_option( 'ep_query_log_by_status', 'failed' ); + $by_context = get_site_option( 'ep_query_log_by_context', [] ); } else { - $log = get_option( 'ep_query_log', array() ); - $enabled = get_option( 'ep_enable_logging' ); + $log = get_option( 'ep_query_log', array() ); + $enabled = get_option( 'ep_enable_logging' ); + $by_status = get_option( 'ep_query_log_by_status', 'failed' ); + $by_context = get_option( 'ep_query_log_by_context', [] ); } if ( is_array( $log ) ) { @@ -255,6 +254,36 @@ public function screen_options() { severe performance implications on your website. We generally recommend only enabling logging during dashboard indexing and disabling after.', 'debug-bar-elasticpress' ) ); ?> + + + + + + + + + +
+
+
+ + + @@ -359,21 +388,33 @@ public function maybe_add_request_type( array $args, string $path, array $query_ * @return array */ public function maybe_add_request_context( array $args ) : array { - $args['ep_context'] = 'public'; + $args['ep_context'] = $this->get_current_context(); + + return $args; + } + + /** + * Get the current context + * + * @since 3.1.0 + * @return string + */ + protected function get_current_context() : string { + $context = 'public'; if ( is_admin() ) { - $args['ep_context'] = 'admin'; + $context = 'admin'; } if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { - $args['ep_context'] = 'ajax'; + $context = 'ajax'; } if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { - $args['ep_context'] = 'rest'; + $context = 'rest'; } - return $args; + return $context; } /** @@ -428,4 +469,87 @@ protected function determine_request_query_type( array $request_args, string $pa return $type; } + + /** + * Whether logging is enabled or not + * + * @since 3.1.0 + * @return boolean + */ + protected function is_enabled() : bool { + if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { + $enabled = get_site_option( 'ep_enable_logging' ); + } else { + $enabled = get_option( 'ep_enable_logging' ); + } + + return ! empty( $enabled ); + } + + /** + * Whether the current context should or not be logged + * + * @since 3.1.0 + * @return boolean + */ + protected function should_log_by_context() { + if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { + $by_context = get_site_option( 'ep_query_log_by_context', [] ); + } else { + $by_context = get_option( 'ep_query_log_by_context', [] ); + } + + return empty( $by_context ) || in_array( $this->get_current_context(), $by_context, true ); + } + + /** + * Whether a query (and a type) should be logged or not + * + * @since 3.1.0 + * @param array $query Remote request arguments + * @param string $type Query type + * @return boolean + */ + protected function should_log_by_status( array $query, string $type ) : bool { + if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { + $by_status = get_site_option( 'ep_query_log_by_status', 'failed' ); + } else { + $by_status = get_option( 'ep_query_log_by_status', 'failed' ); + } + + if ( 'all' === $by_status ) { + return true; + } + + /** + * This filter allows you to map query types to callables. If the callable returns true, + * that query will be logged. + * + * @var array + * @since 1.3 + * @since 2.1.0 Added `bulk_index` + */ + $allowed_log_types = apply_filters( + 'ep_debug_bar_allowed_log_types', + array( + 'put_mapping' => array( $this, 'is_query_error' ), + 'delete_network_alias' => array( $this, 'is_query_error' ), + 'create_network_alias' => array( $this, 'is_query_error' ), + 'bulk_index' => array( $this, 'is_bulk_index_error' ), + 'bulk_index_posts' => array( $this, 'is_query_error' ), + 'delete_index' => array( $this, 'maybe_log_delete_index' ), + 'create_pipeline' => array( $this, 'is_query_error' ), + 'get_pipeline' => array( $this, 'is_query_error' ), + 'query' => array( $this, 'is_query_error' ), + ), + $query, + $type + ); + + if ( ! isset( $allowed_log_types[ $type ] ) ) { + return false; + } + + return call_user_func( $allowed_log_types[ $type ], $query ); + } } From ad5854cf36b64378f56d38cf3d624c0efbde16d2 Mon Sep 17 00:00:00 2001 From: Felipe Elia Date: Wed, 13 Sep 2023 13:16:54 -0300 Subject: [PATCH 2/2] Set limits for loggin --- classes/QueryLog.php | 160 +++++++++++++++++++++++++++++-------------- 1 file changed, 109 insertions(+), 51 deletions(-) diff --git a/classes/QueryLog.php b/classes/QueryLog.php index f61e442..4dd32c6 100644 --- a/classes/QueryLog.php +++ b/classes/QueryLog.php @@ -9,6 +9,8 @@ namespace DebugBarElasticPress; +use ElasticPress\Utils; + defined( 'ABSPATH' ) || exit; /** @@ -31,6 +33,7 @@ public function setup() { add_action( 'ep_remote_request', array( $this, 'log_query' ), 10, 2 ); add_action( 'admin_init', array( $this, 'action_admin_init' ) ); add_action( 'admin_init', array( $this, 'maybe_clear_log' ) ); + add_action( 'init', array( $this, 'maybe_disable' ) ); /** * Handle query storage as JSON strings. @@ -57,7 +60,7 @@ public function action_admin_init() { if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK && isset( $_POST['ep_enable_logging'] ) ) { check_admin_referer( 'ep-debug-options' ); - update_site_option( 'ep_enable_logging', (int) $_POST['ep_enable_logging'] ); + update_site_option( 'ep_enable_logging', $this->sanitize_enable_logging( $_POST['ep_enable_logging'] ) ); update_site_option( 'ep_query_log_by_status', sanitize_text_field( $_POST['ep_query_log_by_status'] ) ); if ( ! empty( $_POST['ep_query_log_by_context'] ) ) { update_site_option( 'ep_query_log_by_context', array_map( 'sanitize_text_field', $_POST['ep_query_log_by_context'] ) ); @@ -68,21 +71,17 @@ public function action_admin_init() { register_setting( 'ep-debug', 'ep_enable_logging', - [ 'sanitize_callback' => 'intval' ] + [ 'sanitize_callback' => [ $this, 'sanitize_enable_logging' ] ] ); register_setting( 'ep-debug', 'ep_query_log_by_status', - [ - 'type' => 'string', - 'sanitize_callback' => 'sanitize_text_field', - ] + [ 'sanitize_callback' => 'sanitize_text_field' ] ); register_setting( 'ep-debug', 'ep_query_log_by_context', [ - 'type' => 'array', 'sanitize_callback' => function ( $value ) { return ! empty( $value ) ? array_map( 'sanitize_text_field', $value ) : []; }, @@ -101,11 +100,7 @@ public function maybe_clear_log() { return; } - if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { - delete_site_option( 'ep_query_log' ); - } else { - delete_option( 'ep_query_log' ); - } + Utils\delete_option( 'ep_query_log' ); wp_safe_redirect( remove_query_arg( 'ep_clear_query_log' ) ); exit(); @@ -187,22 +182,19 @@ public function log_query( $query, $type ) { return; } - if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { - $log = get_site_option( 'ep_query_log', array() ); - } else { - $log = get_option( 'ep_query_log', array() ); - } + $log = Utils\get_option( 'ep_query_log', [] ); $log[] = array( 'query' => $query, 'type' => $type, ); - if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { - update_site_option( 'ep_query_log', $log ); - } else { - update_option( 'ep_query_log', $log ); + // Storing this log would exceed the limit + if ( mb_strlen( maybe_serialize( $log ) ) > $this->get_logging_storage_limit() ) { + return; } + + Utils\update_option( 'ep_query_log', $log ); } /** @@ -211,17 +203,10 @@ public function log_query( $query, $type ) { * @since 1.3 */ public function screen_options() { - if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { - $log = get_site_option( 'ep_query_log', array() ); - $enabled = get_site_option( 'ep_enable_logging' ); - $by_status = get_site_option( 'ep_query_log_by_status', 'failed' ); - $by_context = get_site_option( 'ep_query_log_by_context', [] ); - } else { - $log = get_option( 'ep_query_log', array() ); - $enabled = get_option( 'ep_enable_logging' ); - $by_status = get_option( 'ep_query_log_by_status', 'failed' ); - $by_context = get_option( 'ep_query_log_by_context', [] ); - } + $log = Utils\get_option( 'ep_query_log', array() ); + $enabled = Utils\get_option( 'ep_enable_logging' ); + $by_status = Utils\get_option( 'ep_query_log_by_status', 'failed' ); + $by_context = Utils\get_option( 'ep_query_log_by_context', [] ); if ( is_array( $log ) ) { $log = array_reverse( $log ); @@ -232,6 +217,8 @@ public function screen_options() { if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { $action = ''; } + + $is_time_limit = ! empty( $enabled ) && ! in_array( $enabled, [ '0', 0, '-1' ], true ); ?>
@@ -244,14 +231,32 @@ public function screen_options() { - + @@ -287,6 +292,18 @@ public function screen_options() {
+ +
- severe performance implications on your website. We generally recommend only enabling logging during dashboard indexing and disabling after.', 'debug-bar-elasticpress' ) ); ?> + + severe performance implications on your website.', 'debug-bar-elasticpress' ) ); + if ( $is_time_limit ) { + echo ' ' . wp_kses_post( + sprintf( + /* translators: date */ + __( 'Logging queries until %s.', 'debug-bar-elasticpress' ), + wp_date( 'Y-m-d H:i:s', $enabled ) + ) + ); + } + ?> +
+

+ %s', 'debug-bar-elasticpress' ), + size_format( $this->get_logging_storage_limit() ) + ) + ); + ?> +

+

@@ -477,11 +494,7 @@ protected function determine_request_query_type( array $request_args, string $pa * @return boolean */ protected function is_enabled() : bool { - if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { - $enabled = get_site_option( 'ep_enable_logging' ); - } else { - $enabled = get_option( 'ep_enable_logging' ); - } + $enabled = Utils\get_option( 'ep_enable_logging' ); return ! empty( $enabled ); } @@ -493,11 +506,7 @@ protected function is_enabled() : bool { * @return boolean */ protected function should_log_by_context() { - if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { - $by_context = get_site_option( 'ep_query_log_by_context', [] ); - } else { - $by_context = get_option( 'ep_query_log_by_context', [] ); - } + $by_context = Utils\get_option( 'ep_query_log_by_context', [] ); return empty( $by_context ) || in_array( $this->get_current_context(), $by_context, true ); } @@ -510,12 +519,8 @@ protected function should_log_by_context() { * @param string $type Query type * @return boolean */ - protected function should_log_by_status( array $query, string $type ) : bool { - if ( defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) { - $by_status = get_site_option( 'ep_query_log_by_status', 'failed' ); - } else { - $by_status = get_option( 'ep_query_log_by_status', 'failed' ); - } + protected function should_log_by_status( array $query, $type ) : bool { + $by_status = Utils\get_option( 'ep_query_log_by_status', 'failed' ); if ( 'all' === $by_status ) { return true; @@ -552,4 +557,57 @@ protected function should_log_by_status( array $query, string $type ) : bool { return call_user_func( $allowed_log_types[ $type ], $query ); } + + /** + * Return the size limit for stored logs + * + * @since 3.1.0 + * @return integer + */ + protected function get_logging_storage_limit() : int { + /** + * Filter the log size limit + * + * @since 3.1.0 + * @hook ep_debug_bar_log_size_limit + * @param {int} $number Log size limit + * @return {int} New limit + */ + return apply_filters( 'ep_debug_bar_log_size_limit', MB_IN_BYTES ); + } + + /** + * Conditionally disable logging based on period + * + * @since 3.1.0 + */ + public function maybe_disable() { + $enabled = Utils\get_option( 'ep_enable_logging' ); + + $is_time_limit = ! empty( $enabled ) && ! in_array( $enabled, [ '0', 0, '-1' ], true ); + if ( ! $is_time_limit || $enabled > wp_date( 'U' ) ) { + return; + } + + Utils\update_option( 'ep_enable_logging', 0 ); + } + + /** + * Sanitize the ep_enable_logging option, conditionally setting it as a time limit + * + * @since 3.1.0 + * @param mixed $value Value sent + * @return mixed + */ + public function sanitize_enable_logging( $value ) { + $value = sanitize_text_field( $_POST['ep_enable_logging'] ); + + if ( 'time_limit' === $value ) { + $value = wp_date( 'U', strtotime( '+5 minutes' ) ); + } else { + $value = (int) ! empty( $value ); + } + + return $value; + } }