diff --git a/README.md b/README.md index 0b5176f..0571c43 100755 --- a/README.md +++ b/README.md @@ -49,6 +49,22 @@ class EventStoreServiceProvider extends EventStoreApplicationServiceProvider }); } + /** + * Handle logging when event is triggered. + * + * @return void + */ + public function logger() + { + // This will setup the logger for when an event happens. + EventStore::logger(); + + // You can customise this by doing the following. + EventStore::logger(function ($event, $type) { + Log::info($event->getType()); + }); + } + /** * Register the application services. */ diff --git a/composer.json b/composer.json index 5469a05..5c2bd1d 100755 --- a/composer.json +++ b/composer.json @@ -24,7 +24,8 @@ }, "require-dev": { "orchestra/testbench": "^4.0", - "phpunit/phpunit": "^8.0" + "phpunit/phpunit": "^8.0", + "timacdonald/log-fake": "^1.4" }, "autoload": { "psr-4": { diff --git a/src/Console/Commands/EventStoreWorker.php b/src/Console/Commands/EventStoreWorker.php index 325afd7..d971097 100644 --- a/src/Console/Commands/EventStoreWorker.php +++ b/src/Console/Commands/EventStoreWorker.php @@ -79,7 +79,6 @@ private function processPersistentStream($eventStore, string $stream): void $eventStore ->persistentSubscription($stream, config('eventstore.group'), $this->option('parallel') ?? 1) ->subscribe(function (AcknowledgeableEventRecord $event) { - $this->logEventStart($event, 'persistent'); try { $this->dispatch($event); $event->ack(); @@ -96,7 +95,6 @@ private function processVolatileStream($eventStore, string $stream): void $eventStore ->volatileSubscription($stream) ->subscribe(function (EventRecord $event) { - $this->logEventStart($event, 'volatile'); try { $this->dispatch($event); } catch (\Exception $e) { @@ -106,17 +104,6 @@ private function processVolatileStream($eventStore, string $stream): void }, 'report'); } - protected function logEventStart(EventRecord $event, $type = '') - { - $url = parse_url(config('eventstore.http_url')); - $url = "{$url['scheme']}://{$url['host']}:{$url['port']}"; - - $stream = $event->getStreamId(); - $number = $event->getNumber(); - - Log::info("{$url}/streams/{$stream}/{$number}", ['type' => $type]); - } - protected function dumpEvent(EventRecord $event) { dump([ @@ -141,23 +128,31 @@ protected function safeGetMetadata(EventRecord $event) public function dispatch(EventRecord $eventRecord): void { - $event = $this->makeSerializableEvent($eventRecord); + $logger = LaravelEventStore::$logger; + $serializedEvent = $payload = $this->makeSerializableEvent($eventRecord); + $event = $serializedEvent->getType(); - if ($localEvent = $this->mapToLocalEvent($event)) { - event($localEvent); - } else { - event($event->getType(), $event); + if ($localEvent = $this->mapToLocalEvent($serializedEvent)) { + $event = $localEvent; + $payload = null; } + + $logger($serializedEvent, $event); + event($event, $payload); } private function makeSerializableEvent(EventRecord $event): JsonEventRecord { $data = new EventData(); + $data->setEventId($event->getId()); $data->setEventType($event->getType()); - $data->setCreatedEpoch($event->getCreated()->getTimestamp() * 1000); + $data->setEventNumber($event->getNumber()); $data->setData(json_encode($event->getData())); + $data->setEventStreamId($event->getStreamId()); $data->setMetadata(json_encode($this->safeGetMetadata($event))); + $data->setCreatedEpoch($event->getCreated()->getTimestamp() * 1000); + return new JsonEventRecord($data); } diff --git a/src/EventStore.php b/src/EventStore.php index bca3279..7834273 100644 --- a/src/EventStore.php +++ b/src/EventStore.php @@ -2,6 +2,9 @@ namespace DigitalRisks\LaravelEventStore; +use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Event; + class EventStore { /** @@ -11,6 +14,13 @@ class EventStore */ public static $eventToClass; + /** + * Variable for logger. + * + * @var callable + */ + public static $logger; + /** * Set the event class based on current event key. * @@ -25,4 +35,26 @@ public static function eventToClass(?callable $callback = null) static::$eventToClass = $callback; } + + /** + * Set the logger environment. + * + * @param callable $callback + * @return void + */ + public static function logger(?callable $callback = null) + { + $callback = $callback ?: function ($event, $type) { + $url = parse_url(config('eventstore.http_url')); + $url = "{$url['scheme']}://{$url['host']}:{$url['port']}/web/index.html#"; + $type = $event->getType(); + $stream = $event->getStreamId(); + $number = $event->getNumber(); + $hasListener = Event::hasListeners($type); + + Log::info("{$url}/streams/{$stream}/{$number}", ['type' => $type, 'hasListeners' => $hasListener]); + }; + + static::$logger = $callback; + } } diff --git a/src/ServiceProvider.php b/src/ServiceProvider.php index c2b9d73..c793139 100755 --- a/src/ServiceProvider.php +++ b/src/ServiceProvider.php @@ -17,7 +17,6 @@ class ServiceProvider extends LaravelServiceProvider */ public function boot() { - $this->eventClasses(); if ($this->app->runningInConsole()) { $this->publishes([ __DIR__ . '/../config/eventstore.php' => config_path('eventstore.php'), @@ -29,6 +28,9 @@ public function boot() ]); } + $this->eventClasses(); + $this->logger(); + Event::listen(ShouldBeStored::class, SendToEventStoreListener::class); } @@ -42,6 +44,16 @@ public function eventClasses() EventStore::eventToClass(); } + /** + * Handle logging when event is triggered. + * + * @return void + */ + public function logger() + { + EventStore::logger(); + } + /** * Register the application services. */ diff --git a/src/Tests/Traits/MakesEventRecords.php b/src/Tests/Traits/MakesEventRecords.php index 16d7fd1..f536af4 100644 --- a/src/Tests/Traits/MakesEventRecords.php +++ b/src/Tests/Traits/MakesEventRecords.php @@ -8,12 +8,13 @@ trait MakesEventRecords { - public function makeEventRecord($type, $data, $metadata = [], $created = null) + public function makeEventRecord($type, $data, $metadata = [], $created = null, $stream = 'test-stream') { $event = new EventRecord(); $created = new Carbon($created); $event->setEventType($type); + $event->setEventStreamId($stream); $event->setCreatedEpoch($created->getTimestamp() * 1000); $event->setData(json_encode($data)); $event->setMetadata(json_encode($metadata)); diff --git a/tests/LoggerTest.php b/tests/LoggerTest.php new file mode 100644 index 0000000..5764f0c --- /dev/null +++ b/tests/LoggerTest.php @@ -0,0 +1,58 @@ +makeEventRecord('test_event', ['hello' => 'world']); + + // Act. + $worker->dispatch($event); + + // Assert. + Log::assertLogged('info', function ($message, $context) { + $this->assertStringContainsString("/streams/test-stream/0", $message); + $this->assertEquals(['type' => 'test_event', 'hasListeners' => false], $context); + + return true; + }); + } + + public function test_it_logs_an_event_with_a_listener() + { + // Arrange. + Log::swap(new LogFake); + + $worker = resolve(EventStoreWorker::class); + $event = $this->makeEventRecord('test_event', ['hello' => 'world']); + Event::listen('test_event', function () { + }); + + // Act. + $worker->dispatch($event); + + // Assert. + Log::assertLogged('info', function ($message, $context) { + $this->assertStringContainsString("/streams/test-stream/0", $message); + $this->assertEquals(['type' => 'test_event', 'hasListeners' => true], $context); + + return true; + }); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index 70effd0..1f01df9 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -11,6 +11,7 @@ class TestCase extends Orchestra protected function getPackageProviders($app) { EventStore::eventToClass(); + EventStore::logger(); return [ ServiceProvider::class,