Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 8, 2025

  • Understand the codebase structure and how profiling works
  • Design the wp profile queries command structure
  • Implement the core queries() method in Command.php
  • Add support for viewing all queries with execution time
  • Add --hook=<hook> parameter to filter queries for a specific hook
  • Add --callback=<callback> parameter to filter queries for a specific callback
  • Add formatting support (table, json, yaml, csv)
  • Add ordering support (--order, --orderby)
  • Add tests for the new command including hook/callback filtering
  • Enhance Logger to track query indices
  • Update documentation in README.md
  • Run code review and security checks
  • Improve first test to add custom plugin with database queries
  • Fix PHP warnings for non-numeric values in Formatter
  • Address code review feedback (callback filtering, query_indices reset, handle both params)
  • Fix test failures:
    • Added 'hook' property to loggers created when wrapping callbacks
    • Added additional validation in Formatter to check both value and totals are numeric
  • Implementation complete

Summary

Fixed two issues causing test failures:

  1. Hook filtering returning 0 results: When profiling a specific hook (e.g., --hook=init), the Profiler wraps callbacks but wasn't storing which hook they belonged to. Modified wrap_current_filter_callbacks() in Profiler.php to include the hook property in callback loggers, enabling proper filtering.

  2. PHP warning in Formatter: Added additional validation to check that both $value and $totals[$i] are numeric before performing addition, preventing warnings when non-numeric values slip through.

Original prompt

This section details on the original issue you should resolve

<issue_title>Introduce wp profile queries</issue_title>
<issue_description>It would be helpful to be able to see all queries and how much time they're taking.

Also make it possible to show actual queries for (a) a specific callback or (b) all queries within a specific hook</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI self-assigned this Nov 8, 2025
Copilot AI and others added 3 commits November 8, 2025 10:36
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
Copilot AI changed the title [WIP] Introduce wp profile queries to monitor query performance Introduce wp profile queries command Nov 8, 2025
Copilot AI requested a review from swissspidy November 8, 2025 10:42
@swissspidy swissspidy requested a review from Copilot November 8, 2025 14:23

This comment was marked as resolved.

swissspidy and others added 3 commits November 8, 2025 15:27
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
@swissspidy

This comment was marked as resolved.

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>

This comment was marked as resolved.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +601 to +608
foreach ( $logger->query_indices as $query_index ) {
if ( ! isset( $query_map[ $query_index ] ) ) {
$query_map[ $query_index ] = array(
'hook' => isset( $logger->hook ) ? $logger->hook : null,
'callback' => isset( $logger->callback ) ? $logger->callback : null,
);
}
}
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Potential issue with query map overwriting. When multiple loggers track the same query index (e.g., nested hooks), the check ! isset( $query_map[ $query_index ] ) at line 602 prevents overwriting. This means the first logger's hook/callback will be used, but in nested scenarios, this might not be the most specific or accurate mapping. Consider whether the first-logger-wins approach is the intended behavior, or if you need to track multiple hooks/callbacks per query.

Copilot uses AI. Check for mistakes.
Comment on lines 582 to 630
$loggers = $profiler->get_loggers();
foreach ( $loggers as $logger ) {
// Skip if filtering by callback and this isn't the right one
if ( $callback && isset( $logger->callback ) ) {
// Normalize callback for comparison
$normalized_callback = str_replace( array( '->', '::' ), '', (string) $logger->callback );
$normalized_filter = str_replace( array( '->', '::' ), '', $callback );
if ( false === stripos( $normalized_callback, $normalized_filter ) ) {
continue;
}
}

// Skip if filtering by hook and this isn't the right one
if ( $hook && isset( $logger->hook ) && $logger->hook !== $hook ) {
continue;
}

// Get the query indices for this logger
if ( isset( $logger->query_indices ) && ! empty( $logger->query_indices ) ) {
foreach ( $logger->query_indices as $query_index ) {
if ( ! isset( $query_map[ $query_index ] ) ) {
$query_map[ $query_index ] = array(
'hook' => isset( $logger->hook ) ? $logger->hook : null,
'callback' => isset( $logger->callback ) ? $logger->callback : null,
);
}
}
}
}
}

// Get all queries
$queries = array();
if ( ! empty( $wpdb->queries ) ) {
foreach ( $wpdb->queries as $index => $query_data ) {
// If filtering by hook/callback, only include queries in the map
if ( ( $hook || $callback ) && ! isset( $query_map[ $index ] ) ) {
continue;
}

$query_obj = new QueryLogger(
$query_data[0], // SQL query
$query_data[1], // Time
isset( $query_data[2] ) ? $query_data[2] : '', // Caller
isset( $query_map[ $index ]['hook'] ) ? $query_map[ $index ]['hook'] : null,
isset( $query_map[ $index ]['callback'] ) ? $query_map[ $index ]['callback'] : null
);
$queries[] = $query_obj;
}
Copy link

Copilot AI Nov 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Performance consideration: The nested loop structure (lines 583-610 and 616-630) could be inefficient for sites with many queries and hooks. For N loggers and M queries, this is O(N*Q + M) where Q is queries per logger. If $wpdb->queries contains thousands of entries, this might be slow. Consider optimizing by building the query map in a single pass if performance becomes an issue, though the current implementation is clear and correct for typical use cases.

Copilot uses AI. Check for mistakes.
…indices

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@swissspidy

This comment was marked as resolved.

… validation

Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>

This comment was marked as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Introduce wp profile queries

2 participants