Skip to content

Commit

Permalink
Add CommandCollector (#54)
Browse files Browse the repository at this point in the history
  • Loading branch information
RobinHoutevelts authored Jul 3, 2024
1 parent a3aa663 commit bd6c014
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 0 deletions.
7 changes: 7 additions & 0 deletions config/xray.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@
*/
'view' => env('XRAY_VIEW', true),

/*
|--------------------------------------------------------------------------
| Trace Commands
|--------------------------------------------------------------------------
*/
'command' => env('XRAY_COMMAND', true),

/*
|--------------------------------------------------------------------------
| Trace Routes
Expand Down
36 changes: 36 additions & 0 deletions src/Collectors/CommandCollector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Napp\Xray\Collectors;

use Illuminate\Console\Events\CommandFinished;
use Illuminate\Console\Events\CommandStarting;
use Napp\Xray\Segments\JobSegment;

class CommandCollector extends EventsCollector
{
public function registerEventListeners(): void
{
$this->app['events']->listen(CommandStarting::class, function (CommandStarting $event) {
if ($this->app->runningInConsole()) {
$this->initCliTracer($event->command);
}
$name = 'Command ' . $event->command;

$this->addCustomSegment(
(new JobSegment())->setName($name)->setPayload(['arguments' => $event->input->getArguments(), 'options' => $event->input->getOptions()]),
$name,
);
});

$this->app['events']->listen(CommandFinished::class, function (CommandFinished $event) {
$name = 'Command ' . $event->command;
if ($this->hasAddedSegment($name)) {
$this->getSegment($name)->setResult($event->exitCode === 0);
$this->endSegment($name);
$this->submitCliTracer();
}
});
}
}
5 changes: 5 additions & 0 deletions src/XrayServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Illuminate\Support\ServiceProvider;
use Napp\Xray\Collectors\CacheCollector;
use Napp\Xray\Collectors\CommandCollector;
use Napp\Xray\Collectors\DatabaseQueryCollector;
use Napp\Xray\Collectors\FrameworkCollector;
use Napp\Xray\Collectors\JobCollector;
Expand Down Expand Up @@ -65,6 +66,10 @@ protected function registerCollectors(): void
app(JobCollector::class);
}

if (config('xray.command')) {
app(CommandCollector::class);
}

if (config('xray.view')) {
app(ViewCollector::class);
}
Expand Down
96 changes: 96 additions & 0 deletions tests/Collectors/CommandCollectorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

namespace Napp\Xray\Tests\Collectors;

use Illuminate\Config\Repository;
use Illuminate\Console\Events\CommandFinished;
use Illuminate\Console\Events\CommandStarting;
use Illuminate\Container\Container;
use Illuminate\Foundation\Application;
use Napp\Xray\Collectors\CommandCollector;
use Napp\Xray\Segments\Trace;
use Pkerrigan\Xray\Segment;
use Pkerrigan\Xray\Submission\SegmentSubmitter;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;

class CommandCollectorTest extends TestCase
{
public function test_it_creates_segment() {
// given a mock implementation of the Application Object
$mockApplication = new CommandCollectorTestMockApplication();
$mockApplication->bind('config', function() {
return new Repository([
'xray' => [
'enabled' => true,
'submitter' => CommandCollectorSegmentSubmitter::class,
],
]);
});
Container::setInstance($mockApplication);
CommandCollectorSegmentSubmitter::$submittedSegments = [];

// given a CommandCollector object
$commandCollector = new CommandCollector($mockApplication);
// with a tracer that forces sampling
$commandCollector->tracer()->setSampled(true);

// and the events our collector listens to
$startedEvent = new CommandStarting("foobar", new ArrayInput([]), new NullOutput());
$finishedEvent = new CommandFinished("foobar", new ArrayInput([]), new NullOutput(), 0);

// after dispatching the events on the mock application
$mockApplication->events->dispatch($startedEvent);
$mockApplication->events->dispatch($finishedEvent);

// then a trace should have been submitted
$this->assertCount(1, CommandCollectorSegmentSubmitter::$submittedSegments);
$trace = json_decode(json_encode(CommandCollectorSegmentSubmitter::$submittedSegments[0]), true);

// with a segment named "Command foobar"
$this->assertEquals("Command foobar", $trace["subsegments"][0]["name"]);
}
}

class CommandCollectorTestMockApplication extends Application {

public $events;
public function __construct()
{
$this->events = new CommandCollectorTestMockEvents();
$this->instance('events', $this->events);
}
}

class CommandCollectorTestMockEvents {
protected $listeners = [];

public function listen(string $event, $callback) {
$this->listeners[$event] = $callback;
}

public function dispatch($eventObject) {
$eventClass = get_class($eventObject);

if(!array_key_exists($eventClass, $this->listeners)) {
throw new \Exception("Unit test exception, $eventClass was never registered");
}

$eventCallback = $this->listeners[$eventClass];

$eventCallback($eventObject);
}
}

class CommandCollectorSegmentSubmitter implements SegmentSubmitter
{

public static $submittedSegments = [];

public function submitSegment(Segment $segment): void
{
self::$submittedSegments[] = $segment;
}

}

0 comments on commit bd6c014

Please sign in to comment.