Skip to content

Commit

Permalink
feat(extension/trace): implement twig instrumentation
Browse files Browse the repository at this point in the history
  • Loading branch information
gaelreyrol committed Jan 7, 2024
1 parent 5a978ab commit 48200c5
Show file tree
Hide file tree
Showing 18 changed files with 324 additions and 5 deletions.
8 changes: 7 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
"ext-opentelemetry": "*",
"ext-xdebug": "*",
"doctrine/dbal": "^3.7",
"doctrine/doctrine-bundle": "^2.11",
"doctrine/orm": "^2.17",
"friendsofphp/php-cs-fixer": "^3.41",
"guzzlehttp/promises": "^2.0",
"matthiasnoback/symfony-config-test": "^5.1",
Expand All @@ -79,7 +81,9 @@
"symfony/http-kernel": "^6.4 || ^7.0",
"symfony/monolog-bundle": "^3.10",
"symfony/phpunit-bridge": "^6.4 || ^7.0",
"symfony/yaml": "^6.4 || ^7.0"
"symfony/twig-bundle": "^7.0",
"symfony/yaml": "^6.4 || ^7.0",
"twig/twig": "^3.8"
},
"config": {
"allow-plugins": {
Expand All @@ -93,6 +97,8 @@
"symfony/console": "Needed to enable Symfony HttpKernel instrumentation",
"symfony/http-kernel": "Needed to enable Symfony Console instrumentation",
"symfony/monolog-bundle": "Needed to register OpenTelemetry handler in Symfony Monolog service",
"doctrine/orm": "Needed to enable Doctrine ORM instrumentation",
"doctrine/dbal": "Needed to enable Doctrine DBAL instrumentation",
"open-telemetry/exporter-otlp": "Needed to export OpenTelemetry data via OTPL",
"open-telemetry/exporter-zipkin": "Needed to export OpenTelemetry data via Zipkin",
"open-telemetry/transport-grpc": "Needed to export OpenTelemetry data via gRPC",
Expand Down
8 changes: 8 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ private function addInstrumentationSection(ArrayNodeDefinition $node): void
->append($this->getMeteringInstrumentationNode())
->end()
->end()
->arrayNode('twig')
->addDefaultsIfNotSet()
->canBeEnabled()
->children()
->append($this->getTracingInstrumentationNode())
->append($this->getMeteringInstrumentationNode())
->end()
->end()
->end()
->end()
;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\ExtensionLoader\Instrumentation;

use Doctrine\DBAL\Driver\Middleware;
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;

final class DoctrineInstrumentationExtensionLoader extends AbstractInstrumentationExtensionLoader
{
Expand All @@ -13,9 +13,9 @@ public function __construct()

protected function assertInstrumentationCanHappen(): void
{
/* if (!class_exists(Middleware::class)) {
throw new \LogicException('To configure the Doctrine instrumentation, you must first install the doctrine/dbal package.');
}*/
if (!class_exists(DoctrineBundle::class)) {
throw new \LogicException('To configure the Doctrine instrumentation, you must first install the doctrine/doctrine-bundle package.');
}
}

protected function setTracingDefinitions(): void
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\ExtensionLoader\Instrumentation;

use Symfony\Bundle\TwigBundle\TwigBundle;

final class TwigInstrumentationExtensionLoader extends AbstractInstrumentationExtensionLoader
{
public function __construct()
{
parent::__construct('twig');
}

protected function assertInstrumentationCanHappen(): void
{
if (!class_exists(TwigBundle::class)) {
throw new \LogicException('To configure the Twig instrumentation, you must first install the symfony/twig-bundle package.');
}
}

protected function setTracingDefinitions(): void
{
$this->container
->getDefinition('open_telemetry.instrumentation.twig.trace.extension')
->addTag('twig.extension')
->setArgument('$tracer', $this->getInstrumentationTracerOrDefaultTracer());
}

protected function setMeteringDefinitions(): void
{
return;
}
}
2 changes: 2 additions & 0 deletions src/DependencyInjection/OpenTelemetryExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\ExtensionLoader\Instrumentation\ConsoleInstrumentationExtensionLoader;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\ExtensionLoader\Instrumentation\DoctrineInstrumentationExtensionLoader;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\ExtensionLoader\Instrumentation\HttpKernelInstrumentationExtensionLoader;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\ExtensionLoader\Instrumentation\TwigInstrumentationExtensionLoader;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\ExtensionLoader\LogsExtensionLoader;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\ExtensionLoader\MetricsExtensionLoader;
use FriendsOfOpenTelemetry\OpenTelemetryBundle\DependencyInjection\ExtensionLoader\TracesExtensionLoader;
Expand Down Expand Up @@ -36,6 +37,7 @@ protected function loadInternal(array $mergedConfig, ContainerBuilder $container
(new HttpKernelInstrumentationExtensionLoader())->load($mergedConfig, $container);
(new ConsoleInstrumentationExtensionLoader())->load($mergedConfig, $container);
(new DoctrineInstrumentationExtensionLoader())->load($mergedConfig, $container);
(new TwigInstrumentationExtensionLoader())->load($mergedConfig, $container);
}

/**
Expand Down
18 changes: 18 additions & 0 deletions src/EventListener/Doctrine/Trace/OnClearListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\EventListener\Doctrine\Trace;

use Doctrine\ORM\Event\OnClearEventArgs;
use OpenTelemetry\API\Trace\TracerInterface;

class OnClearListener
{
public function __construct(
private readonly TracerInterface $tracer,
) {
}

public function onClear(OnClearEventArgs $args): void
{
}
}
18 changes: 18 additions & 0 deletions src/EventListener/Doctrine/Trace/OnFlushListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\EventListener\Doctrine\Trace;

use Doctrine\ORM\Event\OnFlushEventArgs;
use OpenTelemetry\API\Trace\TracerInterface;

class OnFlushListener
{
public function __construct(
private readonly TracerInterface $tracer,
) {
}

public function onFlush(OnFlushEventArgs $args): void
{
}
}
18 changes: 18 additions & 0 deletions src/EventListener/Doctrine/Trace/PostFlushListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\EventListener\Doctrine\Trace;

use Doctrine\ORM\Event\PostFlushEventArgs;
use OpenTelemetry\API\Trace\TracerInterface;

class PostFlushListener
{
public function __construct(
private readonly TracerInterface $tracer,
) {
}

public function postFlush(PostFlushEventArgs $args): void
{
}
}
18 changes: 18 additions & 0 deletions src/EventListener/Doctrine/Trace/PostLoadListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\EventListener\Doctrine\Trace;

use Doctrine\ORM\Event\PostLoadEventArgs;
use OpenTelemetry\API\Trace\TracerInterface;

class PostLoadListener
{
public function __construct(
private readonly TracerInterface $tracer,
) {
}

public function postLoad(PostLoadEventArgs $args): void
{
}
}
18 changes: 18 additions & 0 deletions src/EventListener/Doctrine/Trace/PostPersistListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\EventListener\Doctrine\Trace;

use Doctrine\ORM\Event\PostPersistEventArgs;
use OpenTelemetry\API\Trace\TracerInterface;

class PostPersistListener
{
public function __construct(
private readonly TracerInterface $tracer,
) {
}

public function postPersist(PostPersistEventArgs $args): void
{
}
}
18 changes: 18 additions & 0 deletions src/EventListener/Doctrine/Trace/PostRemoveListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\EventListener\Doctrine\Trace;

use Doctrine\ORM\Event\PostRemoveEventArgs;
use OpenTelemetry\API\Trace\TracerInterface;

class PostRemoveListener
{
public function __construct(
private readonly TracerInterface $tracer,
) {
}

public function postRemove(PostRemoveEventArgs $args): void
{
}
}
18 changes: 18 additions & 0 deletions src/EventListener/Doctrine/Trace/PostUpdateListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\EventListener\Doctrine\Trace;

use Doctrine\ORM\Event\PostUpdateEventArgs;
use OpenTelemetry\API\Trace\TracerInterface;

class PostUpdateListener
{
public function __construct(
private readonly TracerInterface $tracer,
) {
}

public function postUpdate(PostUpdateEventArgs $args): void
{
}
}
18 changes: 18 additions & 0 deletions src/EventListener/Doctrine/Trace/PreFlushListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\EventListener\Doctrine\Trace;

use Doctrine\ORM\Event\PreFlushEventArgs;
use OpenTelemetry\API\Trace\TracerInterface;

class PreFlushListener
{
public function __construct(
private readonly TracerInterface $tracer,
) {
}

public function preFlush(PreFlushEventArgs $args): void
{
}
}
18 changes: 18 additions & 0 deletions src/EventListener/Doctrine/Trace/PrePersistListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\EventListener\Doctrine\Trace;

use Doctrine\ORM\Event\PrePersistEventArgs;
use OpenTelemetry\API\Trace\TracerInterface;

class PrePersistListener
{
public function __construct(
private readonly TracerInterface $tracer,
) {
}

public function prePersist(PrePersistEventArgs $args): void
{
}
}
18 changes: 18 additions & 0 deletions src/EventListener/Doctrine/Trace/PreRemoveListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\EventListener\Doctrine\Trace;

use Doctrine\ORM\Event\PreRemoveEventArgs;
use OpenTelemetry\API\Trace\TracerInterface;

class PreRemoveListener
{
public function __construct(
private readonly TracerInterface $tracer,
) {
}

public function preRemove(PreRemoveEventArgs $args): void
{
}
}
18 changes: 18 additions & 0 deletions src/EventListener/Doctrine/Trace/PreUpdateListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\EventListener\Doctrine\Trace;

use Doctrine\ORM\Event\PreUpdateEventArgs;
use OpenTelemetry\API\Trace\TracerInterface;

class PreUpdateListener
{
public function __construct(
private readonly TracerInterface $tracer,
) {
}

public function preRemove(PreUpdateEventArgs $args): void
{
}
}
69 changes: 69 additions & 0 deletions src/Extension/Twig/Trace/TwigTraceExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\Extension\Twig\Trace;

use OpenTelemetry\API\Trace\Span;
use OpenTelemetry\API\Trace\SpanKind;
use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\Context\Context;
use Twig\Extension\AbstractExtension;
use Twig\Profiler\NodeVisitor\ProfilerNodeVisitor;
use Twig\Profiler\Profile;

class TwigTraceExtension extends AbstractExtension
{
/**
* @var \SplObjectStorage<Profile, Span>
*/
private \SplObjectStorage $spans;

public function __construct(
private readonly TracerInterface $tracer,
) {
$this->spans = new \SplObjectStorage();
}

public function enter(Profile $profile): void
{
$spanBuilder = $this->tracer
->spanBuilder($this->getSpanName($profile))
->setSpanKind(SpanKind::KIND_SERVER)
;

$parent = Context::getCurrent();

$span = $spanBuilder->setParent($parent)->startSpan();

$this->spans[$profile] = $span;
}

public function leave(Profile $profile): void
{
if (!isset($this->spans[$profile])) {
return;
}
$this->spans[$profile]->end();
unset($this->spans[$profile]);
}

public function getNodeVisitors(): array
{
return [
new ProfilerNodeVisitor(self::class),
];
}

private function getSpanName(Profile $profile): string
{
switch (true) {
case $profile->isRoot():
return $profile->getName();

case $profile->isTemplate():
return $profile->getTemplate();

default:
return sprintf('%s::%s(%s)', $profile->getTemplate(), $profile->getType(), $profile->getName());
}
}
}
Loading

0 comments on commit 48200c5

Please sign in to comment.