log_file = WP_CONTENT_DIR . '/realtime-debug.log'; $this->request_id = uniqid('req_', true); $this->start_time = microtime(true); // Очищаем файл при инициализации $this->clean_log_file(); $this->init(); } /** * Очистка лог-файла с проверками */ private function clean_log_file() { // Если файл не существует, создаем его if (!file_exists($this->log_file)) { if (touch($this->log_file)) { chmod($this->log_file, 0644); $this->log_message("Создан новый лог-файл", 'SYSTEM'); } else { error_log('Не удалось создать файл realtime-debug.log'); return; } } // Проверяем доступность для записи if (!is_writable($this->log_file)) { error_log('Файл realtime-debug.log недоступен для записи'); return; } // Очищаем файл if (file_put_contents($this->log_file, '') === false) { error_log('Не удалось очистить файл realtime-debug.log'); } else { $this->log_message("Лог-файл очищен", 'SYSTEM'); } } private function init() { // Начинаем логирование как можно раньше add_action('plugins_loaded', [$this, 'log_plugins_loaded'], 1); add_action('setup_theme', [$this, 'log_setup_theme'], 1); add_action('after_setup_theme', [$this, 'log_after_setup_theme'], 1); add_action('init', [$this, 'log_init'], 1); // Логируем все основные этапы add_action('wp_loaded', [$this, 'log_wp_loaded']); add_action('parse_query', [$this, 'log_parse_query']); add_action('pre_get_posts', [$this, 'log_pre_get_posts']); add_action('wp', [$this, 'log_wp']); // Логируем SQL запросы add_filter('query', [$this, 'log_sql_query']); // Логируем шаблоны add_filter('template_include', [$this, 'log_template_include'], 9999); // Логируем завершение add_action('shutdown', [$this, 'log_shutdown'], 9999); // Логируем хуки в реальном времени $this->setup_hook_logging(); } public function setup_hook_logging() { $important_hooks = [ 'template_redirect', 'get_header', 'wp_head', 'the_post', 'loop_start', 'loop_end', 'get_sidebar', 'get_footer', 'wp_footer', 'admin_bar_menu', 'wp_enqueue_scripts', 'wp_print_styles', 'wp_print_scripts' ]; foreach ($important_hooks as $hook) { add_action($hook, function() use ($hook) { $this->log_hook($hook); }, 1); } } private function log_message($message, $level = 'INFO') { $timestamp = microtime(true); $elapsed = round(($timestamp - $this->start_time) * 1000, 2); $memory = memory_get_usage(true); $log = sprintf( "[%s] %s | %6.2fms | %8s | %s | %s\n", date('H:i:s'), $this->request_id, $elapsed, size_format($memory, 0), $level, $message ); file_put_contents($this->log_file, $log, FILE_APPEND); } public function log_plugins_loaded() { $this->log_message('PLUGINS_LOADED - Плагины загружены'); } public function log_setup_theme() { $this->log_message('SETUP_THEME - Начинается загрузка темы'); } public function log_after_setup_theme() { $this->log_message('AFTER_SETUP_THEME - Тема загружена'); } public function log_init() { $this->log_message('INIT - WordPress инициализирован'); } public function log_wp_loaded() { $this->log_message('WP_LOADED - WordPress полностью загружен'); } public function log_parse_query() { global $wp_query; $this->log_message(sprintf('PARSE_QUERY - Запрос: %s', $wp_query->query_vars['pagename'] ?? 'main')); } public function log_pre_get_posts($query) { if ($query->is_main_query()) { $this->log_message('PRE_GET_POSTS - Основной запрос к posts'); } } public function log_wp() { $this->log_message('WP - Запрос обработан, готовим данные для шаблона'); } public function log_sql_query($query) { $trimmed = trim($query); if (!empty($trimmed) && !str_starts_with($trimmed, '/*')) { //$short_query = substr($trimmed, 0, 150); //if (strlen($trimmed) > 150) { // $short_query .= '...'; // } $this->log_message("SQL: {$query}", 'SQL'); } return $query; } public function log_hook($hook) { $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 4); $caller = $this->get_caller_info($backtrace); $this->log_message("HOOK: {$hook} → {$caller}", 'HOOK'); } public function log_template_include($template) { $template_name = basename($template); $this->log_message("TEMPLATE: {$template_name}", 'TEMPLATE'); return $template; } public function log_shutdown() { $total_time = round((microtime(true) - $this->start_time) * 1000, 2); $peak_memory = memory_get_peak_usage(true); $this->log_message("SHUTDOWN - Завершение работы ({$total_time}ms, " . size_format($peak_memory) . ")", 'FINISH'); } private function get_caller_info($backtrace) { foreach ($backtrace as $trace) { if (isset($trace['file']) && !str_contains($trace['file'], 'wp-includes') && !str_contains($trace['file'], 'wp-admin')) { $file = basename($trace['file']); $line = $trace['line'] ?? 'unknown'; return "{$file}:{$line}"; } } return 'unknown'; } } // Инициализируем логгер только если включен дебаг //if (defined('WP_DEBUG') && WP_DEBUG) { RealtimePageLogger::get_instance(); //} // Функция для очистки лога add_action('wp_ajax_clear_realtime_log', 'clear_realtime_debug_log'); function clear_realtime_debug_log() { if (current_user_can('administrator')) { file_put_contents(WP_CONTENT_DIR . '/realtime-debug.log', ''); echo "Realtime log cleared!"; } wp_die(); }