opentelemetry-php icon indicating copy to clipboard operation
opentelemetry-php copied to clipboard

[opentelemetry-php-contrib] Symfony OtelSdkBundle integration error

Open michael-paktolus opened this issue 2 years ago • 5 comments

I did setup based on this documention: https://github.com/open-telemetry/opentelemetry-php-contrib/blob/main/src/Symfony/src/OtelSdkBundle/README.md and got an error: App\EventListener\TracingKernelSubscriber::__construct(): Argument #1 ($provider) must be of type OpenTelemetry\SDK\Trace\TracerProvider, OpenTelemetry\Contrib\Symfony\OtelSdkBundle\Debug\TraceableTracerProvider given

michael-paktolus avatar Sep 24 '23 19:09 michael-paktolus

Can you please try changing the type-hint in the readme example to:

public function __construct( \OpenTelemetry\SDK\Trace\TracerProviderInterface $provider)

brettmc avatar Sep 25 '23 00:09 brettmc

Can you please try changing the type-hint in the readme example to:

public function __construct( \OpenTelemetry\SDK\Trace\TracerProviderInterface $provider)

Thank you for your suggestion. I have forgot to mention that have Symfony 5.4.22 After this change I started receive next error for all requests:

"User Notice: Scope: missing call to Scope::detach() for scope #1222, created \n\tat OpenTelemetry.Context.Context.activate(Context.php:84)\n\tat OpenTelemetry.API.Trace.Span.activate(Span.php:51)\n\tat App.EventListener.TracingKernelSubscriber.onRequestEvent(TracingKernelSubscriber.php:31)\n\tat Symfony.Component.EventDispatcher.Debug.WrappedListener.__invoke(WrappedListener.php:118)\n\tat Symfony.Component.EventDispatcher.EventDispatcher.callListeners(EventDispatcher.php:230)\n\tat Symfony.Component.EventDispatcher.EventDispatcher.dispatch(EventDispatcher.php:59)\n\tat Symfony.Component.EventDispatcher.Debug.TraceableEventDispatcher.dispatch(TraceableEventDispatcher.php:154)\n\tat Symfony.Component.HttpKernel.HttpKernel.handleRaw(HttpKernel.php:139)\n\tat Symfony.Component.HttpKernel.HttpKernel.handle(HttpKernel.php:75)\n\tat Symfony.Component.HttpKernel.Kernel.handle(Kernel.php:202)\n\tat Symfony.Component.Runtime.Runner.Symfony.HttpKernelRunner.run(HttpKernelRunner.php:35)\n\tat require_once(autoload_runtime.php:35)\n\tat {main}(index.php:5)\n"

and saw next Traces in Jaeger UI:

/api/services
/api/traces
/api/services/{service}/operations

but no Traces for my endpoints

michael-paktolus avatar Sep 25 '23 07:09 michael-paktolus

No problem. I can take a pretty good guess at what's wrong next. Change the TracingKernelSubscriber to:

<?php

namespace App\EventSubscriber;

use OpenTelemetry\API\Trace\SpanInterface;
use OpenTelemetry\Context\ScopeInterface;
use OpenTelemetry\SDK\Trace\TracerProvider;
use OpenTelemetry\SDK\Trace\TracerProviderInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\TerminateEvent;
use Symfony\Component\HttpKernel\KernelEvents;

class TracingKernelSubscriber implements EventSubscriberInterface
{
    private TracerProvider $provider;
    private ?SpanInterface $mainSpan = null;
    private ?ScopeInterface $scope = null;

    public function __construct(TracerProviderInterface $provider)
    {
        // store a reference to the TracerProvider in case we want to create
        // more spans on different events (not covered in this example)
        $this->provider = $provider;
    }

    public function onRequestEvent(RequestEvent $event)
    {
        // Create our main span and activate it
        $this->mainSpan = $this->provider
            ->getTracer('io.opentelemetry.contrib.php')
            ->spanBuilder('main')
            ->startSpan();
        $this->scope = $this->mainSpan->activate();
    }

    public function onTerminateEvent(TerminateEvent $event): void
    {
        // end our main span once the request has been processed and the kernel terminates.
        $this->mainSpan->end();
        $this->scope->detach();
    }

    public static function getSubscribedEvents(): array
    {
        // return the subscribed events, their methods and priorities
        // use a very high integer for the Request priority and a
        // very low negative integer for the Terminate priority, so the listener
        // will be the first and last one to be called respectively.
        return [
            KernelEvents::REQUEST => [['onRequestEvent', 10000]],
            KernelEvents::TERMINATE => [['onTerminateEvent', -10000]],
        ];
    }
}

Note that we keep track of the scope when activating the root span, and detach it when finished.

brettmc avatar Sep 25 '23 07:09 brettmc

Thanks a lot!. The error disappear, but still no traces for my endpoints (I have expected they should be added automatically when I request any endpoint). So, I have added span in Controller based on documentation https://github.com/open-telemetry/opentelemetry-php-contrib/blob/main/src/Symfony/src/OtelSdkBundle/README.md#31-create-sub-spans-in-the-controller and got Cannot autowire service "App\Controller\TestController": argument "$tracer" of method "__construct()" references class "OpenTelemetry\SDK\Trace\Tracer" but no such service exists.

michael-paktolus avatar Sep 25 '23 08:09 michael-paktolus

I'm not very familiar with either Symfony or the sdk bundle, but here's what I'd try. It looks like TracerProviderInterface is configured as a service. So, change your parameter to TracerProviderInterface $tracerProvider, then in the body, $tracer = $tracerProvider->getTracer(/*some params*/). It's definitely not the "right way" though.

You might also like to try to use a console logger to simplify your setup, it's a good way to tell if spans are actually being generated.

It's sounding like we need somebody who understands Symfony to test out this documentation.

brettmc avatar Sep 26 '23 00:09 brettmc