From 589065910240f2dbc122362e95cd9175d0653a8a Mon Sep 17 00:00:00 2001 From: Alex Renoki Date: Mon, 17 Aug 2020 21:06:51 +0300 Subject: [PATCH 1/6] Refactored the dashboard logger --- src/Dashboard/DashboardLogger.php | 134 ++++------------ .../Controllers/TriggerEventController.php | 11 +- src/PubSub/Drivers/RedisClient.php | 151 +++++++++++------- src/WebSockets/Channels/Channel.php | 14 +- .../Messages/PusherClientMessage.php | 7 +- src/WebSockets/WebSocketHandler.php | 12 +- 6 files changed, 160 insertions(+), 169 deletions(-) diff --git a/src/Dashboard/DashboardLogger.php b/src/Dashboard/DashboardLogger.php index 2b00d3f0d6..e787c47a56 100644 --- a/src/Dashboard/DashboardLogger.php +++ b/src/Dashboard/DashboardLogger.php @@ -10,9 +10,9 @@ class DashboardLogger { const LOG_CHANNEL_PREFIX = 'private-websockets-dashboard-'; - const TYPE_DISCONNECTION = 'disconnection'; + const TYPE_DISCONNECTED = 'disconnected'; - const TYPE_CONNECTION = 'connection'; + const TYPE_CONNECTED = 'connected'; const TYPE_VACATED = 'vacated'; @@ -20,7 +20,7 @@ class DashboardLogger const TYPE_SUBSCRIBED = 'subscribed'; - const TYPE_CLIENT_MESSAGE = 'client-message'; + const TYPE_WS_MESSAGE = 'ws-message'; const TYPE_API_MESSAGE = 'api-message'; @@ -28,101 +28,36 @@ class DashboardLogger const TYPE_REPLICATOR_UNSUBSCRIBED = 'replicator-unsubscribed'; - public static function connection(ConnectionInterface $connection) - { - /** @var \GuzzleHttp\Psr7\Request $request */ - $request = $connection->httpRequest; - - static::log($connection->app->id, static::TYPE_CONNECTION, [ - 'details' => [ - 'origin' => "{$request->getUri()->getScheme()}://{$request->getUri()->getHost()}", - 'socketId' => $connection->socketId, - ], - ]); - } - - public static function occupied(ConnectionInterface $connection, string $channelName) - { - static::log($connection->app->id, static::TYPE_OCCUPIED, [ - 'details' => [ - 'channel' => $channelName, - ], - ]); - } - - public static function subscribed(ConnectionInterface $connection, string $channelName) - { - static::log($connection->app->id, static::TYPE_SUBSCRIBED, [ - 'details' => [ - 'socketId' => $connection->socketId, - 'channel' => $channelName, - ], - ]); - } - - public static function clientMessage(ConnectionInterface $connection, stdClass $payload) - { - static::log($connection->app->id, static::TYPE_CLIENT_MESSAGE, [ - 'details' => [ - 'socketId' => $connection->socketId, - 'channel' => $payload->channel, - 'event' => $payload->event, - 'data' => $payload, - ], - ]); - } - - public static function disconnection(ConnectionInterface $connection) - { - static::log($connection->app->id, static::TYPE_DISCONNECTION, [ - 'details' => [ - 'socketId' => $connection->socketId, - ], - ]); - } - - public static function vacated(ConnectionInterface $connection, string $channelName) - { - static::log($connection->app->id, static::TYPE_VACATED, [ - 'details' => [ - 'socketId' => $connection->socketId, - 'channel' => $channelName, - ], - ]); - } - - public static function apiMessage($appId, string $channel, string $event, string $payload) - { - static::log($appId, static::TYPE_API_MESSAGE, [ - 'details' => [ - 'channel' => $connection, - 'event' => $event, - 'payload' => $payload, - ], - ]); - } - - public static function replicatorSubscribed(string $appId, string $channel, string $serverId) - { - static::log($appId, static::TYPE_REPLICATOR_SUBSCRIBED, [ - 'details' => [ - 'serverId' => $serverId, - 'channel' => $channel, - ], - ]); - } - - public static function replicatorUnsubscribed(string $appId, string $channel, string $serverId) - { - static::log($appId, static::TYPE_REPLICATOR_UNSUBSCRIBED, [ - 'details' => [ - 'serverId' => $serverId, - 'channel' => $channel, - ], - ]); - } - - public static function log($appId, string $type, array $attributes = []) + const TYPE_REPLICATOR_JOINED_CHANNEL = 'replicator-joined'; + + const TYPE_REPLICATOR_LEFT_CHANNEL = 'replicator-left'; + + const TYPE_REPLICATOR_MESSAGE_PUBLISHED = 'replicator-message-published'; + + const TYPE_REPLICATOR_MESSAGE_RECEIVED = 'replicator-message-received'; + + /** + * The list of all channels. + * + * @var array + */ + public static $channels = [ + self::TYPE_DISCONNECTED, + self::TYPE_CONNECTED, + self::TYPE_VACATED, + self::TYPE_OCCUPIED, + self::TYPE_SUBSCRIBED, + self::TYPE_WS_MESSAGE, + self::TYPE_API_MESSAGE, + self::TYPE_REPLICATOR_SUBSCRIBED, + self::TYPE_REPLICATOR_UNSUBSCRIBED, + self::TYPE_REPLICATOR_JOINED_CHANNEL, + self::TYPE_REPLICATOR_LEFT_CHANNEL, + self::TYPE_REPLICATOR_MESSAGE_PUBLISHED, + self::TYPE_REPLICATOR_MESSAGE_RECEIVED, + ]; + + public static function log($appId, string $type, array $details = []) { $channelName = static::LOG_CHANNEL_PREFIX.$type; @@ -134,7 +69,8 @@ public static function log($appId, string $type, array $attributes = []) 'data' => [ 'type' => $type, 'time' => strftime('%H:%M:%S'), - ] + $attributes, + 'details' => $details, + ], ]); } } diff --git a/src/HttpApi/Controllers/TriggerEventController.php b/src/HttpApi/Controllers/TriggerEventController.php index bc921e4f1f..819d417878 100644 --- a/src/HttpApi/Controllers/TriggerEventController.php +++ b/src/HttpApi/Controllers/TriggerEventController.php @@ -21,12 +21,11 @@ public function __invoke(Request $request) 'data' => $request->json()->get('data'), ], $request->json()->get('socket_id'), $request->appId); - DashboardLogger::apiMessage( - $request->appId, - $channelName, - $request->json()->get('name'), - $request->json()->get('data') - ); + DashboardLogger::log($request->appId, DashboardLogger::TYPE_API_MESSAGE, [ + 'channel' => $channelName, + 'event' => $request->json()->get('name'), + 'payload' => $request->json()->get('data'), + ]); StatisticsLogger::apiMessage($request->appId); } diff --git a/src/PubSub/Drivers/RedisClient.php b/src/PubSub/Drivers/RedisClient.php index ef48149414..7b730c3f09 100644 --- a/src/PubSub/Drivers/RedisClient.php +++ b/src/PubSub/Drivers/RedisClient.php @@ -12,7 +12,7 @@ use React\Promise\PromiseInterface; use stdClass; -class RedisClient implements ReplicationInterface +class RedisClient extends LocalClient { /** * The running loop. @@ -90,49 +90,29 @@ public function boot(LoopInterface $loop, $factoryClass = null): ReplicationInte } /** - * Handle a message received from Redis on a specific channel. + * Publish a message to a channel on behalf of a websocket user. * - * @param string $redisChannel - * @param string $payload - * @return void + * @param string $appId + * @param string $channel + * @param stdClass $payload + * @return bool */ - protected function onMessage(string $redisChannel, string $payload) + public function publish(string $appId, string $channel, stdClass $payload): bool { - $payload = json_decode($payload); - - // Ignore messages sent by ourselves. - if (isset($payload->serverId) && $this->serverId === $payload->serverId) { - return; - } - - // Pull out the app ID. See RedisPusherBroadcaster - $appId = $payload->appId; - - // We need to put the channel name in the payload. - // We strip the app ID from the channel name, websocket clients - // expect the channel name to not include the app ID. - $payload->channel = Str::after($redisChannel, "{$appId}:"); - - $channelManager = app(ChannelManager::class); - - // Load the Channel instance to sync. - $channel = $channelManager->find($appId, $payload->channel); + $payload->appId = $appId; + $payload->serverId = $this->getServerId(); - // If no channel is found, none of our connections want to - // receive this message, so we ignore it. - if (! $channel) { - return; - } + $payload = json_encode($payload); - $socket = $payload->socket ?? null; + $this->publishClient->__call('publish', ["$appId:$channel", $payload]); - // Remove fields intended for internal use from the payload. - unset($payload->socket); - unset($payload->serverId); - unset($payload->appId); + DashboardLogger::log($appId, DashboardLogger::TYPE_REPLICATOR_MESSAGE_PUBLISHED, [ + 'channel' => $channel, + 'serverId' => $this->getServerId(), + 'payload' => $payload, + ]); - // Push the message out to connected websocket clients. - $channel->broadcastToEveryoneExcept($payload, $socket, $appId, false); + return true; } /** @@ -153,7 +133,10 @@ public function subscribe(string $appId, string $channel): bool $this->subscribedChannels["$appId:$channel"]++; } - DashboardLogger::replicatorSubscribed($appId, $channel, $this->serverId); + DashboardLogger::log($appId, DashboardLogger::TYPE_REPLICATOR_SUBSCRIBED, [ + 'channel' => $channel, + 'serverId' => $this->getServerId(), + ]); return true; } @@ -181,25 +164,10 @@ public function unsubscribe(string $appId, string $channel): bool unset($this->subscribedChannels["$appId:$channel"]); } - DashboardLogger::replicatorUnsubscribed($appId, $channel, $this->serverId); - - return true; - } - - /** - * Publish a message to a channel on behalf of a websocket user. - * - * @param string $appId - * @param string $channel - * @param stdClass $payload - * @return bool - */ - public function publish(string $appId, string $channel, stdClass $payload): bool - { - $payload->appId = $appId; - $payload->serverId = $this->serverId; - - $this->publishClient->__call('publish', ["$appId:$channel", json_encode($payload)]); + DashboardLogger::log($appId, DashboardLogger::TYPE_REPLICATOR_UNSUBSCRIBED, [ + 'channel' => $channel, + 'serverId' => $this->getServerId(), + ]); return true; } @@ -217,6 +185,13 @@ public function publish(string $appId, string $channel, stdClass $payload): bool public function joinChannel(string $appId, string $channel, string $socketId, string $data) { $this->publishClient->__call('hset', ["$appId:$channel", $socketId, $data]); + + DashboardLogger::log($appId, DashboardLogger::TYPE_REPLICATOR_JOINED_CHANNEL, [ + 'channel' => $channel, + 'serverId' => $this->getServerId(), + 'socketId' => $socketId, + 'data' => $data, + ]); } /** @@ -231,6 +206,12 @@ public function joinChannel(string $appId, string $channel, string $socketId, st public function leaveChannel(string $appId, string $channel, string $socketId) { $this->publishClient->__call('hdel', ["$appId:$channel", $socketId]); + + DashboardLogger::log($appId, DashboardLogger::TYPE_REPLICATOR_LEFT_CHANNEL, [ + 'channel' => $channel, + 'serverId' => $this->getServerId(), + 'socketId' => $socketId, + ]); } /** @@ -272,6 +253,62 @@ public function channelMemberCounts(string $appId, array $channelNames): Promise }); } + /** + * Handle a message received from Redis on a specific channel. + * + * @param string $redisChannel + * @param string $payload + * @return void + */ + protected function onMessage(string $redisChannel, string $payload) + { + $payload = json_decode($payload); + + // Ignore messages sent by ourselves. + if (isset($payload->serverId) && $this->getServerId() === $payload->serverId) { + return; + } + + // Pull out the app ID. See RedisPusherBroadcaster + $appId = $payload->appId; + + // We need to put the channel name in the payload. + // We strip the app ID from the channel name, websocket clients + // expect the channel name to not include the app ID. + $payload->channel = Str::after($redisChannel, "{$appId}:"); + + $channelManager = app(ChannelManager::class); + + // Load the Channel instance to sync. + $channel = $channelManager->find($appId, $payload->channel); + + // If no channel is found, none of our connections want to + // receive this message, so we ignore it. + if (! $channel) { + return; + } + + $socket = $payload->socket ?? null; + $serverId = $payload->serverId ?? null; + + // Remove fields intended for internal use from the payload. + unset($payload->socket); + unset($payload->serverId); + unset($payload->appId); + + // Push the message out to connected websocket clients. + $channel->broadcastToEveryoneExcept($payload, $socket, $appId, false); + + DashboardLogger::log($appId, DashboardLogger::TYPE_REPLICATOR_MESSAGE_RECEIVED, [ + 'channel' => $channel->getChannelName(), + 'redisChannel' => $redisChannel, + 'serverId' => $this->getServer(), + 'incomingServerId' => $serverId, + 'incomingSocketId' => $socket, + 'payload' => $payload, + ]); + } + /** * Build the Redis connection URL from Laravel database config. * diff --git a/src/WebSockets/Channels/Channel.php b/src/WebSockets/Channels/Channel.php index 8e301c113d..cd7e473aed 100644 --- a/src/WebSockets/Channels/Channel.php +++ b/src/WebSockets/Channels/Channel.php @@ -82,7 +82,10 @@ public function unsubscribe(ConnectionInterface $connection) $this->replicator->unsubscribe($connection->app->id, $this->channelName); if (! $this->hasConnections()) { - DashboardLogger::vacated($connection, $this->channelName); + DashboardLogger::log($connection->app->id, DashboardLogger::TYPE_VACATED, [ + 'socketId' => $connection->socketId, + 'channel' => $this->channelName, + ]); } } @@ -93,10 +96,15 @@ protected function saveConnection(ConnectionInterface $connection) $this->subscribedConnections[$connection->socketId] = $connection; if (! $hadConnectionsPreviously) { - DashboardLogger::occupied($connection, $this->channelName); + DashboardLogger::log($connection->app->id, DashboardLogger::TYPE_OCCUPIED, [ + 'channel' => $this->channelName, + ]); } - DashboardLogger::subscribed($connection, $this->channelName); + DashboardLogger::log($connection->app->id, DashboardLogger::TYPE_SUBSCRIBED, [ + 'socketId' => $connection->socketId, + 'channel' => $this->channelName, + ]); } public function broadcast($payload) diff --git a/src/WebSockets/Messages/PusherClientMessage.php b/src/WebSockets/Messages/PusherClientMessage.php index f7c4c4557a..1ef519cdc1 100644 --- a/src/WebSockets/Messages/PusherClientMessage.php +++ b/src/WebSockets/Messages/PusherClientMessage.php @@ -38,7 +38,12 @@ public function respond() return; } - DashboardLogger::clientMessage($this->connection, $this->payload); + DashboardLogger::log($this->connection->app->id, DashboardLogger::TYPE_WS_MESSAGE, [ + 'socketId' => $this->connection->socketId, + 'channel' => $this->payload->channel, + 'event' => $this->payload->event, + 'data' => $this->payload, + ]); $channel = $this->channelManager->find($this->connection->app->id, $this->payload->channel); diff --git a/src/WebSockets/WebSocketHandler.php b/src/WebSockets/WebSocketHandler.php index d2fdb6c10d..96a2fe32ad 100644 --- a/src/WebSockets/WebSocketHandler.php +++ b/src/WebSockets/WebSocketHandler.php @@ -48,7 +48,9 @@ public function onClose(ConnectionInterface $connection) { $this->channelManager->removeFromAllChannels($connection); - DashboardLogger::disconnection($connection); + DashboardLogger::log($connection->app->id, DashboardLogger::TYPE_DISCONNECTED, [ + 'socketId' => $connection->socketId, + ]); StatisticsLogger::disconnection($connection); } @@ -106,9 +108,13 @@ protected function establishConnection(ConnectionInterface $connection) ]), ])); - DashboardLogger::connection($connection); + /** @var \GuzzleHttp\Psr7\Request $request */ + $request = $connection->httpRequest; - StatisticsLogger::connection($connection); + DashboardLogger::log($connection->app->id, DashboardLogger::TYPE_CONNECTED, [ + 'origin' => "{$request->getUri()->getScheme()}://{$request->getUri()->getHost()}", + 'socketId' => $connection->socketId, + ]); return $this; } From 09776a18284a2ea400cbf0b08b5949745210ac70 Mon Sep 17 00:00:00 2001 From: Alex Renoki Date: Mon, 17 Aug 2020 21:17:00 +0300 Subject: [PATCH 2/6] Refactored the statistics logger --- config/websockets.php | 6 ++- src/Facades/StatisticsLogger.php | 2 +- .../Logger/NullStatisticsLogger.php | 47 +++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 src/Statistics/Logger/NullStatisticsLogger.php diff --git a/config/websockets.php b/config/websockets.php index 1c9f61f2f7..13aac01bc9 100644 --- a/config/websockets.php +++ b/config/websockets.php @@ -191,9 +191,13 @@ | store them into an array and then store them into the database | on each interval. | + | You can opt-in to avoid any statistics storage by setting the logger + | to the built-in NullLogger. + | */ - 'logger' => BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger::class, + 'logger' => \BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger::class, + // 'logger' => \BeyondCode\LaravelWebSockets\Statistics\Logger\NullStatisticsLogger::class, /* |-------------------------------------------------------------------------- diff --git a/src/Facades/StatisticsLogger.php b/src/Facades/StatisticsLogger.php index 9aadfa7425..518334279a 100644 --- a/src/Facades/StatisticsLogger.php +++ b/src/Facades/StatisticsLogger.php @@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Facade; /** - * @see \BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger + * @see \BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger * @mixin \BeyondCode\LaravelWebSockets\Statistics\Logger\HttpStatisticsLogger */ class StatisticsLogger extends Facade diff --git a/src/Statistics/Logger/NullStatisticsLogger.php b/src/Statistics/Logger/NullStatisticsLogger.php new file mode 100644 index 0000000000..885703e92b --- /dev/null +++ b/src/Statistics/Logger/NullStatisticsLogger.php @@ -0,0 +1,47 @@ +channelManager = $channelManager; + $this->browser = $browser; + } + + public function webSocketMessage(ConnectionInterface $connection) + { + // + } + + public function apiMessage($appId) + { + // + } + + public function connection(ConnectionInterface $connection) + { + // + } + + public function disconnection(ConnectionInterface $connection) + { + // + } + + public function save() + { + // + } +} From 871c942dd969c8c6b8a412e0345e517e7c525733 Mon Sep 17 00:00:00 2001 From: rennokki Date: Mon, 17 Aug 2020 21:18:55 +0300 Subject: [PATCH 3/6] Apply fixes from StyleCI (#466) --- src/Dashboard/DashboardLogger.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Dashboard/DashboardLogger.php b/src/Dashboard/DashboardLogger.php index e787c47a56..f5d0980873 100644 --- a/src/Dashboard/DashboardLogger.php +++ b/src/Dashboard/DashboardLogger.php @@ -3,8 +3,6 @@ namespace BeyondCode\LaravelWebSockets\Dashboard; use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager; -use Ratchet\ConnectionInterface; -use stdClass; class DashboardLogger { From c622f7735133be7323b27086c415d3006ef4cf65 Mon Sep 17 00:00:00 2001 From: Alex Renoki Date: Mon, 17 Aug 2020 21:20:50 +0300 Subject: [PATCH 4/6] Added missing statistics logger. --- src/WebSockets/WebSocketHandler.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/WebSockets/WebSocketHandler.php b/src/WebSockets/WebSocketHandler.php index 96a2fe32ad..7820960b6b 100644 --- a/src/WebSockets/WebSocketHandler.php +++ b/src/WebSockets/WebSocketHandler.php @@ -116,6 +116,8 @@ protected function establishConnection(ConnectionInterface $connection) 'socketId' => $connection->socketId, ]); + StatisticsLogger::connection($connection); + return $this; } } From 417c8322e0cfb270ec89dcd3acffbb1b6e4bca65 Mon Sep 17 00:00:00 2001 From: Alex Renoki Date: Mon, 17 Aug 2020 21:24:18 +0300 Subject: [PATCH 5/6] updated pubsub messages --- src/PubSub/Drivers/LocalClient.php | 14 ++++++------- src/PubSub/Drivers/RedisClient.php | 33 +++++++++++++++++------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/PubSub/Drivers/LocalClient.php b/src/PubSub/Drivers/LocalClient.php index 3e24c73f8b..8209e83803 100644 --- a/src/PubSub/Drivers/LocalClient.php +++ b/src/PubSub/Drivers/LocalClient.php @@ -78,7 +78,7 @@ public function unsubscribe(string $appId, string $channel): bool */ public function joinChannel(string $appId, string $channel, string $socketId, string $data) { - $this->channelData["$appId:$channel"][$socketId] = $data; + $this->channelData["{$appId}:{$channel}"][$socketId] = $data; } /** @@ -92,10 +92,10 @@ public function joinChannel(string $appId, string $channel, string $socketId, st */ public function leaveChannel(string $appId, string $channel, string $socketId) { - unset($this->channelData["$appId:$channel"][$socketId]); + unset($this->channelData["{$appId}:{$channel}"][$socketId]); - if (empty($this->channelData["$appId:$channel"])) { - unset($this->channelData["$appId:$channel"]); + if (empty($this->channelData["{$appId}:{$channel}"])) { + unset($this->channelData["{$appId}:{$channel}"]); } } @@ -108,7 +108,7 @@ public function leaveChannel(string $appId, string $channel, string $socketId) */ public function channelMembers(string $appId, string $channel): PromiseInterface { - $members = $this->channelData["$appId:$channel"] ?? []; + $members = $this->channelData["{$appId}:{$channel}"] ?? []; $members = array_map(function ($user) { return json_decode($user); @@ -130,8 +130,8 @@ public function channelMemberCounts(string $appId, array $channelNames): Promise // Count the number of users per channel foreach ($channelNames as $channel) { - $results[$channel] = isset($this->channelData["$appId:$channel"]) - ? count($this->channelData["$appId:$channel"]) + $results[$channel] = isset($this->channelData["{$appId}:{$channel}"]) + ? count($this->channelData["{$appId}:{$channel}"]) : 0; } diff --git a/src/PubSub/Drivers/RedisClient.php b/src/PubSub/Drivers/RedisClient.php index 7b730c3f09..11a479edd6 100644 --- a/src/PubSub/Drivers/RedisClient.php +++ b/src/PubSub/Drivers/RedisClient.php @@ -104,12 +104,13 @@ public function publish(string $appId, string $channel, stdClass $payload): bool $payload = json_encode($payload); - $this->publishClient->__call('publish', ["$appId:$channel", $payload]); + $this->publishClient->__call('publish', ["{$appId}:{$channel}", $payload]); DashboardLogger::log($appId, DashboardLogger::TYPE_REPLICATOR_MESSAGE_PUBLISHED, [ 'channel' => $channel, 'serverId' => $this->getServerId(), 'payload' => $payload, + 'pubsub' => "{$appId}:{$channel}", ]); return true; @@ -124,18 +125,19 @@ public function publish(string $appId, string $channel, stdClass $payload): bool */ public function subscribe(string $appId, string $channel): bool { - if (! isset($this->subscribedChannels["$appId:$channel"])) { + if (! isset($this->subscribedChannels["{$appId}:{$channel}"])) { // We're not subscribed to the channel yet, subscribe and set the count to 1 - $this->subscribeClient->__call('subscribe', ["$appId:$channel"]); - $this->subscribedChannels["$appId:$channel"] = 1; + $this->subscribeClient->__call('subscribe', ["{$appId}:{$channel}"]); + $this->subscribedChannels["{$appId}:{$channel}"] = 1; } else { // Increment the subscribe count if we've already subscribed - $this->subscribedChannels["$appId:$channel"]++; + $this->subscribedChannels["{$appId}:{$channel}"]++; } DashboardLogger::log($appId, DashboardLogger::TYPE_REPLICATOR_SUBSCRIBED, [ 'channel' => $channel, 'serverId' => $this->getServerId(), + 'pubsub' => "{$appId}:{$channel}", ]); return true; @@ -150,23 +152,24 @@ public function subscribe(string $appId, string $channel): bool */ public function unsubscribe(string $appId, string $channel): bool { - if (! isset($this->subscribedChannels["$appId:$channel"])) { + if (! isset($this->subscribedChannels["{$appId}:{$channel}"])) { return false; } // Decrement the subscription count for this channel - $this->subscribedChannels["$appId:$channel"]--; + $this->subscribedChannels["{$appId}:{$channel}"]--; // If we no longer have subscriptions to that channel, unsubscribe - if ($this->subscribedChannels["$appId:$channel"] < 1) { - $this->subscribeClient->__call('unsubscribe', ["$appId:$channel"]); + if ($this->subscribedChannels["{$appId}:{$channel}"] < 1) { + $this->subscribeClient->__call('unsubscribe', ["{$appId}:{$channel}"]); - unset($this->subscribedChannels["$appId:$channel"]); + unset($this->subscribedChannels["{$appId}:{$channel}"]); } DashboardLogger::log($appId, DashboardLogger::TYPE_REPLICATOR_UNSUBSCRIBED, [ 'channel' => $channel, 'serverId' => $this->getServerId(), + 'pubsub' => "{$appId}:{$channel}", ]); return true; @@ -184,13 +187,14 @@ public function unsubscribe(string $appId, string $channel): bool */ public function joinChannel(string $appId, string $channel, string $socketId, string $data) { - $this->publishClient->__call('hset', ["$appId:$channel", $socketId, $data]); + $this->publishClient->__call('hset', ["{$appId}:{$channel}", $socketId, $data]); DashboardLogger::log($appId, DashboardLogger::TYPE_REPLICATOR_JOINED_CHANNEL, [ 'channel' => $channel, 'serverId' => $this->getServerId(), 'socketId' => $socketId, 'data' => $data, + 'pubsub' => "{$appId}:{$channel}", ]); } @@ -205,12 +209,13 @@ public function joinChannel(string $appId, string $channel, string $socketId, st */ public function leaveChannel(string $appId, string $channel, string $socketId) { - $this->publishClient->__call('hdel', ["$appId:$channel", $socketId]); + $this->publishClient->__call('hdel', ["{$appId}:{$channel}", $socketId]); DashboardLogger::log($appId, DashboardLogger::TYPE_REPLICATOR_LEFT_CHANNEL, [ 'channel' => $channel, 'serverId' => $this->getServerId(), 'socketId' => $socketId, + 'pubsub' => "{$appId}:{$channel}", ]); } @@ -223,7 +228,7 @@ public function leaveChannel(string $appId, string $channel, string $socketId) */ public function channelMembers(string $appId, string $channel): PromiseInterface { - return $this->publishClient->__call('hgetall', ["$appId:$channel"]) + return $this->publishClient->__call('hgetall', ["{$appId}:{$channel}"]) ->then(function ($members) { // The data is expected as objects, so we need to JSON decode return array_map(function ($user) { @@ -244,7 +249,7 @@ public function channelMemberCounts(string $appId, array $channelNames): Promise $this->publishClient->__call('multi', []); foreach ($channelNames as $channel) { - $this->publishClient->__call('hlen', ["$appId:$channel"]); + $this->publishClient->__call('hlen', ["{$appId}:{$channel}"]); } return $this->publishClient->__call('exec', []) From a9111ab41569252a38ec6ea9059400d38ef6902a Mon Sep 17 00:00:00 2001 From: Alex Renoki Date: Tue, 18 Aug 2020 09:35:09 +0300 Subject: [PATCH 6/6] refactored dashboard frontend --- .editorconfig | 3 + resources/views/dashboard.blade.php | 646 +++++++++++------- .../Http/Controllers/ShowDashboard.php | 3 + 3 files changed, 408 insertions(+), 244 deletions(-) diff --git a/.editorconfig b/.editorconfig index cd8eb86efa..32de2af6aa 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,5 +11,8 @@ end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true +[*.blade.php] +indent_size = 2 + [*.md] trim_trailing_whitespace = false diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php index e4a761b905..33a69b17c1 100644 --- a/resources/views/dashboard.blade.php +++ b/resources/views/dashboard.blade.php @@ -1,265 +1,423 @@ - - WebSockets Dashboard - - - - - + + + WebSockets Dashboard + + + + + + + + + + + - -
-
-
-
- - - - - - -
-
+ +
+
+
+ Connect to app +
+ +
+
+ +
+ +
-
-
-

Realtime Statistics

-
-
-
-

Event Creator

-
-
-
- -
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-

Events

- - - - - - - - - - - - - - - -
TypeDetailsTime
@{{ log.type }}
@{{ log.details }}
@{{ log.time }}
+
+ + +
+
+
+ +
+
+ Live statistics
-
+ +
+
+ +
+
+ Send payload event to channel +
+ +
+
+ + +
+
+ + +
+
+ +
+ + + +
+ +
+ +
+
+ +
+
+ Server activity +
+ +
+
+ + + + + + + + + + + + + + + +
+ Type + + Details + + Time +
+
+ @{{ log.type }} +
+
+
@{{ log.details }}
+
+ @{{ log.time }} +
+
+
+
+
diff --git a/src/Dashboard/Http/Controllers/ShowDashboard.php b/src/Dashboard/Http/Controllers/ShowDashboard.php index 47088ef515..7f22a45dd3 100644 --- a/src/Dashboard/Http/Controllers/ShowDashboard.php +++ b/src/Dashboard/Http/Controllers/ShowDashboard.php @@ -3,6 +3,7 @@ namespace BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers; use BeyondCode\LaravelWebSockets\Apps\AppManager; +use BeyondCode\LaravelWebSockets\Dashboard\DashboardLogger; use Illuminate\Http\Request; class ShowDashboard @@ -12,6 +13,8 @@ public function __invoke(Request $request, AppManager $apps) return view('websockets::dashboard', [ 'apps' => $apps->all(), 'port' => config('websockets.dashboard.port', 6001), + 'channels' => DashboardLogger::$channels, + 'logPrefix' => DashboardLogger::LOG_CHANNEL_PREFIX, ]); } }