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.
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.
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_idfrom/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
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.
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.
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.
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.
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.