Skip to content

Commit 4a05081

Browse files
committed
feat: Add lightweight debug bar system for development
1 parent 9aa2d20 commit 4a05081

30 files changed

+1049
-26
lines changed

.env.example

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,8 @@ JWT_SECRET=your-secret-key-here
1313
JWT_EXPIRE=3600
1414

1515
CACHE_DRIVER=file
16-
LOG_LEVEL=debug
16+
LOG_LEVEL=debug
17+
18+
# Debug Bar Configuration
19+
DEBUGBAR_ENABLED=true
20+
DEBUGBAR_ALLOWED_IPS=127.0.0.1,::1

CHANGELOG.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
## [1.1.0] - 2025-10-21
6+
7+
### Added
8+
- **Debug Bar System** - Lightweight development debugging toolbar
9+
- Real-time performance monitoring (execution time, memory usage)
10+
- Database query tracking with timing information
11+
- Debug message logging with different severity levels
12+
- HTTP request information capture
13+
- Timer functionality for measuring code execution
14+
- Automatic PDO query interception and logging
15+
- Safe by default - only enabled via environment configuration
16+
- IP whitelist support for security
17+
- Minimal overhead when disabled
18+
19+
### Features
20+
- `CollectorInterface` - Base interface for debug collectors
21+
- `DebugBar` - Main singleton manager for debug functionality
22+
- Built-in collectors:
23+
- `TimerCollector` - Measures execution times
24+
- `MemoryCollector` - Tracks memory usage
25+
- `MessageCollector` - Logs debug messages
26+
- `QueryCollector` - Records database queries
27+
- `RequestCollector` - Captures HTTP request data
28+
- `DebugPDO` - PDO wrapper for automatic query tracking
29+
- Helper functions: `debug()`, `timer_start()`, `timer_stop()`
30+
- Responsive debug toolbar UI with tabbed interface
31+
- Dual output support: HTML toolbar for web pages, JSON headers for APIs
32+
33+
### Configuration
34+
- `DEBUGBAR_ENABLED` - Enable/disable debug bar
35+
- `DEBUGBAR_ALLOWED_IPS` - IP whitelist for security
36+
37+
### Fixed
38+
- PHP 8+ compatibility issues with PDO return types
39+
- `getallheaders()` function compatibility for CLI environments
40+
41+
### Security
42+
- Debug bar automatically disabled in production
43+
- IP-based access control
44+
- No sensitive data exposure in debug output

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Md Rasheduzzaman
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ A production-ready Raw PHP REST API Starter Kit with JWT authentication, user ma
2020
-**Docker Support** - Containerized deployment
2121
-**PHPUnit Testing** - Comprehensive test suite
2222
-**API Documentation** - Complete endpoint docs
23+
-**Debug Bar** - Development debugging toolbar with performance monitoring
2324

2425
## 📁 Project Structure
2526

@@ -29,6 +30,7 @@ A production-ready Raw PHP REST API Starter Kit with JWT authentication, user ma
2930
│ ├── controllers/ # Request handlers
3031
│ ├── core/ # Core framework classes
3132
│ ├── database/ # Migrations and seeders
33+
│ ├── debugbar/ # Debug bar system
3234
│ ├── exceptions/ # Exception handlers
3335
│ ├── helpers/ # Utility classes
3436
│ ├── middleware/ # Request middleware
@@ -58,6 +60,13 @@ cp .env.example .env
5860
# Edit .env with your database credentials
5961
```
6062

63+
**Debug Bar Configuration (Optional)**
64+
```bash
65+
# Enable debug bar for development
66+
DEBUGBAR_ENABLED=true
67+
DEBUGBAR_ALLOWED_IPS=127.0.0.1,::1
68+
```
69+
6170
### 3. Database Setup
6271
```bash
6372
# Option 1: Import the complete database schema
@@ -185,6 +194,65 @@ The HRMS includes the following tables:
185194
- CORS middleware
186195
- SQL injection protection (prepared statements)
187196

197+
## 🔧 Debug Bar
198+
199+
The built-in debug bar provides real-time development insights with minimal performance impact.
200+
201+
### Features
202+
- **Performance Monitoring** - Execution time and memory usage tracking
203+
- **Database Queries** - All SQL queries with timing information
204+
- **Debug Messages** - Categorized logging (info, warning, error)
205+
- **Request Data** - HTTP method, URI, headers, and parameters
206+
- **Custom Timers** - Measure specific code execution times
207+
208+
### Configuration
209+
210+
Add to your `.env` file:
211+
```bash
212+
# Enable debug bar (disabled by default)
213+
DEBUGBAR_ENABLED=true
214+
215+
# Optional: Restrict access by IP (comma-separated)
216+
DEBUGBAR_ALLOWED_IPS=127.0.0.1,::1,192.168.1.100
217+
```
218+
219+
### Usage
220+
221+
#### Debug Messages
222+
```php
223+
// Log debug messages with different levels
224+
debug('User login attempt', 'info');
225+
debug('Invalid credentials', 'warning');
226+
debug('Database connection failed', 'error');
227+
```
228+
229+
#### Performance Timing
230+
```php
231+
// Measure execution time
232+
timer_start('api_call');
233+
// ... your code ...
234+
timer_stop('api_call');
235+
```
236+
237+
#### Automatic Features
238+
- **Database Queries**: All PDO queries are automatically tracked
239+
- **Memory Usage**: Current and peak memory consumption
240+
- **Request Info**: HTTP method, URI, headers automatically captured
241+
242+
### Output Modes
243+
244+
**HTML Pages**: Debug toolbar appears at the bottom of the page
245+
**JSON APIs**: Debug data included in `X-Debugbar-Data` response header (Base64 encoded JSON)
246+
247+
### Security
248+
- Automatically disabled when `DEBUGBAR_ENABLED=false`
249+
- IP whitelist support for production-like environments
250+
- No sensitive data exposure (credentials are filtered)
251+
- Zero performance impact when disabled
252+
253+
### Test Debug Bar
254+
Visit `http://localhost:8000/welcome` to see the debug bar in action.
255+
188256
## 🧪 Testing
189257

190258
```bash

app/config/env.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,20 @@ public static function get($key, $default = null)
2727
{
2828
return self::$variables[$key] ?? $default;
2929
}
30+
31+
public static function getLogLevel()
32+
{
33+
return self::get('LOG_LEVEL', 'INFO');
34+
}
35+
36+
public static function isDebugBarEnabled(): bool
37+
{
38+
return self::get('DEBUGBAR_ENABLED', 'false') === 'true';
39+
}
40+
41+
public static function getDebugBarAllowedIps(): array
42+
{
43+
$ips = self::get('DEBUGBAR_ALLOWED_IPS', '');
44+
return $ips ? explode(',', $ips) : [];
45+
}
3046
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace App\Controllers;
4+
5+
use App\Core\Controller;
6+
use App\Core\Request;
7+
use App\Core\Response;
8+
use App\Helpers\Logger;
9+
10+
class ExampleController extends Controller
11+
{
12+
public function index(Request $request, Response $response)
13+
{
14+
Logger::info('ExampleController index method accessed.', ['user_id' => 123, 'ip_address' => $request->ip()]);
15+
return $response->json(['message' => 'Example index response']);
16+
}
17+
18+
public function show(Request $request, Response $response, $id)
19+
{
20+
Logger::warning('ExampleController show method accessed with ID.', ['id' => $id, 'user_id' => 123]);
21+
return $response->json(['message' => "Showing example with ID: {$id}"]);
22+
}
23+
24+
public function store(Request $request, Response $response)
25+
{
26+
$data = $request->json();
27+
if (empty($data['name'])) {
28+
Logger::error('Attempted to store example with missing name.', ['request_data' => $data]);
29+
return $response->json(['error' => 'Name is required'], 400);
30+
}
31+
Logger::info('New example stored successfully.', ['data' => $data]);
32+
return $response->json(['message' => 'Example stored', 'data' => $data], 201);
33+
}
34+
}

app/controllers/LeaveTypeController.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@ public function index()
1313
$perPage = $this->request->get('per_page', 10);
1414
$page = $this->request->get('page', 1);
1515
$leaveTypes = LeaveType::paginate($perPage, $page);
16-
return Response::json($leaveTypes);
16+
return Response::success('Leave Types retrieved successfully', $leaveTypes);
1717
}
1818

1919
public function show($id)
2020
{
2121
$leaveType = LeaveType::find($id);
2222
if (!$leaveType) {
23-
return Response::json(['error' => 'Leave Type not found'], 404);
23+
return Response::error('Leave Type not found', 404);
2424
}
25-
return Response::json($leaveType);
25+
return Response::success('Leave Type retrieved successfully', $leaveType);
2626
}
2727

2828
public function store()
@@ -34,16 +34,16 @@ public function store()
3434
$leaveType->max_days = $data['max_days'] ?? null;
3535

3636
if ($leaveType->save()) {
37-
return Response::json(['message' => 'Leave Type created successfully', 'leave_type' => $leaveType], 201);
37+
return Response::success('Leave Type created successfully', ['leave_type' => $leaveType], 201);
3838
}
39-
return Response::json(['error' => 'Failed to create leave type'], 500);
39+
return Response::error('Failed to create leave type', 500);
4040
}
4141

4242
public function update($id)
4343
{
4444
$leaveType = LeaveType::find($id);
4545
if (!$leaveType) {
46-
return Response::json(['error' => 'Leave Type not found'], 404);
46+
return Response::error('Leave Type not found', 404);
4747
}
4848

4949
$data = $this->request->json();
@@ -52,21 +52,21 @@ public function update($id)
5252
$leaveType->max_days = $data['max_days'] ?? $leaveType->max_days;
5353

5454
if ($leaveType->save()) {
55-
return Response::json(['message' => 'Leave Type updated successfully', 'leave_type' => $leaveType]);
55+
return Response::success('Leave Type updated successfully', ['leave_type' => $leaveType]);
5656
}
57-
return Response::json(['error' => 'Failed to update leave type'], 500);
57+
return Response::error('Failed to update leave type', 500);
5858
}
5959

6060
public function destroy($id)
6161
{
6262
$leaveType = LeaveType::find($id);
6363
if (!$leaveType) {
64-
return Response::json(['error' => 'Leave Type not found'], 404);
64+
return Response::error('Leave Type not found', 404);
6565
}
6666

6767
if ($leaveType->delete()) {
68-
return Response::json(['message' => 'Leave Type deleted successfully']);
68+
return Response::success('Leave Type deleted successfully');
6969
}
70-
return Response::json(['error' => 'Failed to delete leave type'], 500);
70+
return Response::error('Failed to delete leave type', 500);
7171
}
7272
}

0 commit comments

Comments
 (0)