Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Backtrace Laravel Package

axy/backtrace

axy/backtrace is a lightweight PHP 8.1+ helper for working with call stacks. It provides Trace and ExceptionTrace utilities to inspect and trim backtraces, useful for debugging and cleaning up exception stack displays in apps and libraries.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require axy/backtrace
    

    Requires PHP 8.0+ and Laravel 8+ (or standalone PHP).

  2. Basic Usage:

    use Axy\Backtrace\Backtrace;
    
    $backtrace = new Backtrace();
    $backtrace->start('user_action'); // Start a trace with a label
    
    // Simulate some operations
    $backtrace->step('database_query', ['query' => 'SELECT * FROM users']);
    $backtrace->step('process_data', ['count' => 10]);
    
    $backtrace->end(); // End the trace
    $traceData = $backtrace->getTrace(); // Get structured trace data
    
  3. First Use Case:

    • Debugging Slow Endpoints: Wrap a controller method or service call in Backtrace to log execution steps with timestamps and metadata.
    • Example:
      public function index()
      {
          $backtrace = new Backtrace();
          $backtrace->start('UserController@index');
      
          $users = User::query()->get();
          $backtrace->step('User::all', ['count' => $users->count()]);
      
          return response()->json($users);
      }
      
  4. Where to Look First:

    • README for core concepts.
    • src/Backtrace.php for API reference.
    • tests/ for advanced use cases (e.g., nested traces, custom steps).

Implementation Patterns

Core Workflows

  1. Structured Tracing:

    • Use start()/end() to demarcate logical blocks (e.g., API routes, jobs, commands).
    • Nest traces for hierarchical debugging:
      $backtrace->start('process_order');
      $backtrace->start('validate_payment');
      // ... validation logic
      $backtrace->end(); // End nested trace
      $backtrace->end(); // End parent trace
      
  2. Integration with Laravel:

    • Middleware: Inject Backtrace into middleware to trace HTTP requests:
      public function handle(Request $request, Closure $next)
      {
          $backtrace = new Backtrace();
          $backtrace->start('HTTP_REQUEST', ['method' => $request->method()]);
      
          $response = $next($request);
          $backtrace->step('HTTP_RESPONSE', ['status' => $response->status()]);
          $backtrace->end();
      
          return $response;
      }
      
    • Service Containers: Bind Backtrace to the container for dependency injection:
      $this->app->singleton(Backtrace::class, fn() => new Backtrace());
      
  3. Custom Step Metadata:

    • Attach context to steps (e.g., query parameters, user IDs):
      $backtrace->step('authenticate_user', [
          'user_id' => auth()->id(),
          'provider' => 'sanctum',
      ]);
      
  4. Async Operations:

    • Use Backtrace in queues/jobs to trace background tasks:
      public function handle()
      {
          $backtrace = new Backtrace();
          $backtrace->start('SendEmailJob');
      
          Mail::to($this->user->email)->send(new WelcomeEmail());
          $backtrace->step('Mail::send', ['recipient' => $this->user->email]);
      
          $backtrace->end();
      }
      
  5. Output Formats:

    • Convert traces to JSON for logging (e.g., Laravel Log Channel):
      Log::info('Trace', ['data' => $backtrace->getTrace()]);
      
    • Use Backtrace::toArray() or toJson() for serialization.

Gotchas and Tips

Pitfalls

  1. Memory Leaks:

    • Avoid storing Backtrace instances in long-lived objects (e.g., app state). Traces accumulate steps and can bloat memory.
    • Fix: Create new instances per request/operation or reset with $backtrace->reset().
  2. Nested Trace Mismatches:

    • Forgetting to call end() for nested traces will corrupt the hierarchy.
    • Fix: Use a try-finally block or a context manager:
      $backtrace->start('outer');
      try {
          $backtrace->start('inner');
          // ...
      } finally {
          $backtrace->end();
      }
      $backtrace->end();
      
  3. Performance Overhead:

    • Excessive steps (e.g., logging every loop iteration) can slow down critical paths.
    • Fix: Batch steps or use conditional logging:
      if (config('app.debug')) {
          $backtrace->step('loop_iteration', ['index' => $i]);
      }
      
  4. Thread Safety:

    • Backtrace is not thread-safe. Avoid sharing instances across concurrent requests (e.g., in Laravel’s app singleton).
    • Fix: Bind to the container with AppServiceProvider::boot() or use per-request instances.
  5. Timestamp Precision:

    • Steps use microtime(true), which may not align with system clocks in distributed environments.
    • Fix: Normalize timestamps if comparing across services.

Debugging Tips

  1. Inspect Traces:

    • Use dd($backtrace->getTrace()) to visualize the trace structure during development.
    • Look for missing end() calls or misaligned hierarchies.
  2. Log Exceptions:

    • Catch exceptions and log them with the trace context:
      try {
          $backtrace->start('risky_operation');
          // ...
      } catch (\Exception $e) {
          Log::error('Failed', [
              'trace' => $backtrace->getTrace(),
              'error' => $e->getMessage(),
          ]);
          throw $e;
      } finally {
          $backtrace->end();
      }
      
  3. Custom Step Validation:

    • Override Backtrace::step() to validate metadata:
      $backtrace->step('custom_step', ['required_field' => 'value']);
      

Extension Points

  1. Custom Step Types:

    • Extend Backtrace to add domain-specific steps:
      class DomainBacktrace extends Backtrace
      {
          public function databaseQuery(string $query, array $bindings = [])
          {
              $this->step('db.query', compact('query', 'bindings'));
          }
      }
      
  2. Output Adapters:

    • Implement Axy\Backtrace\Contracts\TraceOutput to write traces to custom destinations (e.g., OpenTelemetry, Datadog):
      class OpenTelemetryAdapter implements TraceOutput
      {
          public function write(array $trace): void
          {
              // Convert to OpenTelemetry spans
          }
      }
      
  3. Middleware Integration:

    • Create a base middleware to auto-inject Backtrace:
      class TraceMiddleware
      {
          public function handle($request, Closure $next)
          {
              $backtrace = new Backtrace();
              $backtrace->start('HTTP', ['uri' => $request->fullUrl()]);
      
              try {
                  return $next($request);
              } finally {
                  $backtrace->end();
                  Log::debug('Trace', ['data' => $backtrace->getTrace()]);
              }
          }
      }
      
  4. Performance Profiling:

    • Combine with laravel-debugbar to visualize traces in the browser:
      Debugbar::info('Trace', $backtrace->getTrace());
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope