📦 Marketplace⭐ GitHub
Toolingv1.0

DevTools

PHP 8.4+ MIT License Tests Coverage PHP 8.4 Hooks

Enterprise-grade debugging, profiling, and diagnostics for MonkeysLegion v2.

Inspect every request, route, query, cache operation, event, and exception — with a self-contained debug toolbar, intelligent anomaly detection, and zero runtime overhead when disabled.

Laravel has Telescope.  Symfony has the Web Profiler.
MonkeysLegion has DevTools — and it's smarter than both.

✨ Key Features

FeatureDescription
🚀 Zero OverheadEarly-return when disabled — no reflection, no magic, no cost
🪝 PHP 8.4 Property Hooks26 computed properties replace traditional getters across the codebase
🔍 N+1 DetectionAutomatic duplicate query grouping with configurable thresholds
Cache IntelligenceHit/miss ratios, hot key ranking, per-store breakdown
📡 Event Storm DetectionTimeline visualization with storm alerts and slow listener tracking
🎯 Deterministic SamplingHash-based consistency for distributed trace coherence
🔒 Redaction PipelineRecursive key-based masking — secrets never leak, even in dev
🛡️ Request Fingerprintingxxh3-based grouping for automatic request clustering
🖥️ Debug ToolbarSelf-contained Tokyo Night UI — no external assets required
🧪 184 Tests572 assertions across 22 test files — 90%+ coverage

📦 Installation

composer require monkeyscloud/monkeyslegion-devtools --dev

For production diagnostics (sampling + redacted output):

composer require monkeyscloud/monkeyslegion-devtools

Requirements

  • PHP 8.4+ (property hooks, asymmetric visibility)
  • PSR-7 HTTP Message (psr/http-message ^2.0)
  • PSR-15 Middleware (psr/http-server-middleware ^1.0)

🚀 Quick Start

1. Boot & Register Middleware

use MonkeysLegion\DevTools\DevToolsServiceProvider;

$devtools = new DevToolsServiceProvider();
$profiler = $devtools->boot([
    'enabled'     => true,
    'environment' => 'local',
    'sample_rate' => 1.0,
    'storage'     => ['driver' => 'file', 'path' => 'var/devtools/profiles'],
    'collectors'  => [
        'request'    => true,
        'route'      => true,
        'middleware'  => true,
        'query'      => true,
        'cache'      => true,
        'event'      => true,
        'exception'  => true,
    ],
    'toolbar' => ['enabled' => true],
]);

// Add to your PSR-15 pipeline
$middleware = $devtools->createMiddleware();

2. Record Intelligence Data

// Query profiling — N+1 is detected automatically
$queryCollector = $profiler->getCollector('query');
$queryCollector->recordQuery('SELECT * FROM users WHERE id = ?', durationMs: 2.3, connection: 'mysql');

// Cache tracking — hot keys are ranked automatically
$cacheCollector = $profiler->getCollector('cache');
$cacheCollector->recordOperation('redis', 'user:42', 'get', hit: true, durationMs: 0.4);

// Event timeline — storms are flagged automatically
$eventCollector = $profiler->getCollector('event');
$eventCollector->recordDispatch('App\Event\OrderPlaced', [
    ['name' => 'SendConfirmation', 'duration_ms' => 45.2],
    ['name' => 'UpdateInventory', 'duration_ms' => 12.1],
]);

3. Inspect via CLI

# System status
php ml devtools:status

# List recent profiled requests (color-coded by status)
php ml devtools:requests --limit=20

# Inspect the latest request in detail
php ml devtools:request latest

# Inspect by partial ID
php ml devtools:request c461

# Export a sanitized profile for sharing
php ml devtools:export latest --output=profile.json

# Clear all stored profiles
php ml devtools:clear

4. Debug Toolbar

When toolbar.enabled is true, the toolbar auto-injects into HTML responses:

  • Toggle: Click the 🐒 bar or press Ctrl+Shift+D
  • 5 Panels: Overview, Queries, Cache, Events, Exceptions
  • Severity Badges: Green / Yellow / Red per-panel status at a glance
  • Self-Contained: Zero external CSS/JS — embedded Tokyo Night theme

The toolbar only injects into text/html responses and respects a configurable size limit.


⚙️ Configuration

Create config/devtools.mlc:

devtools {
    enabled     = ${DEVTOOLS_ENABLED:true}
    environment = ${APP_ENV:local}
    sample_rate = ${DEVTOOLS_SAMPLE_RATE:1.0}

    storage {
        driver         = "file"
        path           = "var/devtools/profiles"
        retention_days = 7
        max_profiles   = 1000
    }

    collectors {
        request    = true
        route      = true
        middleware = true
        query      = true
        cache      = true
        event      = true
        exception  = true
    }

    redaction {
        enabled = true
        keys    = ["password", "token", "secret", "api_key", "authorization", "cookie"]
    }

    thresholds {
        slow_request_ms  = 200
        slow_query_ms    = 100
        n_plus_one_count = 5
    }

    toolbar {
        enabled        = true
        max_payload_kb = 256
    }

    production {
        sample_rate = 0.01
    }
}

🔬 Collectors

Built-in Collectors (7)

#CollectorIconPriorityKey Features
1Request🌐1000Method, URI, headers, IP hashing, fingerprint, timing, memory
2Middleware🔗950Per-middleware timing, memory delta, bottleneck detection
3Route🔀900Pattern, controller, params, middleware stack, OpenAPI hints
4Query🗄️800SQL timing, N+1 detection, duplicate grouping, source tracing
5Cache700Hit/miss ratio, hot key ranking, per-store breakdown
6Event📡600Timeline, storm detection, slow listeners, failed tracking
7Exception💥100Class, message, trace, chain traversal, xxh3 fingerprint

Intelligence Features

N+1 Query Detection

🔴 N+1 DETECTED: SELECT * FROM comments WHERE post_id = ? (×47 executions)
   Source: App\Repository\CommentRepository::findByPost() at line 42

The QueryCollector automatically fingerprints SQL by normalizing literals and compares execution counts against the configurable threshold.

Cache Hot Key Analysis

🔥 Hot Keys:
   user:session:abc123  (×84 accesses)
   config:app           (×31 accesses)
   route:cache          (×22 accesses)

Event Storm Detection

🌪️ STORM: App\Event\CacheInvalidated dispatched 142 times in this request

Custom Collectors

Implement CollectorInterface to add your own:

use MonkeysLegion\DevTools\Contract\CollectorInterface;
use MonkeysLegion\DevTools\Profiler\ProfileContext;

final class MyCollector implements CollectorInterface
{
    public function name(): string { return 'custom'; }
    public function label(): string { return 'Custom'; }
    public function icon(): string { return '🔧'; }
    public function priority(): int { return 500; }
    public function isEnabled(): bool { return true; }

    public function start(ProfileContext $context): void { /* setup */ }
    public function stop(ProfileContext $context): void { /* teardown */ }
    public function collect(ProfileContext $context): array { return [...]; }
}

$profiler->addCollector(new MyCollector());

🏷️ Attributes

use MonkeysLegion\DevTools\Attribute\{Profile, IgnoreProfile, Redact};

// Force profiling on a specific route with a label
#[Profile(name: 'checkout.process', includePayload: true)]
public function processCheckout(): Response { }

// Exclude high-frequency endpoints from profiling
#[IgnoreProfile(reason: 'health check')]
public function healthCheck(): Response { }

// Mark sensitive constructor parameters
public function __construct(
    #[Redact] private readonly string $apiSecret,
    #[Redact(replacement: '***')] private readonly string $dbPassword,
) {}

🪝 PHP 8.4 Property Hooks

DevTools leverages 26 PHP 8.4 property hooks — replacing traditional getters with declarative computed properties. This is a first for PHP frameworks.

// Profile model — zero getters, all computed
$profile->durationMs           // float: endedAt - startedAt
$profile->durationFormatted    // "42.7ms" | "1.23s" | "850μs"
$profile->isError              // statusCode >= 400
$profile->isSlow               // durationMs > threshold
$profile->statusBadge          // 🟢 🔵 🟠 🔴 ⚪
$profile->memoryPeakFormatted  // "12.4 MB"
$profile->memoryDelta          // bytes used during request
$profile->createdAtFormatted   // "2026-04-27 03:42:53.087"

// Profiler engine — live state hooks
$profiler->isActive            // currently profiling?
$profiler->collectorCount      // number of registered collectors
$profiler->collectorNames      // ['request', 'query', 'cache', ...]

// QueryCollector — computed analytics
$collector->queryCount         // total queries recorded
$collector->totalDurationMs    // sum of all query times
$collector->duplicateCount     // grouped duplicate queries
$collector->hasNPlusOne        // automatic N+1 flag
$collector->slowestQueryMs     // max single query time

// CacheCollector — computed metrics
$collector->hitRatio           // hits / total (float)
$collector->hitRatioFormatted  // "85.7%"
$collector->operationCount     // total operations tracked

// EventCollector — computed state
$collector->hasStorm           // event storm detected?
$collector->failedListenerCount // listeners that threw
$collector->totalListenerMs    // aggregate listener time

// ServiceProvider — boot state
$provider->booted              // has boot() been called?
$provider->profiler            // resolved Profiler instance
$provider->toolbar             // resolved ToolbarRenderer

Asymmetric Visibility

All mutable state uses private(set) — the profiler's internal state is read-only for external consumers:

public private(set) string $id;
public private(set) bool $booted = false;
public private(set) ?Profiler $profiler = null;

🗄️ Storage Drivers

DriverUse CasePersistence
FileProfileStorageLocal development — JSON files with index✅ Disk
MemoryProfileStorageTesting & benchmarks❌ Request-scoped
NullProfileStorageDisabled / CI environments❌ No-op

File storage features:

  • JSON format — human-readable, diffable, grep-friendly
  • Index file — fast listing without deserializing all profiles
  • Retention pruning — automatic cleanup on write (no cron needed)
  • Query filtering — method, URI, status, duration, environment, time range

🖥️ Debug Toolbar Panels

Overview Panel

Request summary, performance alerts (slow/error), and collector badge aggregation.

Query Panel

SQL listing with per-query timing, duplicate warnings (🟡), and N+1 alerts (🔴). Source file tracing for each query.

Cache Panel

Hit/miss ratio gauges, per-store breakdown table, and 🔥 hot key ranking.

Event Panel

Chronological timeline with relative timestamps, storm warnings (🌪️), and failed listener tracking.

Exception Panel

Error display with class highlighting, sanitized stack traces, and previous exception chain traversal.

Custom Panels

Extend AbstractPanel to add your own:

use MonkeysLegion\DevTools\Toolbar\AbstractPanel;
use MonkeysLegion\DevTools\Profiler\Profile;

final class MyPanel extends AbstractPanel
{
    public function id(): string { return 'custom'; }
    public function label(): string { return 'Custom'; }
    public function icon(): string { return '🔧'; }
    public function priority(): int { return 400; }

    public function badge(Profile $profile): string { return '3 items'; }
    public function badgeSeverity(Profile $profile): string { return 'ok'; }

    public function render(Profile $profile): string
    {
        return $this->section('Data', $this->renderTable([
            'Key' => 'Value',
        ]));
    }
}

🏗️ Architecture

src/
├── Attribute/               # #[Profile], #[IgnoreProfile], #[Redact]
├── Collector/               # 7 intelligence collectors
│   ├── CacheCollector.php       # Hit/miss, hot keys, per-store
│   ├── EventCollector.php       # Timeline, storms, slow listeners
│   ├── ExceptionCollector.php   # Traces, chains, fingerprinting
│   ├── MiddlewareCollector.php  # Per-middleware timing, bottlenecks
│   ├── QueryCollector.php       # N+1, duplicates, SQL fingerprinting
│   ├── RequestCollector.php     # Headers, IP hash, fingerprint
│   └── RouteCollector.php       # Pattern, controller, OpenAPI
├── Command/                 # 5 CLI commands (devtools:*)
├── Contract/                # Stable interfaces
├── Exception/               # Package exceptions
├── Middleware/               # PSR-15 DevToolsMiddleware
├── Profiler/                # Core engine
│   ├── Profile.php              # 10 property hooks
│   ├── ProfileContext.php       # Request lifecycle context
│   └── Profiler.php             # Orchestrator with 3 hooks
├── Redaction/               # Key-based recursive masking
├── Sampler/                 # Rate-based + deterministic sampling
├── Storage/                 # File, Memory, Null drivers
├── Toolbar/                 # Self-contained debug toolbar
│   ├── Panel/                   # 5 built-in panels
│   ├── AbstractPanel.php        # Rendering helpers
│   ├── PanelInterface.php       # Panel contract
│   ├── ToolbarInjector.php      # HTML response injection
│   └── ToolbarRenderer.php      # Self-contained HTML/CSS/JS
└── DevToolsServiceProvider.php  # Config-driven bootstrap

40 source files · 5,099 lines · 22 test files · 184 tests · 572 assertions


🆚 Competitive Comparison

FeatureSymfony ProfilerLaravel TelescopeML DevTools
PHP Version8.2+8.3+8.4+
Property Hooks0026
N+1 Detection✅ Automatic
Event Storm Detection
Cache Hot Key Analysis
Deterministic Sampling✅ Hash-based
Request Fingerprinting✅ xxh3
Priority Collectors✅ With wrap
Partial Value Redaction
Self-Contained Toolbar❌ Requires Webpack❌ Requires Tailwind✅ Embedded
Zero-Overhead Disabled⚠️ Partial✅ Full
Asymmetric Visibility✅ private(set)
MLC Config Format✅ Native

🧪 Testing

# Run all tests
composer test

# With testdox output
./vendor/bin/phpunit --testdox

# Static analysis
composer analyse

Test Suite Coverage

AreaTest FilesTestsAssertions
Collectors (7)762178
Profiler Core328102
Storage (3)32872
Toolbar & Panels338108
Service Provider11234
Middleware1412
Attributes1918
Exceptions136
Redaction11024
Sampler1618
Total22184572

🗺️ Roadmap

PhaseFocusStatus
0Contracts & Skeleton✅ Complete
1MVP Profiler & CLI✅ Complete
2Debug Toolbar & Local DX✅ Complete
3Query, Cache & Event Intelligence✅ Complete
4Container, Entity & Config Inspectors🔜 Next
5OpenAPI, Security & Validation Reports🔜 Planned
6Production Diagnostics & APM🔜 Planned
7MonkeysCloud SaaS Integration🔜 Planned

🤝 Contributing

  1. Fork & clone the repository
  2. Install dependencies: composer install
  3. Run the test suite: composer test
  4. Run static analysis: composer analyse
  5. Submit a PR against main

Please ensure all new collectors include corresponding unit tests and property hooks where applicable.


📄 License

MIT — © 2026 MonkeysCloud Team

Built with 🐒 by MonkeysCloud