Skip to content
This repository was archived by the owner on Feb 7, 2024. It is now read-only.

[2.x] Custom statistics drivers #473

Merged
merged 2 commits into from
Aug 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions config/websockets.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,

],

/*
|--------------------------------------------------------------------------
Expand Down
8 changes: 8 additions & 0 deletions docs/debugging/dashboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
20 changes: 4 additions & 16 deletions src/Console/CleanStatistics.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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.");
}
Expand Down
112 changes: 112 additions & 0 deletions src/Statistics/Drivers/DatabaseDriver.php
Original file line number Diff line number Diff line change
@@ -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();
}
}
67 changes: 67 additions & 0 deletions src/Statistics/Drivers/StatisticsDriver.php
Original file line number Diff line number Diff line change
@@ -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;
}
24 changes: 12 additions & 12 deletions src/Statistics/Events/StatisticsUpdated.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace BeyondCode\LaravelWebSockets\Statistics\Events;

use BeyondCode\LaravelWebSockets\Dashboard\DashboardLogger;
use BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry;
use BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;
Expand All @@ -14,21 +14,21 @@ class StatisticsUpdated implements ShouldBroadcast
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.
*
* @param \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry $webSocketsStatisticsEntry
* @param \BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver $driver
* @return void
*/
public function __construct(WebSocketsStatisticsEntry $webSocketsStatisticsEntry)
public function __construct(StatisticsDriver $driver)
{
$this->webSocketsStatisticsEntry = $webSocketsStatisticsEntry;
$this->driver = $driver;
}

/**
Expand All @@ -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(),
];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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()],
Expand All @@ -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';
}
Expand Down
11 changes: 11 additions & 0 deletions src/WebSocketsServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
);
});
}

/**
Expand Down