Skip to content

Commit

Permalink
Capture notification duration (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
avosalmon authored Feb 17, 2025
1 parent f3c3d2e commit 651c95f
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Laravel\Nightwatch\Hooks;

use Illuminate\Notifications\Events\NotificationSending;
use Illuminate\Notifications\Events\NotificationSent;
use Laravel\Nightwatch\Core;
use Laravel\Nightwatch\State\CommandState;
Expand All @@ -11,7 +12,7 @@
/**
* @internal
*/
final class NotificationSentListener
final class NotificationListener
{
/**
* @param Core<RequestState|CommandState> $nightwatch
Expand All @@ -22,7 +23,7 @@ public function __construct(
//
}

public function __invoke(NotificationSent $event): void
public function __invoke(NotificationSending|NotificationSent $event): void
{
try {
$this->nightwatch->sensor->notification($event);
Expand Down
5 changes: 3 additions & 2 deletions src/NightwatchServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use Illuminate\Log\Context\Repository as ContextRepository;
use Illuminate\Log\LogManager;
use Illuminate\Mail\Events\MessageSent;
use Illuminate\Notifications\Events\NotificationSending;
use Illuminate\Notifications\Events\NotificationSent;
use Illuminate\Queue\Events\JobQueued;
use Illuminate\Routing\Events\PreparingResponse;
Expand All @@ -55,7 +56,7 @@
use Laravel\Nightwatch\Hooks\JobQueuedListener;
use Laravel\Nightwatch\Hooks\LogoutListener;
use Laravel\Nightwatch\Hooks\MessageSentListener;
use Laravel\Nightwatch\Hooks\NotificationSentListener;
use Laravel\Nightwatch\Hooks\NotificationListener;
use Laravel\Nightwatch\Hooks\PreparingResponseListener;
use Laravel\Nightwatch\Hooks\QueryExecutedListener;
use Laravel\Nightwatch\Hooks\RequestBootedHandler;
Expand Down Expand Up @@ -267,7 +268,7 @@ private function registerHooks(): void
/**
* @see \Laravel\Nightwatch\Records\Notification
*/
$events->listen(NotificationSent::class, (new NotificationSentListener($core))(...));
$events->listen([NotificationSending::class, NotificationSent::class], (new NotificationListener($core))(...));

/**
* @see \Laravel\Nightwatch\Records\OutgoingRequest
Expand Down
3 changes: 2 additions & 1 deletion src/SensorManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Http\Request;
use Illuminate\Mail\Events\MessageSent;
use Illuminate\Notifications\Events\NotificationSending;
use Illuminate\Notifications\Events\NotificationSent;
use Illuminate\Queue\Events\JobAttempted;
use Illuminate\Queue\Events\JobQueued;
Expand Down Expand Up @@ -138,7 +139,7 @@ public function mail(MessageSent $event): void
$sensor($event);
}

public function notification(NotificationSent $event): void
public function notification(NotificationSending|NotificationSent $event): void
{
$sensor = $this->notificationSensor ??= new NotificationSensor(
executionState: $this->executionState,
Expand Down
25 changes: 22 additions & 3 deletions src/Sensors/NotificationSensor.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,57 @@

namespace Laravel\Nightwatch\Sensors;

use Illuminate\Notifications\Events\NotificationSending;
use Illuminate\Notifications\Events\NotificationSent;
use Laravel\Nightwatch\Clock;
use Laravel\Nightwatch\Records\Notification;
use Laravel\Nightwatch\State\CommandState;
use Laravel\Nightwatch\State\RequestState;
use Laravel\Nightwatch\Types\Str;
use RuntimeException;

use function hash;
use function round;
use function str_contains;

/**
* @internal
*/
final class NotificationSensor
{
private ?float $startTime = null;

private ?int $duration = null;

public function __construct(
private RequestState|CommandState $executionState,
private Clock $clock,
) {
//
}

public function __invoke(NotificationSent $event): void
public function __invoke(NotificationSending|NotificationSent $event): void
{
$now = $this->clock->microtime();

if ($event instanceof NotificationSending) {
$this->startTime = $now;
$this->duration = null;

return;
}

if ($this->startTime === null) {
throw new RuntimeException('No start time found for ['.$event->notifiable::class.'].'); // @phpstan-ignore classConstant.nonObject
}

if (str_contains($event->notification::class, "@anonymous\0")) {
$class = Str::before($event->notification::class, "\0");
} else {
$class = $event->notification::class;
}

$this->duration = (int) round(($now - $this->startTime) * 1_000_000);
$this->executionState->notifications++;

$this->executionState->records->write(new Notification(
Expand All @@ -48,8 +67,8 @@ public function __invoke(NotificationSent $event): void
user: $this->executionState->user->id(),
channel: $event->channel,
class: $class,
duration: 0, // TODO
failed: false, // TODO
duration: $this->duration,
failed: false, // TODO: The framework doesn't dispatch the `NotificationFailed` event.
));
}
}
19 changes: 11 additions & 8 deletions tests/Feature/Sensors/NotificationSensorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Illuminate\Support\Facades\Route;

use function Pest\Laravel\post;
use function Pest\Laravel\travelTo;

beforeAll(function () {
forceRequestExecutionState();
Expand Down Expand Up @@ -56,7 +57,7 @@
[
'v' => 1,
't' => 'notification',
'timestamp' => 946688523.456789,
'timestamp' => 946688523.459289,
'deploy' => 'v1.2.3',
'server' => 'web-01',
'_group' => hash('md5', 'MyNotification'),
Expand All @@ -67,7 +68,7 @@
'user' => '',
'channel' => 'mail',
'class' => 'MyNotification',
'duration' => 0,
'duration' => 2500,
'failed' => false,
],
]);
Expand Down Expand Up @@ -98,7 +99,7 @@ public function via(object $notifiable)
[
'v' => 1,
't' => 'notification',
'timestamp' => 946688523.456789,
'timestamp' => 946688523.459289,
'deploy' => 'v1.2.3',
'server' => 'web-01',
'_group' => hash('md5', 'MyNotification@anonymous'),
Expand All @@ -109,13 +110,13 @@ public function via(object $notifiable)
'user' => '',
'channel' => 'mail',
'class' => 'MyNotification@anonymous',
'duration' => 0,
'duration' => 2500,
'failed' => false,
],
[
'v' => 1,
't' => 'notification',
'timestamp' => 946688523.456789,
'timestamp' => 946688523.461789,
'deploy' => 'v1.2.3',
'server' => 'web-01',
'_group' => hash('md5', 'MyNotification@anonymous'),
Expand All @@ -126,13 +127,13 @@ public function via(object $notifiable)
'user' => '',
'channel' => 'mail',
'class' => 'MyNotification@anonymous',
'duration' => 0,
'duration' => 2500,
'failed' => false,
],
[
'v' => 1,
't' => 'notification',
'timestamp' => 946688523.456789,
'timestamp' => 946688523.464289,
'deploy' => 'v1.2.3',
'server' => 'web-01',
'_group' => hash('md5', 'MyNotification@anonymous'),
Expand All @@ -143,7 +144,7 @@ public function via(object $notifiable)
'user' => '',
'channel' => 'mail',
'class' => 'MyNotification@anonymous',
'duration' => 0,
'duration' => 2500,
'failed' => false,
],
]);
Expand All @@ -166,6 +167,8 @@ public function toArray(object $notifiable)

public function toMail(object $notifiable)
{
travelTo(now()->addMicroseconds(2500));

return (new Illuminate\Mail\Mailable)
->subject('Hello World')
->to('[email protected]')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?php

use Illuminate\Notifications\Events\NotificationSending;
use Illuminate\Notifications\Events\NotificationSent;
use Laravel\Nightwatch\Hooks\NotificationSentListener;
use Laravel\Nightwatch\Hooks\NotificationListener;
use Laravel\Nightwatch\SensorManager;

it('gracefully handles exceptions', function () {
Expand All @@ -11,7 +12,7 @@

public function __construct() {}

public function notification(NotificationSent $event): void
public function notification(NotificationSending|NotificationSent $event): void
{
$this->thrown = true;

Expand All @@ -21,7 +22,7 @@ public function notification(NotificationSent $event): void

$event = new NotificationSent(new stdClass, new stdClass, 'broadcast');

$handler = new NotificationSentListener($nightwatch);
$handler = new NotificationListener($nightwatch);

$handler($event);

Expand Down

0 comments on commit 651c95f

Please sign in to comment.