diff --git a/config/websockets.php b/config/websockets.php index b4256118fe..fd1d32ba9a 100644 --- a/config/websockets.php +++ b/config/websockets.php @@ -178,16 +178,25 @@ /* |-------------------------------------------------------------------------- - | Statistics Eloquent Model + | Statistics Driver |-------------------------------------------------------------------------- | - | This model will be used to store the statistics of the WebSocketsServer. - | The only requirement is that the model should extend - | `WebSocketsStatisticsEntry` provided by this package. + | Here you can specify which driver to use to store the statistics to. + | See down below for each driver's setting. + | + | Available: database | */ - 'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class, + 'driver' => 'database', + + 'database' => [ + + 'driver' => \BeyondCode\LaravelWebSockets\Statistics\Drivers\DatabaseDriver::class, + + 'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class, + + ], /* |-------------------------------------------------------------------------- diff --git a/docs/debugging/dashboard.md b/docs/debugging/dashboard.md index a3fbca71a0..b37194d300 100644 --- a/docs/debugging/dashboard.md +++ b/docs/debugging/dashboard.md @@ -92,6 +92,14 @@ However, to disable it entirely and void any incoming statistic, you can uncomme 'logger' => \BeyondCode\LaravelWebSockets\Statistics\Logger\NullStatisticsLogger::class, // use the `NullStatisticsLogger` instead ``` +## Custom Statistics Drivers + +By default, the package comes with a few drivers like the Database driver which stores the data into the database. + +You should add your custom drivers under the `statistics` key in `websockets.php` and create a driver class that implements the `\BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver` interface. + +Take a quick look at the `\BeyondCode\LaravelWebSockets\Statistics\Drivers\DatabaseDriver` driver to see how to perform your integration. + ## Event Creator The dashboard also comes with an easy-to-use event creator, that lets you manually send events to your channels. diff --git a/src/Console/CleanStatistics.php b/src/Console/CleanStatistics.php index 786ff37c24..bc09cf6f36 100644 --- a/src/Console/CleanStatistics.php +++ b/src/Console/CleanStatistics.php @@ -2,9 +2,8 @@ namespace BeyondCode\LaravelWebSockets\Console; -use Carbon\Carbon; +use BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver; use Illuminate\Console\Command; -use Illuminate\Database\Eloquent\Builder; class CleanStatistics extends Command { @@ -27,25 +26,14 @@ class CleanStatistics extends Command /** * Run the command. * + * @param \BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver $driver * @return void */ - public function handle() + public function handle(StatisticsDriver $driver) { $this->comment('Cleaning WebSocket Statistics...'); - $appId = $this->argument('appId'); - - $maxAgeInDays = config('websockets.statistics.delete_statistics_older_than_days'); - - $cutOffDate = Carbon::now()->subDay($maxAgeInDays)->format('Y-m-d H:i:s'); - - $class = config('websockets.statistics.model'); - - $amountDeleted = $class::where('created_at', '<', $cutOffDate) - ->when(! is_null($appId), function (Builder $query) use ($appId) { - $query->where('app_id', $appId); - }) - ->delete(); + $amountDeleted = $driver::delete($this->argument('appId')); $this->info("Deleted {$amountDeleted} record(s) from the WebSocket statistics."); } diff --git a/src/Statistics/Drivers/DatabaseDriver.php b/src/Statistics/Drivers/DatabaseDriver.php new file mode 100644 index 0000000000..a8d5175a85 --- /dev/null +++ b/src/Statistics/Drivers/DatabaseDriver.php @@ -0,0 +1,112 @@ +record = $record; + } + + /** + * Get the app ID for the stats. + * + * @return mixed + */ + public function getAppId() + { + return $this->record->app_id; + } + + /** + * Get the time value. Should be Y-m-d H:i:s. + * + * @return string + */ + public function getTime(): string + { + return Carbon::parse($this->record->created_at)->toDateTimeString(); + } + + /** + * Get the peak connection count for the time. + * + * @return int + */ + public function getPeakConnectionCount(): int + { + return $this->record->peak_connection_count ?? 0; + } + + /** + * Get the websocket messages count for the time. + * + * @return int + */ + public function getWebsocketMessageCount(): int + { + return $this->record->websocket_message_count ?? 0; + } + + /** + * Get the API message count for the time. + * + * @return int + */ + public function getApiMessageCount(): int + { + return $this->record->api_message_count ?? 0; + } + + /** + * Create a new statistic in the store. + * + * @param array $data + * @return \BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver + */ + public static function create(array $data): StatisticsDriver + { + $class = config('websockets.statistics.database.model'); + + return new static($class::create($data)); + } + + /** + * Delete statistics from the store, + * optionally by app id, returning + * the number of deleted records. + * + * @param mixed $appId + * @return int + */ + public static function delete($appId = null): int + { + $cutOffDate = Carbon::now()->subDay( + config('websockets.statistics.delete_statistics_older_than_days') + )->format('Y-m-d H:i:s'); + + $class = config('websockets.statistics.database.model'); + + return $class::where('created_at', '<', $cutOffDate) + ->when($appId, function ($query) use ($appId) { + return $query->whereAppId($appId); + }) + ->delete(); + } +} diff --git a/src/Statistics/Drivers/StatisticsDriver.php b/src/Statistics/Drivers/StatisticsDriver.php new file mode 100644 index 0000000000..8ed1e5ec02 --- /dev/null +++ b/src/Statistics/Drivers/StatisticsDriver.php @@ -0,0 +1,67 @@ +webSocketsStatisticsEntry = $webSocketsStatisticsEntry; + $this->driver = $driver; } /** @@ -39,11 +39,11 @@ public function __construct(WebSocketsStatisticsEntry $webSocketsStatisticsEntry public function broadcastWith() { return [ - 'time' => (string) $this->webSocketsStatisticsEntry->created_at, - 'app_id' => $this->webSocketsStatisticsEntry->app_id, - 'peak_connection_count' => $this->webSocketsStatisticsEntry->peak_connection_count, - 'websocket_message_count' => $this->webSocketsStatisticsEntry->websocket_message_count, - 'api_message_count' => $this->webSocketsStatisticsEntry->api_message_count, + 'time' => $this->driver->getTime(), + 'app_id' => $this->driver->getAppId(), + 'peak_connection_count' => $this->driver->getPeakConnectionCount(), + 'websocket_message_count' => $this->driver->getWebsocketMessageCount(), + 'api_message_count' => $this->driver->getApiMessageCount(), ]; } diff --git a/src/Statistics/Http/Controllers/WebSocketStatisticsEntriesController.php b/src/Statistics/Http/Controllers/WebSocketStatisticsEntriesController.php index 312230a32d..bf9453bbe3 100644 --- a/src/Statistics/Http/Controllers/WebSocketStatisticsEntriesController.php +++ b/src/Statistics/Http/Controllers/WebSocketStatisticsEntriesController.php @@ -2,6 +2,7 @@ namespace BeyondCode\LaravelWebSockets\Statistics\Http\Controllers; +use BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver; use BeyondCode\LaravelWebSockets\Statistics\Events\StatisticsUpdated; use BeyondCode\LaravelWebSockets\Statistics\Rules\AppId; use Illuminate\Http\Request; @@ -12,9 +13,10 @@ class WebSocketStatisticsEntriesController * Store the entry. * * @param \Illuminate\Http\Request $request + * @param \BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver $driver * @return \Illuminate\Http\Response */ - public function store(Request $request) + public function store(Request $request, StatisticsDriver $driver) { $validatedAttributes = $request->validate([ 'app_id' => ['required', new AppId()], @@ -23,11 +25,9 @@ public function store(Request $request) 'api_message_count' => 'required|integer', ]); - $webSocketsStatisticsEntryModelClass = config('websockets.statistics.model'); - - $statisticModel = $webSocketsStatisticsEntryModelClass::create($validatedAttributes); - - broadcast(new StatisticsUpdated($statisticModel)); + broadcast(new StatisticsUpdated( + $driver::create($validatedAttributes) + )); return 'ok'; } diff --git a/src/WebSocketsServiceProvider.php b/src/WebSocketsServiceProvider.php index 8431724479..297820fab0 100644 --- a/src/WebSocketsServiceProvider.php +++ b/src/WebSocketsServiceProvider.php @@ -10,6 +10,7 @@ use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize as AuthorizeDashboard; use BeyondCode\LaravelWebSockets\PubSub\Broadcasters\RedisPusherBroadcaster; use BeyondCode\LaravelWebSockets\Server\Router; +use BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver; use BeyondCode\LaravelWebSockets\Statistics\Http\Controllers\WebSocketStatisticsEntriesController; use BeyondCode\LaravelWebSockets\Statistics\Http\Middleware\Authorize as AuthorizeStatistics; use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager; @@ -74,6 +75,16 @@ public function register() $this->app->singleton(AppManager::class, function () { return $this->app->make(config('websockets.managers.app')); }); + + $this->app->singleton(StatisticsDriver::class, function () { + $driver = config('websockets.statistics.driver'); + + return $this->app->make( + config('websockets.statistics')[$driver]['driver'] + ?? + \BeyondCode\LaravelWebSockets\Statistics\Drivers\DatabaseDriver::class + ); + }); } /**