Rhapsody Debug Toolbar

Rhapsody includes a powerful, non‑intrusive debug toolbar that appears at the bottom of every page when the application is in development mode (APP_ENV=development). It gives you real‑time insight into your application's performance, database queries, session data, middleware execution, dependency resolution, and more – all without cluttering your design.

💡 Tip: The toolbar is only injected into HTML responses. JSON/API responses are never altered.

Toolbar Overview

The toolbar is divided into clickable tabs, each displaying a specific category of debug information. It also includes a persistent header that shows key metrics at a glance.

Rhapsody v1.0 Request 200 Logs Database 12 Queries Session Cache Performance Environment Time: 231 ms 45%

Header Widgets

  • Request Status – HTTP status code of the response (green = 200, red = 4xx/5xx).
  • Execution Time – total time taken to process the request (in milliseconds).
  • Memory Peak – a visual bar showing peak memory usage relative to the memory_limit; colour‑coded: green (safe), amber (warning), red (critical).

Request Tab

The Request tab provides a comprehensive snapshot of the incoming HTTP request. It's your go‑to for debugging routing issues, inspecting headers, or reproducing a request via cURL.

Request Overview

At the top, you'll find essential request metadata:

  • Method – HTTP verb (GET, POST, PUT, DELETE, etc.)
  • Full URL – the complete URL of the request (including protocol, host, and query string)
  • Client IP – the IP address of the client making the request
  • Timestamp – exact time the request was received

Route Details

Displays information about the matched route:

  • Path – the URI path (after stripping APP_BASE_URL)
  • Controller – the class handling the request
  • Action – the method being called
  • Parameters – dynamic route parameters (e.g., user_id from /users/{user_id})
  • Middleware – the list of route‑specific middleware (shown as a chain, e.g., auth → guest)

If no route matched, the panel shows a helpful "No route matched" message – ideal for debugging 404s.

Request Headers

All HTTP headers sent by the client are displayed in a clean key‑value table. This includes standard headers like User-Agent, Accept, Content-Type, and any custom headers your application or client may send.

Query Parameters

If the request URL contains a query string (e.g., /users?page=2&limit=10), the parameters are displayed in a key‑value table. This is useful for debugging pagination, filters, or other GET parameters.

Request Body

For POST, PUT, PATCH, or DELETE requests, the raw request body is displayed:

  • If the body is valid JSON, it is automatically pretty‑printed for readability.
  • If the body is plain text (e.g., form data), it is shown as‑is.
  • If the request had no body, this section is omitted.

Copy cURL Command

At the bottom of the Request tab, there is a 📋 Copy cURL button. Clicking it generates a complete curl command that replicates the current request – including method, URL, headers, and body. This is invaluable for:

  • Reproducing bugs in a terminal
  • Sharing a request with a colleague for debugging
  • Testing API endpoints independently
Pro Tip: On Windows, use curl.exe instead of curl to avoid PowerShell's alias. The command generated in the toolbar will automatically use curl.exe on Windows.

Why use cURL instead of just viewing page source?

You might wonder: "I can already see the page source in my browser – why do I need a cURL command?" Here's why it's much more powerful:

🔁 Reproduce anywhere

Run the exact same request on any machine – your local terminal, a server, or a colleague's laptop. No browser, no cookies, no extensions.

✏️ Modify and test

Tweak headers, change parameters, or alter the request body to test different scenarios quickly. No need to navigate through forms or click around.

📦 See the full response

Page source only shows the HTML body. cURL shows everything – status code, headers, cookies, and timing details. Perfect for debugging APIs.

📤 Share with teammates

Instead of saying "click this button and fill out that form", you can share a one‑line command that reproduces the bug exactly.

⏱️ Measure performance

Add timing flags to measure DNS lookup, connection time, and total response time – metrics you can't get from page source.

🤖 Automate testing

Use the cURL command in CI/CD pipelines, load‑testing scripts, or monitoring tools to verify your endpoints automatically.

🧠 In a nutshell: View Page Source = quick visual inspection of the HTML structure.
cURL Command = a complete, reproducible snapshot of the entire HTTP transaction.

Logs Tab

Shows the last 50 lines of your PHP error log and Apache error log (or web server log). The log file paths are defined in config.php under the logging key.

Note: If a log file is not found or not readable, the toolbar will show a message indicating that.

Database Tab

Lists every SQL query executed during the request, along with:

  • SQL – the raw query string
  • Parameters – bound values (as JSON)
  • Execution Time – time taken (in milliseconds)
  • Caller – the file and line where the query was initiated

N+1 Query Detection

The toolbar automatically flags potential N+1 query patterns. This happens when the same query structure (after normalising literal values) is executed more than 3 times in a single request.

  • If detected, a warning box appears at the top of the Database tab.
  • Each flagged query is marked with a warning icon (⚠️) in the list.
  • See the Performance & Caching guide for strategies to fix N+1.

N+1 Queries Explained

N+1 queries occur when your code executes one query to fetch a list of records, and then another query for each record to fetch related data.

Simple analogy

Imagine you go to a library and ask:
"How many books do you have?" (1 query)
The librarian tells you there are 10 books.
Then you ask:
"What are the titles of each of the 10 books?"
... and you ask that 10 separate times (10 more queries).
That's 11 queries total — an N+1 problem.


Session Tab

Shows the contents of $_SESSION in a clean key‑value table. Nested arrays are rendered as indented lists for readability. Values are colour‑coded:

  • true / false – booleans
  • null – null values
  • Object – objects (class name shown)
  • Keys – array keys

This is invaluable for debugging authentication state, flash messages, and user‑specific data.


Cache Tab

Displays performance metrics for the framework's cache system (driven by Cache::remember() and Cache::get()).

  • Hits – number of successful cache lookups
  • Misses – number of cache misses (values not found)
  • Total Requests – hits + misses
  • Hit Ratio – percentage of requests that were hits
  • A progress bar visualises the ratio with colour coding:
    • Green – > 70% (healthy)
    • Yellow – 40‑70% (room for improvement)
    • Red – < 40% (cache may be underused or ineffective)

If your application is not using caching, the stats will remain zero – that's expected. See the Caching documentation to add cache to your code.


Performance Tab

This tab is powered by a React component (PerformancePanel) and provides a high‑level dashboard of your application's performance metrics, all in one place.

  • Execution Time – same as the header, with a progress bar scaled to 1000ms
  • Memory Usage – current memory peak (MB) with a bar scaled to 16MB
  • Database Queries – total query count, scaled to 100 queries
  • Cache Hit Ratio – the same cache ratio as the Cache tab
  • N+1 Detection – summary of any potential N+1 patterns, with a collapsible detail list
  • Route / Controller – shows the matched route (same as Request tab)

Environment Tab

This comprehensive tab gives you deep insight into your application's runtime environment, middleware pipeline, and dependency injection container. It is your go‑to for debugging bootstrapping issues, middleware misconfigurations, and circular dependencies.

Environment Variables

Displays all environment variables ($_ENV) in a sortable table. Sensitive values (passwords, secrets, API keys) are partially masked for your security. This is useful for verifying that your .env settings are correctly loaded.

Middleware Tracer

Shows every middleware that ran during the request, in the exact order they were executed:

  • Type – Global (runs on every request) or Route (assigned to specific routes)
  • Class – the middleware class name
  • Route – the route path (for route middleware)
  • Duration – execution time in milliseconds (colour‑coded: green < 20ms, yellow 20‑50ms, red > 50ms)
  • Total Middleware Time – sum of all middleware execution times

This is invaluable for pinpointing slow middleware that might be causing request latency, or for verifying that your middleware stack is correctly ordered.

Container Inspector

Visualises the service container's dependency resolution for the current request:

  • Service – the resolved class (or interface)
  • Duration – time taken to resolve (colour‑coded like middleware)
  • Called By – the class that requested this service (helps trace dependencies)
  • Status – ✅ Resolved (success) or ⚠️ Circular (if a circular dependency was detected)
  • Total Resolve Time – sum of all resolution times

If you see a ⚠️ Circular status, the toolbar will also show the circular chain (e.g., A → B → C → A), making it easy to fix. This is particularly useful for debugging complex dependency graphs in large applications.

Pro Tip: The Environment tab is perfect for diagnosing "silent" failures – when a page loads but behaves unexpectedly. Check the middleware order and container resolutions to catch misconfigurations quickly.

Enabling / Disabling the Toolbar

The toolbar is automatically injected when APP_ENV is set to development. To disable it in development (e.g., to test raw HTML output), you can temporarily comment out the toolbar injection in index.php (around line where Toolbar is instantiated).

In production (APP_ENV=production), the toolbar is never shown, regardless of the development setting. This is a security feature.


Extending the Toolbar

The toolbar is designed to be extensible. You can add your own panels by hooking into the Debug::end() method and injecting custom data into the $this->data array. The React components (PerformancePanel, MemoryProfiler) are also open to extension.

For advanced use, refer to the source code in vendor/arout/rhapsody-core/src/Debug.php and vendor/arout/rhapsody-core/src/Toolbar.php.


Happy debugging!

The toolbar is your best friend during development. Use it to catch performance bottlenecks, inefficient queries, middleware misconfigurations, circular dependencies, session anomalies, and request‑level issues before they reach production.