-
-
Notifications
You must be signed in to change notification settings - Fork 1
Development Workflow
Jean-Marc Strauven edited this page Aug 6, 2025
·
2 revisions
Learn how to integrate Laravel ChronoTrace into your development workflow for debugging, testing, and quality assurance.
# Install ChronoTrace in development
composer require --dev grazulex/laravel-chronotrace
php artisan chronotrace:install
# Configure for development
CHRONOTRACE_ENABLED=true
CHRONOTRACE_MODE=always
CHRONOTRACE_RETENTION_DAYS=3
CHRONOTRACE_ASYNC_STORAGE=false # Sync for immediate debugging// Add to your IDE snippets for quick debugging
// VS Code snippet example
{
"chronotrace-debug": {
"prefix": "ctdebug",
"body": [
"// ChronoTrace debug point",
"\\Grazulex\\LaravelChronotrace\\Facades\\ChronoTrace::addEvent('debug', [",
" 'message' => '${1:Debug message}',",
" 'data' => ${2:\\$data},",
" 'file' => __FILE__,",
" 'line' => __LINE__",
"]);"
],
"description": "Add ChronoTrace debug event"
}
}# Start your development day
php artisan chronotrace:purge --days=1 # Clean yesterday's traces
php artisan chronotrace:diagnose # Check system health
# Enable full recording for development
CHRONOTRACE_MODE=always
CHRONOTRACE_CAPTURE_EVENTS=true# Create a new feature branch
git checkout -b feature/user-notifications
# Enable targeted recording for your feature
php artisan chronotrace:record --routes="notifications/*" --duration=8h// In your controller - add custom events for debugging
class NotificationController extends Controller
{
public function store(Request $request)
{
ChronoTrace::addEvent('notification_create_start', [
'user_id' => $request->user()->id,
'type' => $request->type,
]);
$notification = Notification::create($request->validated());
ChronoTrace::addEvent('notification_create_complete', [
'notification_id' => $notification->id,
'processing_time' => $this->getProcessingTime(),
]);
return response()->json($notification, 201);
}
}# Test the new endpoint
curl -X POST localhost:8000/api/notifications \
-H "Content-Type: application/json" \
-d '{"type":"email","message":"Test notification"}'
# Check the trace immediately
php artisan chronotrace:list --limit=1
php artisan chronotrace:replay {latest-trace-id}# Find slow requests in your feature
php artisan chronotrace:list --route="notifications*" --min-duration=1000
# Analyze bottlenecks
php artisan chronotrace:replay {slow-trace-id} --filter=database
php artisan chronotrace:replay {slow-trace-id} --filter=http// Before optimization (identified via ChronoTrace)
public function getUserNotifications($userId)
{
$user = User::find($userId);
$notifications = $user->notifications; // N+1 problem detected!
foreach ($notifications as $notification) {
$notification->sender; // Another N+1 detected!
}
return $notifications;
}
// After optimization
public function getUserNotifications($userId)
{
return User::with(['notifications.sender'])
->find($userId)
->notifications;
}# Test the optimized version
curl localhost:8000/api/users/123/notifications
# Compare performance
php artisan chronotrace:list --route="users/*/notifications" --limit=2
# Should show improved duration and fewer DB queries# Enable error-focused recording
CHRONOTRACE_MODE=record_on_error
# Reproduce the bug to capture error trace
curl -X POST localhost:8000/api/problematic-endpoint# Find the error trace
php artisan chronotrace:list --status=error --limit=1
# Deep dive into the error
php artisan chronotrace:replay {error-trace-id}
# Focus on specific aspects
php artisan chronotrace:replay {error-trace-id} --filter=database
php artisan chronotrace:replay {error-trace-id} --filter=http// Example fix based on trace analysis
public function processOrder(Request $request)
{
try {
// ChronoTrace showed this query was failing
$inventory = Inventory::lockForUpdate()
->where('product_id', $request->product_id)
->where('quantity', '>=', $request->quantity)
->first();
if (!$inventory) {
throw new InsufficientInventoryException();
}
// Process order...
} catch (Exception $e) {
ChronoTrace::addEvent('order_processing_error', [
'error' => $e->getMessage(),
'product_id' => $request->product_id,
'requested_quantity' => $request->quantity,
]);
throw $e;
}
}# Record HTTP-focused traces
php artisan chronotrace:record --duration=30m
# Test API integration
php artisan test --filter=ExternalApiTest
# Analyze API calls
php artisan chronotrace:list --filter=http
php artisan chronotrace:replay {trace-id} --filter=http// Add comprehensive API debugging
class PaymentGatewayService
{
public function processPayment($amount, $token)
{
ChronoTrace::addEvent('payment_start', [
'amount' => $amount,
'gateway' => 'stripe',
'attempt' => 1,
]);
try {
$response = Http::timeout(30)
->post('https://api.stripe.com/v1/charges', [
'amount' => $amount,
'source' => $token,
]);
ChronoTrace::addEvent('payment_response', [
'status' => $response->status(),
'duration' => $response->transferStats->getTransferTime(),
'success' => $response->successful(),
]);
return $response->json();
} catch (ConnectException $e) {
ChronoTrace::addEvent('payment_connection_failed', [
'error' => $e->getMessage(),
'timeout' => true,
]);
// Implement fallback or retry logic
throw new PaymentGatewayException('Payment service unavailable');
}
}
}# Export specific traces
php artisan chronotrace:replay {trace-id} --format=json > debug_trace.json
# Share via Slack/Teams
php artisan chronotrace:replay {trace-id} --format=markdown > trace_analysis.md// Create custom debug report command
class CreateDebugReport extends Command
{
protected $signature = 'debug:report {feature} {--traces=5}';
public function handle()
{
$feature = $this->argument('feature');
$traceCount = $this->option('traces');
// Get recent traces for the feature
$traces = $this->getFeatureTraces($feature, $traceCount);
// Generate markdown report
$report = $this->generateMarkdownReport($traces);
// Save to file
file_put_contents("debug_reports/{$feature}_" . date('Y-m-d') . ".md", $report);
$this->info("Debug report created for {$feature}");
}
}#!/bin/bash
# .git/hooks/pre-commit
# Run ChronoTrace tests before commit
php artisan chronotrace:test-internal --component=database,cache
# Check for performance regressions
php artisan test --group=performance
# Verify no debugging code left in
if grep -r "ChronoTrace::addEvent.*debug" app/; then
echo "Error: Debug ChronoTrace events found in code"
exit 1
fi## Performance Impact Checklist
- [ ] Tested with ChronoTrace recording enabled
- [ ] No N+1 queries introduced (verified with `--filter=database`)
- [ ] API calls under 2 seconds (verified with `--filter=http`)
- [ ] Memory usage under 50MB (verified with trace analysis)
- [ ] No debug events left in code
## ChronoTrace Analysis
<!-- Paste relevant trace analysis here -->// tests/Feature/NotificationFeatureTest.php
use Grazulex\LaravelChronotrace\Testing\ChronoTraceAssertions;
class NotificationFeatureTest extends TestCase
{
use ChronoTraceAssertions;
public function test_notification_creation_performance()
{
$this->enableChronoTrace();
$user = User::factory()->create();
$response = $this->actingAs($user)
->postJson('/api/notifications', [
'type' => 'email',
'message' => 'Test notification',
]);
$response->assertStatus(201);
// Assert performance requirements
$this->assertTraceDuration(lessThan: 500); // < 500ms
$this->assertDatabaseQueriesLessThan(5);
$this->assertNoNPlusOneQueries();
// Assert business logic
$trace = $this->getLastTrace();
$customEvents = $trace['events']['custom'] ?? [];
$this->assertCount(2, $customEvents); // start and complete events
$this->assertEquals('notification_create_start', $customEvents[0]['type']);
$this->assertEquals('notification_create_complete', $customEvents[1]['type']);
}
public function test_notification_list_caching()
{
$this->enableChronoTrace();
$user = User::factory()->create();
// First request - should cache
$this->actingAs($user)->getJson('/api/notifications');
$firstTrace = $this->getLastTrace();
// Second request - should hit cache
$this->actingAs($user)->getJson('/api/notifications');
$secondTrace = $this->getLastTrace();
// Assert caching worked
$this->assertCacheHitRate(greaterThan: 80);
$this->assertTrue($secondTrace['duration'] < $firstTrace['duration']);
}
}// tests/Performance/PerformanceRegressionTest.php
class PerformanceRegressionTest extends TestCase
{
use ChronoTraceAssertions;
/**
* @group performance
*/
public function test_api_endpoints_performance_baseline()
{
$this->enableChronoTrace();
$endpoints = [
['GET', '/api/users', 200, 300], // max 300ms
['POST', '/api/notifications', 201, 500], // max 500ms
['GET', '/api/dashboard', 200, 1000], // max 1s
];
foreach ($endpoints as [$method, $url, $expectedStatus, $maxDuration]) {
$response = $this->json($method, $url, $this->getTestData($method));
$response->assertStatus($expectedStatus);
$this->assertTraceDuration(lessThan: $maxDuration);
// Log performance for trending
$trace = $this->getLastTrace();
$this->logPerformanceMetric($url, $trace['duration'], $maxDuration);
}
}
}# .github/workflows/chronotrace-ci.yml
name: ChronoTrace CI
on: [push, pull_request]
jobs:
performance-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.3
extensions: redis
- name: Install dependencies
run: composer install
- name: Setup test environment
run: |
cp .env.ci .env
php artisan key:generate
php artisan migrate --seed
- name: Test ChronoTrace functionality
run: php artisan chronotrace:test-internal
- name: Run performance tests
run: php artisan test --group=performance
- name: Generate performance report
run: |
php artisan debug:report ci-build --traces=10
- name: Upload performance artifacts
uses: actions/upload-artifact@v2
with:
name: performance-report
path: debug_reports/// Create a simple dashboard for monitoring
class PerformanceDashboard extends Command
{
protected $signature = 'dashboard:performance';
public function handle()
{
$this->info('π ChronoTrace Performance Dashboard');
$this->line('');
// Recent performance metrics
$this->displayRecentMetrics();
// Top slow endpoints
$this->displaySlowEndpoints();
// Database performance
$this->displayDatabaseMetrics();
// Cache efficiency
$this->displayCacheMetrics();
}
private function displayRecentMetrics()
{
$traces = $this->getRecentTraces(100);
$avgDuration = $traces->avg('duration');
$p95Duration = $traces->percentile(95, 'duration');
$errorRate = $traces->where('status', '>=', 400)->count() / $traces->count() * 100;
$this->table(['Metric', 'Value'], [
['Average Response Time', round($avgDuration) . 'ms'],
['95th Percentile', round($p95Duration) . 'ms'],
['Error Rate', round($errorRate, 2) . '%'],
['Total Requests', $traces->count()],
]);
}
}// Monitor A/B test performance
class ABTestMonitoring
{
public function trackVariantPerformance($userId, $variant)
{
ChronoTrace::addEvent('ab_test_variant', [
'user_id' => $userId,
'variant' => $variant,
'test_name' => 'checkout_flow_v2',
]);
// Your A/B test logic here
}
public function analyzeABTestResults($testName)
{
// Query traces with A/B test events
$traces = ChronoTrace::searchTraces([
'custom_events.ab_test_variant.test_name' => $testName,
'created_at' => ['>=', now()->subWeek()],
]);
// Group by variant and analyze performance
$results = $traces->groupBy('events.custom.ab_test_variant.variant')
->map(function ($variantTraces) {
return [
'count' => $variantTraces->count(),
'avg_duration' => $variantTraces->avg('duration'),
'error_rate' => $variantTraces->where('status', '>=', 400)->count() / $variantTraces->count(),
];
});
return $results;
}
}# Load testing with ChronoTrace monitoring
# load-test.sh
# Start ChronoTrace recording
php artisan chronotrace:record --duration=10m --sample-rate=0.1 &
# Run load test
ab -n 1000 -c 10 http://localhost:8000/api/test-endpoint
# Analyze load test results
php artisan chronotrace:list --since="10 minutes ago" --min-duration=1000
php artisan debug:report load-test-$(date +%Y%m%d) --traces=50-
Start each feature with
chronotrace:record --routes="feature/*" - Add custom events at key business logic points
- Review traces before committing code
- Set performance budgets and test against them
- Clean up debug events before production
- Share trace IDs when reporting bugs
- Include performance analysis in code reviews
- Document performance expectations for each endpoint
- Use consistent event naming across the team
- Automate performance regression testing
- Test with production-like data volumes
- Verify PII scrubbing works correctly
- Set up appropriate retention policies
- Configure monitoring and alerting
- Plan for storage scaling
- Basic Usage - Learn ChronoTrace fundamentals
- Commands - Complete command reference
- Testing - Testing strategies
- Production Monitoring - Production deployment
Integrate ChronoTrace into your daily workflow! Use these patterns to make debugging more efficient and catch performance issues early in development.
- Getting Started - Install and configure ChronoTrace
- Examples - Real-world debugging scenarios
- Production Guide - Deploy safely in production
- Troubleshooting - Solve common issues
| Section | Page | Description |
|---|---|---|
| π Basics | Your First Trace | Step-by-step beginner guide |
| ποΈ Config | Recording Modes | Choose when to record traces |
| π‘οΈ Security | Security & PII | Protect sensitive data |
| π§ Tools | Commands | Complete command reference |
- π¬ GitHub Discussions - Community support
- π Report Issues - Bug reports & feature requests
- π§ Contact - Direct support
- π‘ Feature Requests - Suggest improvements
ChronoTrace helps Laravel developers debug applications faster with intelligent request tracing.
Made with β€οΈ by Grazulex β’ Documentation updated August 2024