PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.8
Booking for Appointments and Events Calendar – Amelia v2.4.8
2.4.9 2.4.8 2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / src / Infrastructure / CommandBus / LoggingMiddleware.php
ameliabooking / src / Infrastructure / CommandBus Last commit date
LoggingMiddleware.php 1 week ago
LoggingMiddleware.php
78 lines
1 <?php
2
3 namespace AmeliaBooking\Infrastructure\CommandBus;
4
5 use AmeliaBooking\Domain\Services\Logger\LoggerInterface;
6 use League\Tactician\Middleware;
7
8 /**
9 * Class LoggingMiddleware
10 *
11 * Logs command failures only (exception + timing). Successful results are not logged.
12 * Channel is inferred from the command namespace so payment/booking/etc. land in the
13 * matching log file instead of a generic "command" file.
14 *
15 * @package AmeliaBooking\Infrastructure\CommandBus
16 */
17 class LoggingMiddleware implements Middleware
18 {
19 private const COMMANDS_NAMESPACE = 'AmeliaBooking\\Application\\Commands\\';
20
21 /** @var array<string, string> Top-level Commands\* segment → logger channel */
22 private const CHANNEL_BY_NAMESPACE = [
23 'payment' => LoggerInterface::CHANNEL_PAYMENT,
24 'paymentgateway' => LoggerInterface::CHANNEL_PAYMENT,
25 'square' => LoggerInterface::CHANNEL_PAYMENT,
26 'stripe' => LoggerInterface::CHANNEL_PAYMENT,
27 'booking' => LoggerInterface::CHANNEL_BOOKING,
28 'settings' => LoggerInterface::CHANNEL_SETTINGS,
29 'user' => LoggerInterface::CHANNEL_USER,
30 'notification' => LoggerInterface::CHANNEL_NOTIFICATION,
31 'zoom' => LoggerInterface::CHANNEL_ZOOM,
32 'google' => LoggerInterface::CHANNEL_SYNC,
33 'outlook' => LoggerInterface::CHANNEL_SYNC,
34 'apple' => LoggerInterface::CHANNEL_SYNC,
35 'calendar' => LoggerInterface::CHANNEL_SYNC,
36 ];
37
38 private LoggerInterface $logger;
39
40 public function __construct(LoggerInterface $logger)
41 {
42 $this->logger = $logger;
43 }
44
45 public function execute($command, callable $next)
46 {
47 $commandClass = get_class($command);
48 $start = microtime(true);
49
50 try {
51 return $next($command);
52 } catch (\Throwable $e) {
53 $elapsedMs = round((microtime(true) - $start) * 1000, 2);
54
55 $this->logger
56 ->channel($this->resolveChannel($commandClass))
57 ->error("Failed: {$commandClass}", [
58 'elapsed_ms' => $elapsedMs,
59 'exception' => $e,
60 ]);
61
62 throw $e;
63 }
64 }
65
66 private function resolveChannel(string $commandClass): string
67 {
68 if (strpos($commandClass, self::COMMANDS_NAMESPACE) !== 0) {
69 return LoggerInterface::CHANNEL_COMMAND;
70 }
71
72 $relative = substr($commandClass, strlen(self::COMMANDS_NAMESPACE));
73 $segment = strtolower(explode('\\', $relative)[0] ?? '');
74
75 return self::CHANNEL_BY_NAMESPACE[$segment] ?? LoggerInterface::CHANNEL_COMMAND;
76 }
77 }
78