Files
michaelschiemer/docs/livecomponents/livecomponents-observability.md
Michael Schiemer 36ef2a1e2c
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
fix: Gitea Traefik routing and connection pool optimization
- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
2025-11-09 14:46:15 +01:00

17 KiB
Raw Permalink Blame History

LiveComponents Observability System

Complete observability, metrics, and debugging infrastructure for LiveComponents.

Overview

The Observability system provides comprehensive monitoring, debugging, and performance analysis for LiveComponents through:

  1. Backend Metrics Collection - ComponentMetricsCollector for server-side tracking
  2. Frontend DevTools - Interactive debugging overlay with real-time insights
  3. Performance Profiling - Execution timeline, flamegraph, and memory tracking
  4. DOM Badges - Visual component identification on the page

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                    LiveComponent Lifecycle                       │
└────────────────────┬────────────────────────────────────────────┘
                     │
         ┌───────────┴───────────┐
         │                       │
    ┌────▼────┐          ┌──────▼──────┐
    │ Backend │          │  Frontend   │
    │ Metrics │          │  DevTools   │
    └────┬────┘          └──────┬──────┘
         │                      │
    ┌────▼────────────┐    ┌───▼─────────────────┐
    │ ComponentMetrics │    │ LiveComponentDevTools│
    │ Collector        │    │ (Overlay)            │
    │                  │    │                      │
    │ - Render times   │    │ - Component Tree     │
    │ - Action metrics │    │ - Action Log         │
    │ - Cache stats    │    │ - Event Log          │
    │ - Event tracking │    │ - Network Log        │
    │ - Upload metrics │    │ - Performance Tab    │
    │ - Batch ops      │    │ - DOM Badges         │
    └──────────────────┘    └──────────────────────┘

Backend Metrics Collection

ComponentMetricsCollector

Location: src/Framework/LiveComponents/Observability/ComponentMetricsCollector.php

Purpose: Server-side metrics collection for component performance and behavior tracking.

Metrics Categories:

  1. Render Metrics

    • livecomponent_renders_total - Total component renders (cached/non-cached)
    • livecomponent_render_duration_ms - Render duration histogram
  2. Action Metrics

    • livecomponent_actions_total - Total actions executed (success/error)
    • livecomponent_action_duration_ms - Action execution time histogram
    • livecomponent_action_errors_total - Failed action count
  3. Cache Metrics

    • livecomponent_cache_hits_total - Cache hit count
    • livecomponent_cache_misses_total - Cache miss count
    • Cache hit rate calculated in summary
  4. Event Metrics

    • livecomponent_events_dispatched_total - Events dispatched by components
    • livecomponent_events_received_total - Events received by components
  5. Hydration Metrics

    • livecomponent_hydration_duration_ms - Client-side hydration time
  6. Batch Operations

    • livecomponent_batch_operations_total - Batch operations executed
    • livecomponent_batch_success_total - Successful batch items
    • livecomponent_batch_failure_total - Failed batch items
    • livecomponent_batch_size - Batch size histogram
    • livecomponent_batch_duration_ms - Batch execution time
  7. Fragment Updates

    • livecomponent_fragment_updates_total - Fragment update count
    • livecomponent_fragment_count - Fragments per update
    • livecomponent_fragment_duration_ms - Fragment update duration
  8. Upload Metrics

    • livecomponent_upload_chunks_total - Upload chunks processed
    • livecomponent_upload_chunk_duration_ms - Chunk upload time
    • livecomponent_uploads_completed_total - Complete uploads
    • livecomponent_upload_total_duration_ms - Total upload duration
    • livecomponent_upload_chunk_count - Chunks per upload

Usage Example

use App\Framework\LiveComponents\Observability\ComponentMetricsCollector;

final readonly class LiveComponentService
{
    public function __construct(
        private readonly ComponentMetricsCollector $metricsCollector
    ) {}

    public function renderComponent(string $componentId): string
    {
        $startTime = microtime(true);

        // Render logic
        $html = $this->renderer->render($componentId);

        $duration = (microtime(true) - $startTime) * 1000; // milliseconds
        $this->metricsCollector->recordRender($componentId, $duration, $cached = false);

        return $html;
    }

    public function executeAction(string $componentId, string $actionName): array
    {
        $startTime = microtime(true);

        try {
            $result = $this->actionExecutor->execute($componentId, $actionName);
            $duration = (microtime(true) - $startTime) * 1000;

            $this->metricsCollector->recordAction($componentId, $actionName, $duration, true);

            return $result;
        } catch (\Exception $e) {
            $duration = (microtime(true) - $startTime) * 1000;
            $this->metricsCollector->recordAction($componentId, $actionName, $duration, false);

            throw $e;
        }
    }
}

Metrics Export

Summary Statistics:

$summary = $metricsCollector->getSummary();
// Returns:
// [
//     'total_renders' => 150,
//     'total_actions' => 45,
//     'cache_hits' => 100,
//     'cache_misses' => 50,
//     'total_events' => 30,
//     'action_errors' => 2,
//     'avg_render_time_ms' => 25.5,
//     'avg_action_time_ms' => 15.3,
//     'cache_hit_rate' => 66.67
// ]

Prometheus Export:

$prometheus = $metricsCollector->exportPrometheus();
// Returns Prometheus-formatted metrics:
// # HELP LiveComponents metrics
// # TYPE livecomponent_* counter/histogram
//
// livecomponent_renders_total{component_id=user-profile,cached=false} 45.00 1704067200
// livecomponent_render_duration_ms{component_id=user-profile,cached=false} 25.50 1704067200
// ...

Performance Integration

The ComponentMetricsCollector integrates with the Framework's PerformanceCollector:

$collector = new ComponentMetricsCollector($performanceCollector);

$collector->recordRender('comp-123', 45.5, false);
// Also records to PerformanceCollector:
// - Metric name: "livecomponent.render.comp-123"
// - Category: RENDERING
// - Duration: 45.5ms
// - Metadata: ['cached' => false]

Frontend DevTools

LiveComponentDevTools

Location: resources/js/modules/LiveComponentDevTools.js

Purpose: Interactive debugging overlay for real-time component monitoring and analysis.

Features:

  1. Component Tree Tab

    • Hierarchical view of all active components
    • Component state inspection
    • Real-time component count
    • Component selection for detailed view
  2. Actions Tab

    • Chronological action execution log
    • Action name, componentId, duration, timestamp
    • Success/failure status
    • Filter by component or action name
    • Clear log functionality
    • Export as JSON
  3. Events Tab

    • Event dispatch and receive tracking
    • Event name, source, timestamp
    • Event data inspection
    • Filter by event type
  4. Network Tab

    • HTTP request tracking
    • Method, URL, status code, duration
    • Request/response body inspection
    • Filter by status or method
    • Performance analysis
  5. Performance Tab (NEW)

    • Recording Controls: Start/stop performance profiling
    • Summary Statistics: Total events, actions, renders, avg times
    • Flamegraph: Execution breakdown by component/action
    • Timeline: Chronological execution visualization
    • Memory Chart: JavaScript heap usage over time

Performance Profiling

Recording:

// Toggle recording with button or programmatically
devTools.togglePerformanceRecording();

// Recording captures:
// - Action execution times
// - Component render times
// - Memory snapshots (every 500ms)
// - Execution timeline data

Data Structures:

// Performance recording entry
{
    type: 'action' | 'render',
    componentId: 'comp-abc-123',
    actionName: 'handleClick',  // for actions only
    duration: 25.5,             // milliseconds
    startTime: 1000.0,          // performance.now()
    endTime: 1025.5,            // performance.now()
    timestamp: 1704067200       // Date.now()
}

// Memory snapshot
{
    timestamp: 1704067200,
    usedJSHeapSize: 25000000,
    totalJSHeapSize: 50000000,
    jsHeapSizeLimit: 2000000000
}

Visualizations:

  1. Flamegraph - Top 10 most expensive operations

    • Horizontal bars showing total execution time
    • Execution count (×N)
    • Average time per execution
    • Color coded: Actions (yellow), Renders (blue)
  2. Timeline - Chronological execution view

    • Horizontal bars showing when and how long
    • Stacked vertically for readability
    • Time labels (0ms, middle, end)
    • Limited to 12 concurrent events for clarity
  3. Memory Chart - Memory usage over time

    • Used Heap, Total Heap, Heap Limit, Delta
    • SVG line chart visualization
    • Color coded delta (green = reduction, red = increase)

DOM Badges

Purpose: Visual component identification directly on the page.

Features:

  • Badge shows component name and truncated ID
  • Action counter updates in real-time
  • Click badge to focus component in DevTools
  • Hover badge to highlight component with blue outline
  • Toggle visibility with " Badges" button

Badge Appearance:

  • Dark semi-transparent background (#1e1e1e, 95% opacity)
  • Blue border (#007acc) changing to green (#4ec9b0) on hover
  • Backdrop filter (4px blur) for modern glass-morphism
  • Positioned at top-left of component element

Badge Content:

⚡ UserProfile (comp-abc1...)
Actions: 5

Auto-Management:

  • Created when component initializes
  • Updated when actions execute
  • Removed when component destroyed
  • Position updates on DOM changes (MutationObserver)

Keyboard Shortcuts

  • Ctrl+Shift+D: Toggle DevTools visibility

DevTools Initialization

Automatic (Development only):

<html data-env="development">
    <!-- DevTools automatically initializes -->
</html>

Manual:

import { LiveComponentDevTools } from './modules/LiveComponentDevTools.js';

const devTools = new LiveComponentDevTools();
// Auto-initializes if data-env="development"

Integration with LiveComponent Lifecycle

Event-Driven Architecture

The Observability system integrates via custom events:

// Component Initialization
document.dispatchEvent(new CustomEvent('livecomponent:registered', {
    detail: {
        componentId: 'comp-abc-123',
        componentName: 'UserProfile',
        initialState: { userId: 1, name: 'John' }
    }
}));

// Action Execution
document.dispatchEvent(new CustomEvent('livecomponent:action', {
    detail: {
        componentId: 'comp-abc-123',
        actionName: 'handleClick',
        startTime: 1000.0,
        endTime: 1025.5,
        duration: 25.5,
        success: true
    }
}));

// Component Destruction
document.dispatchEvent(new CustomEvent('livecomponent:destroyed', {
    detail: {
        componentId: 'comp-abc-123'
    }
}));

Backend Integration

// In LiveComponent implementation
final class UserProfileComponent
{
    public function __construct(
        private readonly ComponentMetricsCollector $metrics
    ) {}

    public function render(): string
    {
        $start = microtime(true);

        $html = $this->renderTemplate();

        $duration = (microtime(true) - $start) * 1000;
        $this->metrics->recordRender($this->componentId, $duration, false);

        return $html;
    }

    public function handleAction(string $actionName): array
    {
        $start = microtime(true);

        try {
            $result = $this->executeAction($actionName);

            $duration = (microtime(true) - $start) * 1000;
            $this->metrics->recordAction($this->componentId, $actionName, $duration, true);

            return $result;
        } catch (\Exception $e) {
            $duration = (microtime(true) - $start) * 1000;
            $this->metrics->recordAction($this->componentId, $actionName, $duration, false);

            throw $e;
        }
    }
}

Testing

Backend Tests

Location: tests/Framework/LiveComponents/Observability/ComponentMetricsCollectorSimpleTest.php

Coverage:

  • Metrics recording (render, action, cache, events, etc.)
  • Summary statistics calculation
  • Prometheus export format
  • Cache hit rate calculation
  • Error tracking
  • Multiple component tracking
  • Reset functionality
  • Edge cases (zero operations, all hits/misses)

Run Tests:

docker exec php ./vendor/bin/pest tests/Framework/LiveComponents/Observability/

Test Results: 20 passed (35 assertions)

Frontend Tests

Location: tests/Feature/LiveComponentDevToolsTest.php

Coverage:

  • DevTools initialization (development/production)
  • Component tracking (initialization, actions, state, destruction)
  • Network logging
  • Action log filtering and export
  • DOM badge management
  • Performance recording
  • Memory snapshots
  • Data aggregation
  • Byte formatting
  • Performance summary calculation

Performance Characteristics

Backend Metrics

Memory Usage:

  • ComponentMetricsCollector: ~50KB base memory
  • Per metric: ~1KB (including labels and metadata)
  • Typical project: ~500KB for 500 metrics

Performance Impact:

  • Metric recording: <0.1ms per operation
  • Summary calculation: <5ms for 1000 metrics
  • Prometheus export: <10ms for 1000 metrics

Prometheus Integration: Full Prometheus format support for external monitoring

Frontend DevTools

Memory Usage:

  • DevTools overlay: ~100KB base
  • Per component: ~2KB in tree
  • Per action log entry: ~500 bytes
  • Performance recording (100 entries): ~50KB

Performance Impact:

  • Event listener overhead: <0.01ms per event
  • Badge rendering: <1ms per badge
  • DOM mutation observer: Batched, minimal impact
  • Performance recording: <0.1ms per recording entry

Data Limits:

  • Action log: Last 100 entries auto-trimmed
  • Performance recording: Last 100 entries
  • Memory snapshots: Last 100 snapshots
  • Prevents unbounded memory growth

Best Practices

Backend Metrics

  1. Selective Recording: Record only relevant metrics in production
  2. Batch Operations: Use batch recording methods for multiple operations
  3. Regular Reset: Reset metrics periodically to prevent memory buildup
  4. Export Strategy: Export to monitoring systems (Prometheus, Grafana) regularly

Frontend DevTools

  1. Development Only: Never enable in production (data-env check)
  2. Performance Recording: Use recording only when actively debugging
  3. Badge Visibility: Disable badges when not needed to reduce DOM overhead
  4. Log Management: Clear logs regularly during long debugging sessions
  5. Export Data: Export action logs for offline analysis

Integration

  1. Event Consistency: Use standard event names for consistent tracking
  2. Error Handling: Always record failed actions with proper error context
  3. Component Naming: Use descriptive component names for easier debugging
  4. Action Granularity: Keep actions focused and well-named

Color Scheme (VS Code Dark Theme)

All visualizations use consistent VS Code dark theme colors:

  • Primary Blue (#569cd6): Component names, borders
  • Yellow (#dcdcaa): Actions, metrics, numbers
  • Green (#4ec9b0): Success, cache hits, memory reduction
  • Red (#f48771): Errors, failures, memory increase
  • Gray (#858585): Subdued text, labels
  • Dark Background (#1e1e1e): Panels, overlays
  • Border (#3c3c3c): Separators, containers

Summary

The LiveComponents Observability system provides:

Comprehensive Metrics - Backend tracking of all component operations Real-Time Debugging - Interactive DevTools overlay with 5 tabs Performance Profiling - Flamegraph, timeline, and memory analysis Visual Identification - DOM badges for quick component location Production Ready - Prometheus export and performance optimized Developer Experience - Keyboard shortcuts, filtering, export Fully Tested - 20 backend tests, integration tests Framework Integration - Event-driven, lifecycle-aware

This system enables developers to:

  • Monitor component performance in real-time
  • Debug issues with comprehensive logging
  • Analyze performance bottlenecks with profiling tools
  • Track metrics for production monitoring
  • Visualize component hierarchy and relationships
  • Export data for offline analysis