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

Opentelemetry Auto Class Laravel Package

eerzho/opentelemetry-auto-class

Framework-agnostic automatic OpenTelemetry tracing for PHP 8.2+ using #[Traceable]. Mark a class and public methods generate spans via ext-opentelemetry hook API. Supports excluding methods; Laravel/Symfony integrations available.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install the Package:

    composer require eerzho/opentelemetry-auto-class
    

    Ensure ext-opentelemetry is installed and enabled in your PHP environment.

  2. Annotate a Class: Add the #[Traceable] attribute to any class to automatically trace all public methods:

    use OpenTelemetry\Contrib\Instrumentation\Class\Attribute\Traceable;
    
    #[Traceable]
    class UserService
    {
        public function createUser(array $data): void
        {
            // Automatically traced
        }
    }
    
  3. Register Instrumentation: Scan and register the class for tracing in your application’s bootstrap (e.g., AppServiceProvider):

    use OpenTelemetry\Contrib\Instrumentation\Class\AttributeScanner;
    use OpenTelemetry\Contrib\Instrumentation\Class\ClassInstrumentation;
    
    public function boot()
    {
        $map = AttributeScanner::scan([UserService::class]);
        ClassInstrumentation::register($map);
    }
    
  4. Verify Tracing: Trigger the traced method and check your OpenTelemetry backend (e.g., Jaeger, Honeycomb) for the generated span named UserService::createUser.


First Use Case: Tracing Laravel HTTP Requests

For a Laravel application, trace controller methods to monitor API performance:

#[Traceable]
class OrderController extends Controller
{
    public function store(Request $request): JsonResponse
    {
        // Automatically traced as "OrderController::store"
        $order = Order::create($request->all());
        return response()->json($order);
    }
}

Register the controller in AppServiceProvider:

ClassInstrumentation::register(
    AttributeScanner::scan([OrderController::class])
);

Implementation Patterns

Workflows

1. Attribute-Based Tracing

  • Pattern: Annotate classes with #[Traceable] to enable tracing for all public methods.
  • Example:
    #[Traceable(exclude: ['healthCheck'])]
    class PaymentGateway
    {
        public function processPayment(float $amount): void
        {
            // Traced
        }
    
        public function healthCheck(): bool
        {
            // Excluded from tracing
            return true;
        }
    }
    
  • Use Case: Quickly instrument critical services without manual span creation.

2. Manual Instrumentation Map

  • Pattern: Register classes without attributes by defining a method map.
  • Example:
    ClassInstrumentation::register([
        UserRepository::class => [
            'findById' => ['id' => 0], // Capture 'id' argument
            'save' => [], // Trace without arguments
        ],
    ]);
    
  • Use Case: Fine-grained control over traced methods in legacy codebases.

3. Argument Filtering

  • Pattern: Use #[Arguments(exclude: [...])] to hide sensitive data (e.g., passwords, tokens).
  • Example:
    #[Traceable]
    class AuthService
    {
        #[Arguments(exclude: ['password'])]
        public function login(string $email, string $password): void
        {
            // Only 'email' is captured as a span attribute
        }
    }
    
  • Use Case: Securely trace authentication flows while omitting PII.

4. Laravel Integration

  • Pattern: Use the Laravel-specific package (eerzho/opentelemetry-auto-class-laravel) for automatic class discovery.
  • Steps:
    1. Install the Laravel integration:
      composer require eerzho/opentelemetry-auto-class-laravel
      
    2. Publish the config (if needed) and enable auto-discovery in config/opentelemetry.php:
      'instrumentation' => [
          'class' => [
              'enabled' => true,
              'scanned_classes' => [
                  App\Services\*,
                  App\Http\Controllers\*,
              ],
          ],
      ],
      
  • Use Case: Reduce boilerplate by auto-tracing all annotated classes in your app.

Integration Tips

Laravel-Specific

  • Middleware Integration: Trace HTTP requests by annotating middleware:

    #[Traceable]
    class LogRequestMiddleware
    {
        public function handle(Request $request, Closure $next): Response
        {
            return $next($request);
        }
    }
    

    Register it in app/Http/Kernel.php:

    protected $middleware = [
        \App\Http\Middleware\LogRequestMiddleware::class,
    ];
    
  • Queue Jobs: Annotate dispatched jobs to trace async workflows:

    #[Traceable]
    class ProcessOrderJob implements ShouldQueue
    {
        public function handle(): void
        {
            // Traced as "ProcessOrderJob::handle"
        }
    }
    

OpenTelemetry Context

  • Propagate Context: Ensure context is propagated across HTTP requests or queue workers by configuring your OTel SDK:

    use OpenTelemetry\API\Propagation\TextMapPropagator;
    
    $propagator = new TextMapPropagator();
    $propagator->inject($carrier, $context);
    

    In Laravel, use middleware to inject context into HTTP headers:

    public function handle($request, Closure $next)
    {
        $carrier = [];
        $propagator->extract($carrier, $request->header());
        $context = $propagator->extract($carrier, $request->header());
        // Attach context to the request or span
        return $next($request);
    }
    
  • Custom Span Attributes: Extend spans with custom attributes by accessing the active span in your methods:

    use OpenTelemetry\API\Trace\Span;
    use OpenTelemetry\API\Trace\TracerInterface;
    
    #[Traceable]
    class OrderService
    {
        public function __construct(private TracerInterface $tracer) {}
    
        public function create(array $items): void
        {
            $span = $this->tracer->getCurrentSpan();
            $span->setAttribute('order.type', 'premium');
        }
    }
    

Gotchas and Tips

Pitfalls

1. Public Method Limitation

  • Issue: Only public methods are traced. Protected/private methods are ignored.
  • Workaround: Use a public facade method to trace internal logic:
    #[Traceable]
    class UserRepository
    {
        public function getUser(int $id): User
        {
            return $this->fetchUser($id); // Private method NOT traced
        }
    
        private function fetchUser(int $id): User
        {
            return User::find($id);
        }
    }
    

2. Attribute Reflection Overhead

  • Issue: Scanning classes for attributes at runtime may impact bootstrap performance.
  • Mitigation:
    • Cache the scanned class map in a service provider:
      $this->app->singleton('otel.class.map', function () {
          return AttributeScanner::scan([UserService::class, OrderService::class]);
      });
      
    - Use the Laravel integration to avoid manual scanning.
    
    

3. Argument Serialization Quirks

  • Issue: Complex objects (e.g., closures, resources) may serialize to unexpected values (e.g., "resource").
  • Solution: Exclude problematic arguments or customize serialization:
    #[Arguments(exclude: ['callback'])]
    public function execute(callable $callback): void {}
    

4. Context Propagation Failures

  • Issue: Context may not propagate across service boundaries (e.g., HTTP → Queue).
  • Debugging:
    • Verify traceparent headers are set in HTTP requests.
    • Check queue drivers (e.g., Redis, database) support OTel context propagation.
    • Use OTEL_TRACES_SAMPLER to force sampling for debugging:
      OTEL_TRACES_SAMPLER=AlwaysOn
      

5. Laravel Service Container Conflicts

  • Issue: If the same class is registered multiple times (e.g., via attributes and manual map), spans may duplicate.
  • Fix: Ensure classes are only registered once:
    if (!ClassInstrumentation::isRegistered(UserService::class)) {
        ClassInstrumentation::register($map);
    }
    

Debugging

1. Disable Instrumentation

  • Temporarily disable tracing for testing:
    OTEL_PHP_DISABLED_INSTRUMENTATIONS=class
    
    Or programmatically:
    putenv('OTEL_PHP_DISABLED_INSTRUMENTATIONS=class');
    

2. Verify Span Generation

  • Check if spans appear in your OTel backend (e.g., Jaeger):
    docker run -d -p 16686:16686 jaegertracing/all-in-one:1.35
    
    Then query for spans with names like UserService::createUser.

3

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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky