# LiveComponents DevTools & Debugging Guide
Umfassender Leitfaden fΓΌr Debugging und Development Tools fΓΌr LiveComponents.
## Table of Contents
1. [Debug Mode](#debug-mode)
2. [Component State Inspection](#component-state-inspection)
3. [Request/Response Debugging](#requestresponse-debugging)
4. [Performance Profiling](#performance-profiling)
5. [Common Debugging Scenarios](#common-debugging-scenarios)
6. [Browser DevTools Integration](#browser-devtools-integration)
7. [Server-Side Logging](#server-side-logging)
8. [Testing & Development Helpers](#testing--development-helpers)
9. [Troubleshooting Workflows](#troubleshooting-workflows)
10. [Production Debugging](#production-debugging)
---
## Debug Mode
### Enabling Debug Mode
```php
use App\Framework\LiveComponents\Config\LiveComponentsConfig;
// In your configuration (e.g., config/livecomponents.php)
return new LiveComponentsConfig(
debug: true, // Enable debug mode
enableDevTools: true, // Enable DevTools helpers
logLevel: 'debug' // Verbose logging
);
```
### Debug Mode Features
**Automatic Features When Enabled:**
1. **Verbose Logging**: All component lifecycle events logged
2. **State Snapshots**: Before/after state changes captured
3. **Performance Metrics**: Render times, action execution times
4. **Error Context**: Enhanced error messages with full state dump
5. **Request/Response Logging**: All AJAX requests/responses logged
### Environment-Based Configuration
```php
// config/livecomponents.php
use App\Framework\Core\Environment;
use App\Framework\Config\EnvKey;
return new LiveComponentsConfig(
debug: $container->get(Environment::class)->get(EnvKey::APP_ENV) === 'development',
enableDevTools: $container->get(Environment::class)->get(EnvKey::APP_ENV) !== 'production',
logLevel: match ($container->get(Environment::class)->get(EnvKey::APP_ENV)) {
'production' => 'error',
'staging' => 'warning',
'development' => 'debug',
default => 'info'
}
);
```
---
## Component State Inspection
### Server-Side State Inspection
```php
use App\Framework\LiveComponents\Debug\StateInspector;
final readonly class ShoppingCartComponent implements LiveComponentContract
{
public function __construct(
private StateInspector $stateInspector // Injected when debug=true
) {}
#[Action]
public function addItem(CartItem $item): ShoppingCartState
{
// Capture state before action
$this->stateInspector->captureSnapshot('before_add_item', $this->state);
$newState = $this->state->addItem($item);
// Capture state after action
$this->stateInspector->captureSnapshot('after_add_item', $newState);
// Analyze state diff
$diff = $this->stateInspector->diff($this->state, $newState);
$this->stateInspector->log('State changed', [
'action' => 'addItem',
'changes' => $diff,
'item_count_before' => count($this->state->items),
'item_count_after' => count($newState->items)
]);
return $newState;
}
}
```
### Client-Side State Inspection
```javascript
// Access component state from browser console
const component = window.LiveComponents.get('shopping-cart:main');
// Current state
console.log('Current State:', component.state);
// State history (when debug=true)
console.log('State History:', component._debugStateHistory);
// Last action result
console.log('Last Action:', component._lastAction);
// Component metadata
console.log('Component Info:', {
id: component.id,
name: component.name,
version: component.version,
renderCount: component._renderCount,
actionCount: component._actionCount
});
```
### State Snapshots
```php
// Automatic snapshots during development
final readonly class StateSnapshot
{
public function __construct(
public string $label,
public ComponentData $state,
public float $timestamp,
public ?string $triggeredBy = null, // Action name or event
public ?array $metadata = null
) {}
}
// Usage
$inspector->captureSnapshot('cart_loaded', $this->state, metadata: [
'user_id' => $userId,
'session_id' => $sessionId,
'item_count' => count($this->state->items)
]);
// Retrieve snapshots
$snapshots = $inspector->getSnapshots($componentId);
// Compare snapshots
$diff = $inspector->compareSnapshots($snapshot1, $snapshot2);
```
---
## Request/Response Debugging
### Server-Side Request Logging
```php
use App\Framework\LiveComponents\Debug\RequestLogger;
final readonly class LiveComponentsRequestLogger
{
public function logRequest(
string $componentId,
string $action,
array $parameters,
ComponentData $stateBefore,
ComponentData $stateAfter,
float $executionTime
): void {
$this->logger->debug('LiveComponent Action', [
'component_id' => $componentId,
'action' => $action,
'parameters' => $parameters,
'execution_time_ms' => round($executionTime * 1000, 2),
'state_diff' => $this->calculateDiff($stateBefore, $stateAfter),
'timestamp' => microtime(true)
]);
}
}
```
### Client-Side Network Debugging
```javascript
// Enable detailed network logging
window.LiveComponents.setDebug(true);
// Network request interceptor (when debug=true)
window.LiveComponents.onRequest((request) => {
console.group(`π€ LiveComponent Request: ${request.action}`);
console.log('Component:', request.componentId);
console.log('Action:', request.action);
console.log('Parameters:', request.parameters);
console.log('State Hash:', request.stateHash);
console.groupEnd();
});
window.LiveComponents.onResponse((response) => {
console.group(`π₯ LiveComponent Response: ${response.action}`);
console.log('Duration:', `${response.duration}ms`);
console.log('State Updated:', response.stateChanged);
console.log('Fragments:', response.fragments?.length || 0);
console.log('Errors:', response.errors || 'None');
console.groupEnd();
});
window.LiveComponents.onError((error) => {
console.group(`β LiveComponent Error: ${error.action}`);
console.error('Message:', error.message);
console.error('Component:', error.componentId);
console.error('Stack:', error.stack);
console.groupEnd();
});
```
### Browser DevTools Network Panel
**Request Inspection:**
```
POST /livecomponent/action
Headers:
X-LiveComponent: true
X-Component-Id: shopping-cart:main
X-Action: addItem
X-State-Hash: a1b2c3d4e5f6
Request Payload:
{
"item": {
"id": "prod-123",
"name": "Product Name",
"price": 2999,
"quantity": 1
}
}
Response:
{
"success": true,
"stateHash": "f6e5d4c3b2a1",
"fragments": [
{
"selector": "#cart-items",
"html": "
...
"
},
{
"selector": "#cart-total",
"html": "β¬29.99"
}
],
"meta": {
"executionTime": 23.45,
"cacheHit": false,
"fragmentCount": 2
}
}
```
---
## Performance Profiling
### Server-Side Performance Metrics
```php
use App\Framework\LiveComponents\Performance\ComponentProfiler;
final readonly class PerformanceProfiler
{
public function profileAction(
string $componentId,
string $action,
callable $actionHandler
): ProfilingResult {
$startTime = microtime(true);
$startMemory = memory_get_usage(true);
// Execute action
$result = $actionHandler();
$endTime = microtime(true);
$endMemory = memory_get_usage(true);
return new ProfilingResult(
componentId: $componentId,
action: $action,
executionTime: Duration::fromSeconds($endTime - $startTime),
memoryUsed: $endMemory - $startMemory,
peakMemory: memory_get_peak_usage(true),
result: $result
);
}
}
// Usage in component
#[Action]
public function processPayment(PaymentRequest $request): ComponentData
{
return $this->profiler->profileAction(
$this->id->toString(),
'processPayment',
fn() => $this->executePayment($request)
)->result;
}
```
### Component Lifecycle Profiling
```php
final readonly class LifecycleProfiler
{
public function profileRender(LiveComponentContract $component): RenderProfile
{
$metrics = [
'template_load' => $this->measureTemplateLoad($component),
'state_serialization' => $this->measureStateSerialization($component),
'html_generation' => $this->measureHtmlGeneration($component),
'dom_manipulation' => $this->measureDomManipulation($component)
];
return new RenderProfile(
componentId: $component->id,
totalTime: array_sum($metrics),
breakdown: $metrics,
cacheHit: $this->wasCached($component)
);
}
}
```
### Client-Side Performance Metrics
```javascript
// Performance API integration
const performanceObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.name.startsWith('livecomponent:')) {
console.log('Performance Entry:', {
name: entry.name,
duration: `${entry.duration.toFixed(2)}ms`,
startTime: entry.startTime,
type: entry.entryType
});
}
}
});
performanceObserver.observe({ entryTypes: ['measure'] });
// Measure action execution
performance.mark('livecomponent:action:start');
await component.call('addItem', { item });
performance.mark('livecomponent:action:end');
performance.measure(
'livecomponent:action:addItem',
'livecomponent:action:start',
'livecomponent:action:end'
);
```
### Render Performance Tracking
```javascript
// Track rendering performance
class RenderPerformanceTracker {
trackRender(componentId, metrics) {
const entry = {
componentId,
timestamp: Date.now(),
domPatchTime: metrics.domPatchTime,
fragmentCount: metrics.fragmentCount,
bytesReceived: metrics.bytesReceived,
cacheHit: metrics.cacheHit
};
// Store in IndexedDB for analysis
this.storeMetric(entry);
// Warn on slow renders
if (metrics.domPatchTime > 100) {
console.warn(`Slow render detected: ${componentId}`, metrics);
}
}
getAverageRenderTime(componentId) {
const entries = this.getMetrics(componentId);
return entries.reduce((sum, e) => sum + e.domPatchTime, 0) / entries.length;
}
}
```
---
## Common Debugging Scenarios
### Scenario 1: Action Not Triggering
**Symptoms:** Button click doesn't trigger action
**Debug Steps:**
```javascript
// 1. Check if component is registered
const component = window.LiveComponents.get('shopping-cart:main');
console.log('Component exists:', !!component);
// 2. Check action attribute
const button = document.querySelector('[data-action="addItem"]');
console.log('Action attribute:', button?.dataset.action);
console.log('Component ID attribute:', button?.dataset.componentId);
// 3. Check event listeners
console.log('Event listeners:', getEventListeners(button));
// 4. Enable verbose logging
window.LiveComponents.setDebug(true);
// 5. Try manual action call
component.call('addItem', { item: testItem })
.then(result => console.log('Manual call success:', result))
.catch(error => console.error('Manual call failed:', error));
```
**Common Fixes:**
- Missing `data-component-id` attribute
- Incorrect action name (case-sensitive)
- Component not initialized (check initialization order)
- JavaScript errors preventing event binding
### Scenario 2: State Not Updating
**Symptoms:** Server returns success but UI doesn't update
**Debug Steps:**
```php
// Server-side: Verify state change
#[Action]
public function addItem(CartItem $item): ShoppingCartState
{
$oldState = $this->state;
$newState = $this->state->addItem($item);
// Debug logging
error_log("Old item count: " . count($oldState->items));
error_log("New item count: " . count($newState->items));
error_log("State changed: " . ($oldState !== $newState ? 'yes' : 'no'));
return $newState;
}
```
```javascript
// Client-side: Track state updates
window.LiveComponents.onStateChange((event) => {
console.log('State changed:', {
componentId: event.componentId,
oldHash: event.oldHash,
newHash: event.newHash,
changed: event.oldHash !== event.newHash
});
});
```
**Common Fixes:**
- State object not immutable (modifying instead of returning new instance)
- Missing fragments in response
- DomPatcher not applying changes (check selectors)
- Cache preventing updates (clear cache)
### Scenario 3: Memory Leaks
**Symptoms:** Browser memory grows over time
**Debug Steps:**
```javascript
// Heap snapshot comparison
// 1. Take baseline snapshot
console.log('Taking baseline snapshot...');
// Use Chrome DevTools > Memory > Take snapshot
// 2. Perform actions
for (let i = 0; i < 100; i++) {
await component.call('addItem', { item: generateTestItem(i) });
}
// 3. Take second snapshot
console.log('Taking second snapshot...');
// Compare snapshots in DevTools
// Check component cleanup
window.addEventListener('beforeunload', () => {
console.log('Active components:', window.LiveComponents.getAll());
console.log('Event listeners:', window.LiveComponents._eventListeners.size);
});
```
**Common Fixes:**
- Event listeners not cleaned up on component destroy
- DOM references held in closures
- Polling not stopped on unmount
- Large state objects not garbage collected
### Scenario 4: CSRF Token Mismatch
**Symptoms:** 403 Forbidden on action calls
**Debug Steps:**
```javascript
// Check CSRF token presence
const form = document.querySelector('form');
const csrfToken = form.querySelector('[name="_csrf_token"]')?.value;
console.log('CSRF Token in form:', csrfToken);
// Check request headers
window.LiveComponents.onRequest((request) => {
console.log('CSRF Token in request:', request.headers['X-CSRF-Token']);
});
// Check session token
fetch('/api/csrf-token')
.then(r => r.json())
.then(data => console.log('Current session CSRF:', data.token));
```
**Common Fixes:**
- Token not included in request (check middleware)
- Token expired (implement rotation)
- Session cleared (re-authenticate)
- Token not matching session (clear cookies and refresh)
### Scenario 5: Rate Limiting Issues
**Symptoms:** Actions suddenly fail with 429 Too Many Requests
**Debug Steps:**
```javascript
// Track rate limit headers
window.LiveComponents.onResponse((response) => {
if (response.status === 429) {
console.error('Rate Limited:', {
retryAfter: response.headers['Retry-After'],
limit: response.headers['X-RateLimit-Limit'],
remaining: response.headers['X-RateLimit-Remaining'],
reset: response.headers['X-RateLimit-Reset']
});
}
});
// Monitor action frequency
let actionCount = 0;
let startTime = Date.now();
window.LiveComponents.onRequest(() => {
actionCount++;
const elapsed = (Date.now() - startTime) / 1000;
const rate = actionCount / elapsed;
console.log(`Action rate: ${rate.toFixed(2)} req/sec`);
if (rate > 5) {
console.warn('High action rate detected - may trigger rate limiting');
}
});
```
**Common Fixes:**
- Implement debouncing for user actions
- Increase rate limits for legitimate use cases
- Add exponential backoff on 429 responses
- Batch multiple actions into single request
---
## Browser DevTools Integration
### Console Helpers
```javascript
// Global debug helpers (available in console)
// Get component by ID
lc('shopping-cart:main') // Shorthand for window.LiveComponents.get()
// List all components
lc.all()
// Component state
lc.state('shopping-cart:main')
// Component history
lc.history('shopping-cart:main')
// Trigger action manually
lc.call('shopping-cart:main', 'addItem', { item: testItem })
// Enable/disable debug mode
lc.debug(true) // Enable
lc.debug(false) // Disable
// Performance stats
lc.stats('shopping-cart:main')
// Clear component cache
lc.clearCache('shopping-cart:main')
```
### React DevTools Style Inspector
```javascript
// Component tree visualization
window.LiveComponents.inspect()
// Logs component hierarchy:
/*
shopping-cart:main
βββ cart-item:item-1
βββ cart-item:item-2
βββ cart-total:main
*/
// Component details
window.LiveComponents.inspectComponent('shopping-cart:main')
// Logs:
/*
Component: shopping-cart:main
State: { items: [...], total: 2999 }
Actions: [addItem, removeItem, updateQuantity]
Events: [itemAdded, itemRemoved]
Polling: { enabled: true, interval: 5000ms }
Cache: { enabled: true, ttl: 300s, hits: 23, misses: 5 }
Performance: { avgRenderTime: 15ms, actionCount: 47 }
*/
```
---
## Server-Side Logging
### Structured Logging
```php
use App\Framework\LiveComponents\Logging\ComponentLogger;
use Psr\Log\LogLevel;
final readonly class ComponentLogger
{
public function logAction(
string $componentId,
string $action,
array $context = []
): void {
$this->logger->log(LogLevel::INFO, 'LiveComponent action executed', [
'component_id' => $componentId,
'action' => $action,
'user_id' => $context['user_id'] ?? null,
'session_id' => $context['session_id'] ?? null,
'execution_time_ms' => $context['execution_time'] ?? null,
'timestamp' => time()
]);
}
public function logError(
string $componentId,
string $action,
\Throwable $error,
array $context = []
): void {
$this->logger->log(LogLevel::ERROR, 'LiveComponent action failed', [
'component_id' => $componentId,
'action' => $action,
'error_message' => $error->getMessage(),
'error_class' => get_class($error),
'stack_trace' => $error->getTraceAsString(),
'state_snapshot' => $context['state'] ?? null,
'parameters' => $context['parameters'] ?? null
]);
}
}
```
### Action Audit Log
```php
final readonly class ActionAuditLogger
{
public function logActionExecution(
ActionExecution $execution
): void {
$this->auditLog->write([
'event' => 'livecomponent.action',
'component_id' => $execution->componentId,
'action' => $execution->action,
'user_id' => $execution->userId,
'ip_address' => $execution->ipAddress,
'user_agent' => $execution->userAgent,
'parameters' => $this->sanitizeParameters($execution->parameters),
'success' => $execution->success,
'error' => $execution->error?->getMessage(),
'execution_time_ms' => $execution->executionTime->toMilliseconds(),
'timestamp' => $execution->timestamp->format('Y-m-d H:i:s')
]);
}
private function sanitizeParameters(array $parameters): array
{
// Remove sensitive data from logs
$sanitized = $parameters;
foreach (['password', 'token', 'api_key', 'secret'] as $sensitive) {
if (isset($sanitized[$sensitive])) {
$sanitized[$sensitive] = '[REDACTED]';
}
}
return $sanitized;
}
}
```
### Log Aggregation Queries
```bash
# Find slow actions (Elasticsearch/Kibana query)
GET /livecomponents-logs/_search
{
"query": {
"bool": {
"must": [
{ "match": { "event": "livecomponent.action" } },
{ "range": { "execution_time_ms": { "gte": 100 } } }
]
}
},
"aggs": {
"slow_actions": {
"terms": {
"field": "action.keyword",
"size": 10
},
"aggs": {
"avg_time": { "avg": { "field": "execution_time_ms" } }
}
}
}
}
# Find error patterns
GET /livecomponents-logs/_search
{
"query": {
"bool": {
"must": [
{ "match": { "success": false } }
]
}
},
"aggs": {
"error_types": {
"terms": { "field": "error_class.keyword" }
},
"affected_components": {
"terms": { "field": "component_id.keyword" }
}
}
}
```
---
## Testing & Development Helpers
### Pest Testing Helpers
```php
use function Pest\LiveComponents\mountComponent;
use function Pest\LiveComponents\callAction;
// Mount component with debug enabled
it('debugs component state changes', function () {
$component = mountComponent('shopping-cart:main', [
'items' => [],
'total' => 0
], debug: true); // Enable debug mode
// Call action with debug output
$result = callAction($component, 'addItem', [
'item' => ['id' => '1', 'name' => 'Test', 'price' => 1000]
], debug: true);
// Debug output automatically logged:
/*
[DEBUG] Action: addItem
[DEBUG] Before State: {"items":[],"total":0}
[DEBUG] Parameters: {"item":{"id":"1","name":"Test","price":1000}}
[DEBUG] After State: {"items":[...],"total":1000}
[DEBUG] Execution Time: 2.34ms
*/
expect($result['state']['total'])->toBe(1000);
});
```
### Mock State Inspector
```php
// Create mock state inspector for testing
final readonly class MockStateInspector implements StateInspector
{
private array $snapshots = [];
private array $logs = [];
public function captureSnapshot(string $label, ComponentData $state, ?array $metadata = null): void
{
$this->snapshots[] = new StateSnapshot($label, $state, microtime(true), metadata: $metadata);
}
public function getSnapshots(string $componentId): array
{
return array_filter(
$this->snapshots,
fn($s) => str_starts_with($s->label, $componentId)
);
}
public function log(string $message, array $context = []): void
{
$this->logs[] = ['message' => $message, 'context' => $context, 'time' => microtime(true)];
}
public function getLogs(): array
{
return $this->logs;
}
}
// Use in tests
it('captures state snapshots during action', function () {
$inspector = new MockStateInspector();
$component = new ShoppingCartComponent(
id: ComponentId::fromString('cart:test'),
state: new ShoppingCartState([], 0),
stateInspector: $inspector
);
$component->addItem(new CartItem('1', 'Test', 1000));
$snapshots = $inspector->getSnapshots('cart:test');
expect($snapshots)->toHaveCount(2) // before and after
->and($inspector->getLogs())->toContain(fn($log) => $log['message'] === 'State changed');
});
```
---
## Troubleshooting Workflows
### Workflow 1: Component Not Rendering
```
1. Check component registration
β Verify #[LiveComponent] attribute present
β Check component name matches template usage
2. Check initialization
β Console: window.LiveComponents.get('component:id')
β Should return component instance
3. Verify template
β Check render() method returns correct template path
β Verify template file exists
β Check template syntax
4. Check state
β Verify state class is readonly
β Check constructor parameters
β Ensure state serializable
5. Server logs
β Check for component registration errors
β Look for template loading errors
β Verify DI container bindings
```
### Workflow 2: Action Fails Silently
```
1. Enable debug mode
β Set debug: true in config
β Check browser console for errors
2. Network inspection
β DevTools > Network > Filter: livecomponent
β Check request payload
β Verify response status (200/403/429/500)
3. Server-side debugging
β Add error_log() in action method
β Check action parameter types match
β Verify return type is ComponentData
4. State validation
β Ensure new state is returned (not modified)
β Check state is serializable
β Verify no circular references
5. Security checks
β CSRF token present and valid
β Rate limit not exceeded
β Authentication/authorization passed
```
### Workflow 3: Performance Degradation
```
1. Measure baseline
β Use Performance API to measure render times
β Track action execution times
β Monitor network request sizes
2. Identify bottleneck
β Profile component lifecycle
β Check database query count (N+1 problems)
β Verify cache effectiveness
3. Optimize rendering
β Enable fragment rendering
β Implement component caching with varyBy
β Use SWR for non-critical updates
4. Reduce network overhead
β Enable request batching
β Compress responses (gzip)
β Implement polling backoff
5. Server-side optimization
β Add database indexes
β Optimize queries (eager loading)
β Implement query result caching
β Use Redis for session storage
```
---
## Production Debugging
### Safe Production Debugging
```php
// Enable debug mode for specific users only
final readonly class DebugModeManager
{
public function isDebugEnabledForUser(?string $userId): bool
{
if (!$userId) {
return false;
}
// Allow debug mode for admin users
if ($this->userService->isAdmin($userId)) {
return true;
}
// Allow debug mode via feature flag
if ($this->featureFlags->isEnabled('livecomponents-debug', $userId)) {
return true;
}
return false;
}
}
// Conditional debug logging
$config = new LiveComponentsConfig(
debug: $this->debugManager->isDebugEnabledForUser($currentUserId),
enableDevTools: false, // Never enable in production
logLevel: 'error' // Only log errors in production
);
```
### Production Error Tracking
```php
use App\Framework\ErrorReporting\ErrorReporter;
final readonly class ProductionErrorHandler
{
public function __construct(
private ErrorReporter $errorReporter // e.g., Sentry, Rollbar
) {}
public function handleActionError(
string $componentId,
string $action,
\Throwable $error,
array $context
): void {
$this->errorReporter->captureException($error, [
'tags' => [
'component' => 'livecomponents',
'component_id' => $componentId,
'action' => $action
],
'extra' => [
'user_id' => $context['user_id'] ?? null,
'session_id' => $context['session_id'] ?? null,
'state_hash' => $context['state_hash'] ?? null,
'parameters' => $this->sanitize($context['parameters'] ?? [])
],
'fingerprint' => [
$componentId,
$action,
get_class($error)
]
]);
}
}
```
### Production Monitoring
```php
// Metrics collection for production monitoring
final readonly class ProductionMetricsCollector
{
public function recordActionExecution(
string $componentId,
string $action,
float $executionTime,
bool $success
): void {
// StatsD/Prometheus metrics
$this->metrics->increment('livecomponents.action.count', [
'component' => $componentId,
'action' => $action,
'success' => $success ? 'true' : 'false'
]);
$this->metrics->timing('livecomponents.action.duration', $executionTime, [
'component' => $componentId,
'action' => $action
]);
}
public function recordCacheHit(string $componentId, bool $hit): void
{
$this->metrics->increment('livecomponents.cache.' . ($hit ? 'hit' : 'miss'), [
'component' => $componentId
]);
}
}
```
### Feature Flags for Debugging
```php
// Use feature flags to enable debugging features safely
final readonly class FeatureFlagDebugger
{
public function shouldEnableVerboseLogging(string $componentId): bool
{
return $this->featureFlags->isEnabled("debug:verbose:{$componentId}");
}
public function shouldCaptureSnapshots(string $componentId): bool
{
return $this->featureFlags->isEnabled("debug:snapshots:{$componentId}");
}
public function shouldProfilePerformance(string $componentId): bool
{
return $this->featureFlags->isEnabled("debug:profiling:{$componentId}");
}
}
// Usage in component
#[Action]
public function processPayment(PaymentRequest $request): ComponentData
{
if ($this->debugger->shouldCaptureSnapshots($this->id->toString())) {
$this->stateInspector->captureSnapshot('before_payment', $this->state);
}
$result = $this->paymentService->process($request);
if ($this->debugger->shouldCaptureSnapshots($this->id->toString())) {
$this->stateInspector->captureSnapshot('after_payment', $this->state);
}
return $result;
}
```
---
## Summary
### Quick Reference
**Enable Debug Mode:**
```php
new LiveComponentsConfig(debug: true, enableDevTools: true, logLevel: 'debug')
```
**Client-Side Debugging:**
```javascript
window.LiveComponents.setDebug(true);
lc('component:id').state; // Inspect state
lc.call('component:id', 'action', params); // Manual action
```
**Server-Side Debugging:**
```php
$this->stateInspector->captureSnapshot('label', $state);
$this->logger->debug('Action executed', $context);
```
**Performance Profiling:**
```javascript
performance.mark('start');
await action();
performance.mark('end');
performance.measure('action', 'start', 'end');
```
**Production Monitoring:**
```php
$this->errorReporter->captureException($error, $context);
$this->metrics->timing('action.duration', $time);
```
### Best Practices
1. **Development**: Enable debug mode and DevTools
2. **Staging**: Enable selective debug for specific users
3. **Production**: Disable debug, use error reporting and metrics
4. **Logging**: Use structured logging with proper context
5. **Performance**: Profile regularly, set performance budgets
6. **Security**: Never log sensitive data (passwords, tokens)
7. **Monitoring**: Set up alerts for error rates and slow actions
8. **Testing**: Use debug helpers in Pest tests
### Resources
- **Browser DevTools**: Chrome/Firefox/Edge Developer Tools
- **Error Tracking**: Sentry, Rollbar, Bugsnag
- **Metrics**: StatsD, Prometheus, Datadog
- **Logging**: ELK Stack, Graylog, Splunk
- **Profiling**: Blackfire, Tideways, XHProf
- **Testing**: Pest, PHPUnit, Playwright
This guide covers debugging workflows, tools, and best practices for developing and maintaining LiveComponents in development, staging, and production environments.