この記事は最後に更新してから1年以上経過しています。

5.3の新機能:クエリーログに任意の項目を追加できる新フィルター

説明

5.3 RC2」が公開され、正式リリースまであと20日。公式ディレクトリにプラグインを公開していることもあり、5.3に関する開発者向けの情報「Miscellaneous Developer Focused Changes in 5.3」を読んでいる。

ちょっと気になる'log_query_custom_data'フィルター

このページでは register_post_type関数や add_theme_support関数の変更内容に続いて記載されていた「Recording Additional Information For Saved Queries.」の項目が気になった。

WordPressはwp-config.phpに次の記述を指定することで、

$wpdb->queries
(配列)にデータベースに対して実行したクエリー情報を保持する仕組みがある。

define( 'SAVEQUERIES', true );

テーマのfooter.phpの適当なところに次の記述を追加する。

<?php print_r( $GLOBALS['wpdb']->queries ); ?>

5.2.4でサイトのトップページを表示すると、フッターには次のような内容が出力される(抜粋)。

Array
(
    [0] => Array
        (
            [0] => SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes'
            [1] => 0.00094008445739746
            [2] => require('wp-blog-header.php'), require_once('wp-load.php'), require_once('wp-config.php'), require_once('wp-settings.php'), wp_not_installed, is_blog_installed, wp_load_alloptions
            [3] => 1571819572.1011
        )

    [1] => Array
        (
            [0] => SELECT * FROM wp_users WHERE user_login = 'xxxxxxxx' LIMIT 1
            [1] => 0.00076103210449219
            [2] => require('wp-blog-header.php'), require_once('wp-load.php'), require_once('wp-config.php'), require_once('wp-settings.php'), WP->init, wp_get_current_user, _wp_get_current_user, apply_filters('determine_current_user'), WP_Hook->apply_filters, wp_validate_logged_in_cookie, wp_validate_auth_cookie, get_user_by, WP_User::get_data_by
            [3] => 1571819572.3205
        )

:

1つ1つのクエリー情報は、キー0がクエリー文、キー1が実行時間(秒)、キー2が関数の呼び出し情報(カンマ区切り)、キー3が開始時刻(秒)となっている。

5.3では、'log_query_custom_data'フィルターを使用することで任意の情報(配列)が保持できるようになる。次のコードを追加してAJAXリクエストか判別する情報を追加してみよう。

function my_log_query_custom_data( $query_data, $query, $query_time, $query_callstack, $query_start ) {
	$query_data['AJAX'] = wp_doing_ajax()? 1: 0;
	return $query_data;
}

add_filter( 'log_query_custom_data', 'my_log_query_custom_data', 10, 5 );

5.3.0 RC2でサイトのトップページを表示してみると、フッターには次のような内容が出力される(抜粋)。

Array
(
    [0] => Array
        (
            [0] => SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes'
            [1] => 0.0012838840484619
            [2] => require('wp-blog-header.php'), require_once('wp-load.php'), require_once('wp-config.php'), require_once('wp-settings.php'), wp_not_installed, is_blog_installed, wp_load_alloptions
            [3] => 1571820657.1323
            [4] => Array
                (
                )

        )

    [1] => Array
        (
            [0] => SELECT * FROM wp_users WHERE user_login = 'xxxxxxxx' LIMIT 1
            [1] => 0.00050902366638184
            [2] => require('wp-blog-header.php'), require_once('wp-load.php'), require_once('wp-config.php'), require_once('wp-settings.php'), WP->init, wp_get_current_user, _wp_get_current_user, apply_filters('determine_current_user'), WP_Hook->apply_filters, wp_validate_logged_in_cookie, wp_validate_auth_cookie, get_user_by, WP_User::get_data_by
            [3] => 1571820657.3485
            [4] => Array
                (
                    [AJAX] => 0
                )

        )

:

各クエリー情報のキー4には配列が追加され、1つ目のクエリー情報は(フィルターの適用前なので)空の配列が、2つ目にはキー'AJAX'に値0が格納されている。このようにキー4に格納される配列は、'log_query_custom_data'フィルターを追加したタイミングの影響を受ける。

'log_query_custom_data'フィルターでログ出力

'log_query_custom_data'フィルターは本来の主旨と違う気がするが、クエリーを実行した直後にそのクエリー情報をログファイルに出力することも可能だ。

まずはwp-config.phpの内容から('WP_DEBUG_LOG'に指定するログファイルのパス名は適宜修正)。

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', '/var/www/html/wp-content/debug.log' );
define( 'SAVEQUERIES', true );

次にテーマのfunctions.phpの追記。こちらはログファイルに出力する内容によって変わるが、ここでは実行時間を示すパラメータ$query_timeを判定し、2秒以上の場合は余分な空白文字を除去したクエリー文、実行時間、関数の呼び出し情報をログファイルに出力している。

function my_log_query_custom_data( $query_data, $query, $query_time, $query_callstack, $query_start ) {
	if ( 2.0 <= $query_time ) {
		error_log( trim( preg_replace( '/\s+/', ' ', $query ) ) );
		error_log( sprintf( '%.2f', $query_time ) .'s # ' . $query_callstack );
	}
	return $query_data;
}

add_filter( 'log_query_custom_data', 'my_log_query_custom_data', 10, 5 );

余裕があればテーマのfunctions.phpではなく、プラグインによる実装がよいとは思うが、本番環境が重くなり、取り急ぎ原因を調べる一環で「重いクエリー」を探す場合は、このような方法も有効だろう。


最終更新 : 2019年10月23日 20:20


お勧め

delete_post_meta(2018年5月27日 更新)

bool delete_post_meta( int $post_id, string $meta_key [ , mixed $meta_value = '' ] )
投稿情報のカスタムフィールド情報を削除する。

wp_is_numeric_array(2018年5月27日 更新)

bool wp_is_numeric_array( mixed $data )
数値キーのみの配列か調べる。

get_tag_regex(2013年8月3日 更新)

string get_tag_regex( string $tag )
HTMLタグの正規表現パターンを取得する。

get_all_page_ids(2012年5月30日 更新)

array get_all_page_ids( )
全ページ(post_typeが'page')の投稿IDを取得する。

the_post_thumbnail_caption(2018年5月27日 更新)

void the_post_thumbnail_caption( mixed $post = null )
投稿ページのサムネイル(アイキャッチ画像)キャプションを表示する。