Skip to content

Commit

Permalink
Test Opentracing with different frameworks (#256)
Browse files Browse the repository at this point in the history
* Test Opentracing with different frameworks

* Follow official API and make use of tracer provider

* Tracing in different framework
  • Loading branch information
dgafka authored Oct 31, 2023
1 parent d198913 commit 35383ca
Show file tree
Hide file tree
Showing 14 changed files with 415 additions and 75 deletions.
166 changes: 166 additions & 0 deletions Monorepo/CrossModuleTests/Tests/Tracing/TracingStackTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<?php

declare(strict_types=1);

namespace Monorepo\CrossModuleTests\Tests\Tracing;

use Ecotone\Messaging\Config\ConfiguredMessagingSystem;
use Ecotone\Messaging\Config\ModulePackageList;
use Ecotone\Modelling\CommandBus;
use Ecotone\Modelling\QueryBus;
use Illuminate\Foundation\Http\Kernel as LaravelKernel;
use Monorepo\CrossModuleTests\Tests\FullAppTestCase;
use Monorepo\ExampleApp\Common\Domain\Notification\NotificationSubscriber;
use Monorepo\ExampleApp\Common\Domain\Order\Command\PlaceOrder;
use Monorepo\ExampleApp\Common\Domain\Order\Order;
use Monorepo\ExampleApp\Common\Domain\Order\ShippingAddress;
use Monorepo\ExampleApp\Common\Infrastructure\Configuration;
use Monorepo\ExampleApp\Common\Infrastructure\Output;
use Monorepo\ExampleApp\ExampleAppCaseTrait;
use OpenTelemetry\SDK\Trace\SpanExporter\InMemoryExporter;
use Psr\Container\ContainerInterface;
use Test\Ecotone\OpenTelemetry\Integration\TracingTest;

final class TracingStackTest extends FullAppTestCase
{
use ExampleAppCaseTrait;

public static function skippedPackages(): array
{
return ModulePackageList::allPackagesExcept([
ModulePackageList::ASYNCHRONOUS_PACKAGE,
ModulePackageList::TRACING_PACKAGE
]);
}

public function executeForSymfony(ContainerInterface $container, \Symfony\Component\HttpKernel\Kernel $kernel): void
{
$configuration = $container->get(Configuration::class);
/** @var QueryBus $queryBus */
$queryBus = $container->get(QueryBus::class);
$commandBus = $container->get(CommandBus::class);
/** @var InMemoryExporter $exporter */
$exporter = $container->get(InMemoryExporter::class);

$this->placeOrder($commandBus, $configuration);
self::runConsumerForSymfony('notifications', $kernel);
$this->assertCount(1, $queryBus->sendWithRouting('getMessages'));

$this->assertTracing($exporter);
}

public function executeForLaravel(ContainerInterface $container, LaravelKernel $kernel): void
{
$configuration = $container->get(Configuration::class);
/** @var QueryBus $queryBus */
$queryBus = $container->get(QueryBus::class);
$commandBus = $container->get(CommandBus::class);
/** @var InMemoryExporter $exporter */
$exporter = $container->get(InMemoryExporter::class);

$this->placeOrder($commandBus, $configuration);
self::runConsumerForLaravel('notifications');
$this->assertCount(1, $queryBus->sendWithRouting('getMessages'));

$this->assertTracing($exporter);
}

public function executeForLiteApplication(ContainerInterface $container): void
{
$configuration = $container->get(Configuration::class);
/** @var QueryBus $queryBus */
$queryBus = $container->get(QueryBus::class);
/** @var ConfiguredMessagingSystem $messagingSystem */
$messagingSystem = $container->get(ConfiguredMessagingSystem::class);
/** @var InMemoryExporter $exporter */
$exporter = $messagingSystem->getServiceFromContainer(InMemoryExporter::class);

$this->placeOrder($messagingSystem->getCommandBus(), $configuration);
self::runConsumerForMessaging('notifications', $messagingSystem);
$this->assertCount(1, $queryBus->sendWithRouting('getMessages'));

$this->assertTracing($exporter);
}

public function executeForLite(ConfiguredMessagingSystem $messagingSystem): void
{
/** @var Configuration $configuration */
$configuration = $messagingSystem->getServiceFromContainer(Configuration::class);
/** @var QueryBus $queryBus */
$queryBus = $messagingSystem->getServiceFromContainer(QueryBus::class);
/** @var InMemoryExporter $exporter */
$exporter = $messagingSystem->getServiceFromContainer(InMemoryExporter::class);

$this->placeOrder($messagingSystem->getCommandBus(), $configuration);
self::runConsumerForMessaging('notifications', $messagingSystem);
$this->assertCount(1, $queryBus->sendWithRouting('getMessages'));

$this->assertTracing($exporter);
}

private function placeOrder(mixed $commandBus, Configuration $configuration): void
{
$commandBus->send(
new PlaceOrder(
\Ramsey\Uuid\Uuid::uuid4(),
$configuration->userId(),
new ShippingAddress(
'Washington',
'15',
'81-221',
'Netherlands'
),
$configuration->productId()
)
);
}

private function assertTracing(InMemoryExporter $exporter): void
{
TracingTest::compareTreesByDetails(
[
[
'details' => ['name' => 'Command Bus'],
'children' => [
[
'details' => ['name' => 'Command Handler: ' . Order::class . '::create'],
'children' => []
],
[
'details' => ['name' => 'Event Bus'],
'children' => []
],
[
'details' => ['name' => 'Sending to Channel: delivery'],
'children' => []
],
[
'details' => ['name' => 'Sending to Channel: notifications'],
'children' => [
[
'details' => ['name' => 'Receiving from channel: notifications'],
'children' => [
[
'details' => ['name' => 'Event Handler: ' . NotificationSubscriber::class . '::whenOrderWasPlaced'],
'children' => []
]
]
]
]
]
]
],
[
'details' => ['name' => 'Query Bus'],
'children' => [
[
'details' => ['name' => 'Query Handler: ' . Output::class . '::getMessages'],
'children' => []
]
]
]
],
TracingTest::buildTree($exporter)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
use Monorepo\ExampleApp\Common\Infrastructure\StubShippingService;
use Monorepo\ExampleApp\Common\Infrastructure\SystemClock;
use Monorepo\ExampleApp\Common\UI\OrderController;
use OpenTelemetry\API\Trace\TracerProviderInterface;
use OpenTelemetry\SDK\Trace\SpanExporter\InMemoryExporter;
use Psr\Log\LoggerInterface;
use Test\Ecotone\OpenTelemetry\Integration\TracingTest;

class AppServiceProvider extends ServiceProvider
{
Expand Down Expand Up @@ -61,6 +64,12 @@ public function register(): void
$configuration = $app->make(Configuration::class);
return $configuration->productRepository();
});

$this->app->singleton(InMemoryExporter::class, fn() => new InMemoryExporter());
$this->app->singleton(TracerProviderInterface::class, function (Application $app) {
$exporter = $app->make(InMemoryExporter::class);
return TracingTest::prepareTracer($exporter);
});
}

/**
Expand Down
7 changes: 7 additions & 0 deletions Monorepo/ExampleApp/Lite/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,18 @@
use Monorepo\ExampleApp\Common\Infrastructure\StubNotificationSender;
use Monorepo\ExampleApp\Common\Infrastructure\StubShippingService;
use Monorepo\ExampleApp\Common\Infrastructure\SystemClock;
use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\API\Trace\TracerProviderInterface;
use OpenTelemetry\SDK\Trace\SpanExporter\InMemoryExporter;
use Test\Ecotone\OpenTelemetry\Integration\TracingTest;

return function (bool $useCachedVersion = true): ConfiguredMessagingSystem {
$output = new Output();

$configuration = new Configuration();
$stubShippingService = new StubShippingService($output, $configuration);
$stubNotificationSender = new StubNotificationSender($output, $configuration);
$exporter = new InMemoryExporter(new ArrayObject());

$services = [
Configuration::class => $configuration,
Expand All @@ -45,6 +50,8 @@
InMemoryOrderRepository::class => new InMemoryOrderRepository(),
InMemoryProductRepository::class => $configuration->productRepository(),
InMemoryUserRepository::class => $configuration->userRepository(),
InMemoryExporter::class => $exporter,
TracerProviderInterface::class => TracingTest::prepareTracer($exporter)
];
return EcotoneLite::bootstrap(
containerOrAvailableServices: $services,
Expand Down
8 changes: 7 additions & 1 deletion Monorepo/ExampleApp/LiteApplication/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@
use Monorepo\ExampleApp\Common\Infrastructure\StubNotificationSender;
use Monorepo\ExampleApp\Common\Infrastructure\StubShippingService;
use Monorepo\ExampleApp\Common\Infrastructure\SystemClock;
use OpenTelemetry\API\Trace\TracerProviderInterface;
use OpenTelemetry\SDK\Trace\SpanExporter\InMemoryExporter;
use Test\Ecotone\OpenTelemetry\Integration\TracingTest;

return function (bool $useCachedVersion = true): ConfiguredMessagingSystem {
$output = new Output();

$configuration = new Configuration();
$stubNotificationSender = new StubNotificationSender($output, $configuration);
$stubShippingService = new StubShippingService($output, $configuration);
$exporter = new InMemoryExporter(new ArrayObject());

$services = [
Configuration::class => $configuration,
Expand All @@ -38,7 +42,9 @@
ShippingSubscriber::class => new ShippingSubscriber($stubShippingService),
NotificationSubscriber::class => new NotificationSubscriber($stubNotificationSender),
Output::class => $output,
ErrorChannelService::class => new ErrorChannelService()
ErrorChannelService::class => new ErrorChannelService(),
InMemoryExporter::class => $exporter,
TracerProviderInterface::class => TracingTest::prepareTracer($exporter)
];

return EcotoneLiteApplication::bootstrap(
Expand Down
10 changes: 10 additions & 0 deletions Monorepo/ExampleApp/Symfony/config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
use Monorepo\ExampleApp\Common\Infrastructure\Authentication\AuthenticationService;
use Monorepo\ExampleApp\Common\Infrastructure\Configuration;
use Monorepo\ExampleApp\Common\UI\OrderController;
use OpenTelemetry\API\Trace\TracerProviderInterface;
use OpenTelemetry\SDK\Trace\SpanExporter\InMemoryExporter;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Test\Ecotone\OpenTelemetry\Integration\TracingTest;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;

return static function (ContainerConfigurator $containerConfigurator): void {
Expand All @@ -31,4 +34,11 @@
$services->set(UserRepository::class)->factory([service(Configuration::class), 'userRepository']);
$services->set(ProductRepository::class)->factory([service(Configuration::class), 'productRepository']);
$services->get(AuthenticationService::class)->factory([service(Configuration::class), 'authentication']);

$services->set(InMemoryExporter::class, InMemoryExporter::class)
->public();
$services->set(TracerProviderInterface::class)
->factory([TracingTest::class, 'prepareTracer'])
->args([service(InMemoryExporter::class)])
->public();
};
6 changes: 5 additions & 1 deletion packages/Ecotone/src/Messaging/MessageHeaders.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ final class MessageHeaders

public const CHANNEL_SEND_RETRY_NUMBER = 'channelSendRetryNumber';

/** This is needed for tracing, to pass context around within same process */
public const NON_PROPAGATED_CONTEXT = 'nonPropagatedContext';

private array $headers;

/**
Expand Down Expand Up @@ -239,7 +242,8 @@ public static function unsetEnqueueMetadata(array $metadata): array
$metadata[self::CONSUMER_ACK_HEADER_LOCATION],
$metadata[self::POLLED_CHANNEL_NAME],
$metadata[self::CONSUMER_POLLING_METADATA],
$metadata[self::REPLY_CHANNEL]
$metadata[self::REPLY_CHANNEL],
$metadata[self::NON_PROPAGATED_CONTEXT]
);

return $metadata;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Ecotone\OpenTelemetry\TracerInterceptor;
use Ecotone\OpenTelemetry\TracingChannelAdapterBuilder;
use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\API\Trace\TracerProviderInterface;
use Psr\Log\LoggerInterface;

#[ModuleAnnotation]
Expand All @@ -46,7 +47,7 @@ public function prepare(Configuration $messagingConfiguration, array $extensionO
$messagingConfiguration->registerServiceDefinition(
TracerInterceptor::class,
new Definition(TracerInterceptor::class, [
new Reference(TracerInterface::class),
new Reference(TracerProviderInterface::class),
new Reference(LoggerInterface::class),
])
);
Expand Down
13 changes: 11 additions & 2 deletions packages/OpenTelemetry/src/EcotoneSpanBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@
use OpenTelemetry\API\Trace\SpanBuilderInterface;
use OpenTelemetry\API\Trace\SpanKind;
use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\API\Trace\TracerProviderInterface;

final class EcotoneSpanBuilder
{
public static function create(Message $context, string $traceName, TracerInterface $tracer, int $type = SpanKind::KIND_SERVER): SpanBuilderInterface
const ECOTONE_TRACER_NAME = 'io.opentelemetry.contrib.php';

public static function create(
Message $context,
string $traceName,
TracerProviderInterface $tracerProvider,
int $type = SpanKind::KIND_SERVER
): SpanBuilderInterface
{
$userHeaders = MessageHeaders::unsetAllFrameworkHeaders($context->getHeaders()->headers());

Expand All @@ -23,7 +31,8 @@ public static function create(Message $context, string $traceName, TracerInterfa
}
}

return $tracer
return $tracerProvider
->getTracer(self::ECOTONE_TRACER_NAME)
->spanBuilder($traceName)
->setSpanKind($type)
->setAttribute(MessageHeaders::MESSAGE_ID, $context->getHeaders()->getMessageId())
Expand Down
Loading

0 comments on commit 35383ca

Please sign in to comment.