Merge pull request #473 from beyondcode/refactor/custom-statistics-drivers

[2.x] Custom statistics drivers
This commit is contained in:
rennokki 2020-08-18 21:39:53 +03:00 committed by GitHub
commit a2fc559e0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 234 additions and 39 deletions

View File

@ -178,16 +178,25 @@ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Statistics Eloquent Model | Statistics Driver
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| This model will be used to store the statistics of the WebSocketsServer. | Here you can specify which driver to use to store the statistics to.
| The only requirement is that the model should extend | See down below for each driver's setting.
| `WebSocketsStatisticsEntry` provided by this package. |
| 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,
],
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View File

@ -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 '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 ## Event Creator
The dashboard also comes with an easy-to-use event creator, that lets you manually send events to your channels. The dashboard also comes with an easy-to-use event creator, that lets you manually send events to your channels.

View File

@ -2,9 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Console; namespace BeyondCode\LaravelWebSockets\Console;
use Carbon\Carbon; use BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;
class CleanStatistics extends Command class CleanStatistics extends Command
{ {
@ -27,25 +26,14 @@ class CleanStatistics extends Command
/** /**
* Run the command. * Run the command.
* *
* @param \BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver $driver
* @return void * @return void
*/ */
public function handle() public function handle(StatisticsDriver $driver)
{ {
$this->comment('Cleaning WebSocket Statistics...'); $this->comment('Cleaning WebSocket Statistics...');
$appId = $this->argument('appId'); $amountDeleted = $driver::delete($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();
$this->info("Deleted {$amountDeleted} record(s) from the WebSocket statistics."); $this->info("Deleted {$amountDeleted} record(s) from the WebSocket statistics.");
} }

View File

@ -0,0 +1,112 @@
<?php
namespace BeyondCode\LaravelWebSockets\Statistics\Drivers;
use Carbon\Carbon;
class DatabaseDriver implements StatisticsDriver
{
/**
* The model that controls the database table.
*
* @var \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry|null
*/
protected $record;
/**
* Initialize the driver.
*
* @param \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry|null $record
* @return void
*/
public function __construct($record = null)
{
$this->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();
}
}

View File

@ -0,0 +1,67 @@
<?php
namespace BeyondCode\LaravelWebSockets\Statistics\Drivers;
interface StatisticsDriver
{
/**
* Initialize the driver with a stored record.
*
* @param mixed $record
* @return void
*/
public function __construct($record = null);
/**
* Get the app ID for the stats.
*
* @return mixed
*/
public function getAppId();
/**
* Get the time value. Should be Y-m-d H:i:s.
*
* @return string
*/
public function getTime(): string;
/**
* Get the peak connection count for the time.
*
* @return int
*/
public function getPeakConnectionCount(): int;
/**
* Get the websocket messages count for the time.
*
* @return int
*/
public function getWebsocketMessageCount(): int;
/**
* Get the API message count for the time.
*
* @return int
*/
public function getApiMessageCount(): int;
/**
* Create a new statistic in the store.
*
* @param array $data
* @return \BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver
*/
public static function create(array $data): StatisticsDriver;
/**
* 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;
}

View File

@ -3,7 +3,7 @@
namespace BeyondCode\LaravelWebSockets\Statistics\Events; namespace BeyondCode\LaravelWebSockets\Statistics\Events;
use BeyondCode\LaravelWebSockets\Dashboard\DashboardLogger; use BeyondCode\LaravelWebSockets\Dashboard\DashboardLogger;
use BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry; use BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver;
use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
@ -14,21 +14,21 @@ class StatisticsUpdated implements ShouldBroadcast
use SerializesModels; use SerializesModels;
/** /**
* The statistic instance that got updated. * The statistics driver instance.
* *
* @var \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry * @var \BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver
*/ */
protected $webSocketsStatisticsEntry; protected $driver;
/** /**
* Initialize the event. * Initialize the event.
* *
* @param \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry $webSocketsStatisticsEntry * @param \BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver $driver
* @return void * @return void
*/ */
public function __construct(WebSocketsStatisticsEntry $webSocketsStatisticsEntry) public function __construct(StatisticsDriver $driver)
{ {
$this->webSocketsStatisticsEntry = $webSocketsStatisticsEntry; $this->driver = $driver;
} }
/** /**
@ -39,11 +39,11 @@ class StatisticsUpdated implements ShouldBroadcast
public function broadcastWith() public function broadcastWith()
{ {
return [ return [
'time' => (string) $this->webSocketsStatisticsEntry->created_at, 'time' => $this->driver->getTime(),
'app_id' => $this->webSocketsStatisticsEntry->app_id, 'app_id' => $this->driver->getAppId(),
'peak_connection_count' => $this->webSocketsStatisticsEntry->peak_connection_count, 'peak_connection_count' => $this->driver->getPeakConnectionCount(),
'websocket_message_count' => $this->webSocketsStatisticsEntry->websocket_message_count, 'websocket_message_count' => $this->driver->getWebsocketMessageCount(),
'api_message_count' => $this->webSocketsStatisticsEntry->api_message_count, 'api_message_count' => $this->driver->getApiMessageCount(),
]; ];
} }

View File

@ -2,6 +2,7 @@
namespace BeyondCode\LaravelWebSockets\Statistics\Http\Controllers; namespace BeyondCode\LaravelWebSockets\Statistics\Http\Controllers;
use BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver;
use BeyondCode\LaravelWebSockets\Statistics\Events\StatisticsUpdated; use BeyondCode\LaravelWebSockets\Statistics\Events\StatisticsUpdated;
use BeyondCode\LaravelWebSockets\Statistics\Rules\AppId; use BeyondCode\LaravelWebSockets\Statistics\Rules\AppId;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@ -12,9 +13,10 @@ class WebSocketStatisticsEntriesController
* Store the entry. * Store the entry.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param \BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver $driver
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function store(Request $request) public function store(Request $request, StatisticsDriver $driver)
{ {
$validatedAttributes = $request->validate([ $validatedAttributes = $request->validate([
'app_id' => ['required', new AppId()], 'app_id' => ['required', new AppId()],
@ -23,11 +25,9 @@ class WebSocketStatisticsEntriesController
'api_message_count' => 'required|integer', 'api_message_count' => 'required|integer',
]); ]);
$webSocketsStatisticsEntryModelClass = config('websockets.statistics.model'); broadcast(new StatisticsUpdated(
$driver::create($validatedAttributes)
$statisticModel = $webSocketsStatisticsEntryModelClass::create($validatedAttributes); ));
broadcast(new StatisticsUpdated($statisticModel));
return 'ok'; return 'ok';
} }

View File

@ -10,6 +10,7 @@ use BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers\ShowDashboard;
use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize as AuthorizeDashboard; use BeyondCode\LaravelWebSockets\Dashboard\Http\Middleware\Authorize as AuthorizeDashboard;
use BeyondCode\LaravelWebSockets\PubSub\Broadcasters\RedisPusherBroadcaster; use BeyondCode\LaravelWebSockets\PubSub\Broadcasters\RedisPusherBroadcaster;
use BeyondCode\LaravelWebSockets\Server\Router; use BeyondCode\LaravelWebSockets\Server\Router;
use BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver;
use BeyondCode\LaravelWebSockets\Statistics\Http\Controllers\WebSocketStatisticsEntriesController; use BeyondCode\LaravelWebSockets\Statistics\Http\Controllers\WebSocketStatisticsEntriesController;
use BeyondCode\LaravelWebSockets\Statistics\Http\Middleware\Authorize as AuthorizeStatistics; use BeyondCode\LaravelWebSockets\Statistics\Http\Middleware\Authorize as AuthorizeStatistics;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager; use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
@ -74,6 +75,16 @@ class WebSocketsServiceProvider extends ServiceProvider
$this->app->singleton(AppManager::class, function () { $this->app->singleton(AppManager::class, function () {
return $this->app->make(config('websockets.managers.app')); 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
);
});
} }
/** /**