Skip to content

Commit

Permalink
Merge pull request #1168: add LazyPipeline, improve Telemetry
Browse files Browse the repository at this point in the history
  • Loading branch information
spiralbot committed Nov 29, 2024
1 parent 2a4d253 commit 428eed7
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 37 deletions.
42 changes: 35 additions & 7 deletions src/AbstractTracer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

namespace Spiral\Telemetry;

use Spiral\Core\Attribute\Proxy;
use Spiral\Core\BinderInterface;
use Spiral\Core\Container;
use Spiral\Core\ContainerScope;
use Spiral\Core\InvokerInterface;
use Spiral\Core\ScopeInterface;

Expand All @@ -17,7 +18,7 @@
abstract class AbstractTracer implements TracerInterface
{
public function __construct(
#[Proxy] private readonly ?ScopeInterface $scope = new Container(),
private readonly ?ScopeInterface $scope = new Container(),
) {
}

Expand All @@ -26,10 +27,37 @@ public function __construct(
*/
final protected function runScope(Span $span, callable $callback): mixed
{
// TODO: Can we remove this scope?
return $this->scope->runScope([
SpanInterface::class => $span,
TracerInterface::class => $this,
], static fn (InvokerInterface $invoker): mixed => $invoker->invoke($callback));
$container = ContainerScope::getContainer();
if ($container === null) {
return $this->scope->runScope([
SpanInterface::class => $span,
TracerInterface::class => $this,
], static fn (InvokerInterface $invoker): mixed => $invoker->invoke($callback));
}

if ($container instanceof Container) {
$invoker = $container;
$binder = $container;
} else {
/** @var InvokerInterface $invoker */
$invoker = $container->get(InvokerInterface::class);
/** @var BinderInterface $binder */
$binder = $container->get(BinderInterface::class);
}

try {
$prevSpan = $container->get(SpanInterface::class);
} catch (\Throwable) {
$prevSpan = null;
}

$binder->bindSingleton(SpanInterface::class, $span);
try {
return $invoker->invoke($callback);
} finally {
$prevSpan === null
? $binder->removeBinding(SpanInterface::class)
: $binder->bindSingleton(SpanInterface::class, $prevSpan);
}
}
}
14 changes: 6 additions & 8 deletions src/Bootloader/TelemetryBootloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@
use Spiral\Telemetry\Config\TelemetryConfig;
use Spiral\Telemetry\ConfigTracerFactoryProvider;
use Spiral\Telemetry\Exception\TracerException;
use Spiral\Telemetry\LogTracer;
use Spiral\Telemetry\LogTracerFactory;
use Spiral\Telemetry\NullTracer;
use Spiral\Telemetry\NullTracerFactory;
use Spiral\Telemetry\TracerFactoryInterface;
use Spiral\Telemetry\TracerInterface;
use Spiral\Telemetry\TracerFactoryProviderInterface;
use Spiral\Telemetry\TracerInterface;

final class TelemetryBootloader extends Bootloader
{
Expand All @@ -35,7 +33,7 @@ final class TelemetryBootloader extends Bootloader
];

public function __construct(
private readonly ConfiguratorInterface $config
private readonly ConfiguratorInterface $config,
) {
}

Expand All @@ -51,15 +49,15 @@ public function registerTracer(string $name, string|TracerFactoryInterface|Autow
{
$this->config->modify(
TelemetryConfig::CONFIG,
new Append('drivers', $name, $driver)
new Append('drivers', $name, $driver),
);
}

/**
* @throws TracerException
*/
public function initFactory(
TracerFactoryProviderInterface $tracerProvider
TracerFactoryProviderInterface $tracerProvider,
): TracerFactoryInterface {
return $tracerProvider->getTracerFactory();
}
Expand All @@ -68,7 +66,7 @@ public function initFactory(
* @throws TracerException
*/
public function getTracer(
TracerFactoryInterface $tracerFactory
TracerFactoryInterface $tracerFactory,
): TracerInterface {
return $tracerFactory->make();
}
Expand All @@ -83,7 +81,7 @@ private function initConfig(EnvironmentInterface $env): void
'null' => NullTracerFactory::class,
'log' => LogTracerFactory::class,
],
]
],
);
}
}
2 changes: 1 addition & 1 deletion src/LogTracerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ final class LogTracerFactory implements TracerFactoryInterface
private readonly LoggerInterface $logger;

public function __construct(
#[Proxy] private readonly ScopeInterface $scope,
private readonly ScopeInterface $scope,
private readonly ClockInterface $clock,
LogsInterface $logs,
string $channel = self::LOG_CHANNEL
Expand Down
2 changes: 1 addition & 1 deletion src/NullTracerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
final class NullTracerFactory implements TracerFactoryInterface
{
public function __construct(
#[Proxy] private readonly ?ScopeInterface $scope = new Container(),
private readonly ?ScopeInterface $scope = new Container(),
) {
}

Expand Down
20 changes: 9 additions & 11 deletions tests/LogTracerFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Spiral\Tests\Telemetry;

use Mockery as m;
use PHPUnit\Framework\Attributes\RunInSeparateProcess;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Spiral\Core\ScopeInterface;
Expand All @@ -15,26 +15,24 @@

final class LogTracerFactoryTest extends TestCase
{
use m\Adapter\Phpunit\MockeryPHPUnitIntegration;

public function testMake(): void
{
$logs = m::mock(LogsInterface::class);
$logs = $this->createMock(LogsInterface::class);

$logs->shouldReceive('getLogger')->once()
$logs->expects($this->once())
->method('getLogger')
->with('some-channel')
->andReturn($logger = m::mock(LoggerInterface::class));
->willReturn($logger = $this->createMock(LoggerInterface::class));

$factory = new LogTracerFactory(
$scope = m::mock(ScopeInterface::class),
$clock = m::mock(ClockInterface::class),
$scope = $this->createMock(ScopeInterface::class),
$clock = $this->createMock(ClockInterface::class),
$logs,
'some-channel'
);

$clock->shouldReceive('now');
$scope->shouldReceive('runScope')->once();
$logger->shouldReceive('debug')->once();
$clock->expects($this->any())->method('now');
$logger->expects($this->once())->method('debug');

$this->assertInstanceOf(LogTracer::class, $tracer = $factory->make());

Expand Down
2 changes: 2 additions & 0 deletions tests/Monolog/TelemetryProcessorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
namespace Spiral\Tests\Telemetry\Monolog;

use Mockery as m;
use PHPUnit\Framework\Attributes\RunClassInSeparateProcess;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Spiral\Telemetry\Monolog\TelemetryProcessor;
use Spiral\Telemetry\TracerInterface;

#[RunClassInSeparateProcess]
final class TelemetryProcessorTest extends TestCase
{
use m\Adapter\Phpunit\MockeryPHPUnitIntegration;
Expand Down
12 changes: 4 additions & 8 deletions tests/NullTracerFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Spiral\Tests\Telemetry;

use Mockery as m;
use PHPUnit\Framework\Attributes\RunInSeparateProcess;
use PHPUnit\Framework\TestCase;
use Spiral\Core\ScopeInterface;
use Spiral\Telemetry\NullTracer;
Expand All @@ -14,16 +15,11 @@ final class NullTracerFactoryTest extends TestCase
{
use m\Adapter\Phpunit\MockeryPHPUnitIntegration;

#[RunInSeparateProcess]
public function testMake(): void
{
$factory = new NullTracerFactory(
$scope = m::mock(ScopeInterface::class)
);
$factory = new NullTracerFactory(m::mock(ScopeInterface::class));

$scope->shouldReceive('runScope')->once();

$this->assertInstanceOf(NullTracer::class, $tracer = $factory->make());

$tracer->trace('foo', fn() => 'hello');
$this->assertInstanceOf(NullTracer::class, $factory->make());
}
}
44 changes: 43 additions & 1 deletion tests/NullTracerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
namespace Spiral\Tests\Telemetry;

use Mockery as m;
use PHPUnit\Framework\Attributes\RunInSeparateProcess;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Spiral\Core\BinderInterface;
use Spiral\Core\ContainerScope;
use Spiral\Core\InvokerInterface;
use Spiral\Core\ScopeInterface;
use Spiral\Telemetry\NullTracer;
Expand All @@ -16,7 +20,8 @@ final class NullTracerTest extends TestCase
{
use m\Adapter\Phpunit\MockeryPHPUnitIntegration;

public function testTrace(): void
#[RunInSeparateProcess]
public function testFallbackRunScope(): void
{
$tracer = new NullTracer(
$scope = m::mock(ScopeInterface::class)
Expand All @@ -43,4 +48,41 @@ public function testTrace(): void
$tracer->trace('foo', $callable, ['foo' => 'bar'])
);
}

#[RunInSeparateProcess]
public function testWithScopedContainer(): void
{
$tracer = new NullTracer(
$scope = m::mock(ScopeInterface::class)
);

$invoker = m::mock(InvokerInterface::class);
$binder = m::mock(BinderInterface::class);
$container = m::mock(ContainerInterface::class);
$container->expects('get')
->with(InvokerInterface::class)
->andReturn($invoker);
$container->expects('get')
->with(BinderInterface::class)
->andReturn($binder);

$callable = fn() => 'hello';

$invoker->shouldReceive('invoke')
->once()
->with($callable)
->andReturn('hello');
$binder->shouldReceive('bindSingleton')
->once();
$binder->shouldReceive('removeBinding')
->with(SpanInterface::class);
$scope->shouldNotReceive('runScope');

ContainerScope::runScope($container, function () use ($tracer, $callable) {
$this->assertSame(
'hello',
$tracer->trace('foo', $callable, ['foo' => 'bar'])
);
});
}
}

0 comments on commit 428eed7

Please sign in to comment.