Merge branch 'master' of github.com:beyondcode/laravel-websockets
This commit is contained in:
commit
dd283c66d1
|
|
@ -42,10 +42,19 @@ return [
|
||||||
*/
|
*/
|
||||||
'max_request_size_in_kb' => 250,
|
'max_request_size_in_kb' => 250,
|
||||||
|
|
||||||
/*
|
'statistics' => [
|
||||||
* This model will be used to store the statistics of the WebSocketsServer
|
/*
|
||||||
*/
|
* This model will be used to store the statistics of the WebSocketsServer.
|
||||||
'statistics_model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class,
|
* The only requirement is that the model should be or extend
|
||||||
|
* `WebSocketsStatisticsEntry` provided by this package.
|
||||||
|
*/
|
||||||
|
'model' => \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry::class,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here you can specify the interval in seconds at which statistics should be logged.
|
||||||
|
*/
|
||||||
|
'interval_in_seconds' => 60,
|
||||||
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define the optional SSL context for your WebSocket connections.
|
* Define the optional SSL context for your WebSocket connections.
|
||||||
|
|
|
||||||
|
|
@ -53,12 +53,11 @@ class StartWebSocketServer extends Command
|
||||||
|
|
||||||
$browser = new Browser($this->loop, $connector);
|
$browser = new Browser($this->loop, $connector);
|
||||||
|
|
||||||
|
|
||||||
app()->singleton(StatisticsLoggerInterface::class, function() use ($browser) {
|
app()->singleton(StatisticsLoggerInterface::class, function() use ($browser) {
|
||||||
return new HttpStatisticsLogger(app(ChannelManager::class), $browser);
|
return new HttpStatisticsLogger(app(ChannelManager::class), $browser);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->loop->addPeriodicTimer(5, function() {
|
$this->loop->addPeriodicTimer(config('websockets.statistics.interval_in_seconds'), function() {
|
||||||
StatisticsLogger::save();
|
StatisticsLogger::save();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +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 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;
|
||||||
|
|
@ -11,27 +12,30 @@ class StatisticsUpdated implements ShouldBroadcast
|
||||||
{
|
{
|
||||||
use SerializesModels;
|
use SerializesModels;
|
||||||
|
|
||||||
public $statisticModel;
|
/** @var \BeyondCode\LaravelWebSockets\Statistics\Models\WebSocketsStatisticsEntry */
|
||||||
|
protected $webSocketsStatisticsEntry;
|
||||||
|
|
||||||
public function __construct($statisticModel)
|
public function __construct(WebSocketsStatisticsEntry $webSocketsStatisticsEntry)
|
||||||
{
|
{
|
||||||
$this->statisticModel = $statisticModel;
|
$this->webSocketsStatisticsEntry = $webSocketsStatisticsEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function broadcastWith()
|
public function broadcastWith()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'time' => (string)$this->statisticModel->created_at,
|
'time' => $this->webSocketsStatisticsEntry->created_at->timestamp,
|
||||||
'app_id' => $this->statisticModel->app_id,
|
'app_id' => $this->webSocketsStatisticsEntry->appId,
|
||||||
'peak_connection_count' => $this->statisticModel->peak_connection_count,
|
'peak_connection_count' => $this->webSocketsStatisticsEntry->peakConnectionCount,
|
||||||
'websocket_message_count' => $this->statisticModel->websocket_message_count,
|
'websocket_message_count' => $this->webSocketsStatisticsEntry->webSocketMessageCount,
|
||||||
'api_message_count' => $this->statisticModel->api_message_count,
|
'api_message_count' => $this->webSocketsStatisticsEntry->apiMessageCount,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function broadcastOn()
|
public function broadcastOn()
|
||||||
{
|
{
|
||||||
return new PrivateChannel(str_after(DashboardLogger::LOG_CHANNEL_PREFIX . 'statistics', 'private-'));
|
$channelName = str_after(DashboardLogger::LOG_CHANNEL_PREFIX . 'statistics', 'private-');
|
||||||
|
|
||||||
|
return new PrivateChannel($channelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function broadcastAs()
|
public function broadcastAs()
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class WebSocketStatisticsEntriesController
|
||||||
'api_message_count' => 'required|integer',
|
'api_message_count' => 'required|integer',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$webSocketsStatisticsEntryModelClass = config('websockets.statistics_model');
|
$webSocketsStatisticsEntryModelClass = config('websockets.statistics.model');
|
||||||
|
|
||||||
$statisticModel = $webSocketsStatisticsEntryModelClass::create($validatedAttributes);
|
$statisticModel = $webSocketsStatisticsEntryModelClass::create($validatedAttributes);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,13 @@ use Ratchet\ConnectionInterface;
|
||||||
|
|
||||||
class HttpStatisticsLogger implements StatisticsLogger
|
class HttpStatisticsLogger implements StatisticsLogger
|
||||||
{
|
{
|
||||||
/** @var Statistic[] */
|
/** @var \BeyondCode\LaravelWebSockets\Statistics\Statistic[] */
|
||||||
protected $statistics = [];
|
protected $statistics = [];
|
||||||
|
|
||||||
/** @var \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager */
|
/** @var \BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager */
|
||||||
protected $channelManager;
|
protected $channelManager;
|
||||||
|
|
||||||
/** @var Browser */
|
/** @var \Clue\React\Buzz\Browser */
|
||||||
protected $browser;
|
protected $browser;
|
||||||
|
|
||||||
public function __construct(ChannelManager $channelManager, Browser $browser)
|
public function __construct(ChannelManager $channelManager, Browser $browser)
|
||||||
|
|
@ -29,37 +29,39 @@ class HttpStatisticsLogger implements StatisticsLogger
|
||||||
|
|
||||||
public function webSocketMessage(ConnectionInterface $connection)
|
public function webSocketMessage(ConnectionInterface $connection)
|
||||||
{
|
{
|
||||||
$this->initializeStatistics($connection->app->id);
|
$this
|
||||||
|
->findOrMakeStatisticForAppId($connection->app->id)
|
||||||
$this->statistics[$connection->app->id]->webSocketMessage();
|
->webSocketMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function apiMessage($appId)
|
public function apiMessage($appId)
|
||||||
{
|
{
|
||||||
$this->initializeStatistics($appId);
|
$this
|
||||||
|
->findOrMakeStatisticForAppId($appId)
|
||||||
$this->statistics[$appId]->apiMessage();
|
->apiMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function connection(ConnectionInterface $connection)
|
public function connection(ConnectionInterface $connection)
|
||||||
{
|
{
|
||||||
$this->initializeStatistics($connection->app->id);
|
$this
|
||||||
|
->findOrMakeStatisticForAppId($connection->app->id)
|
||||||
$this->statistics[$connection->app->id]->connection();
|
->connection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function disconnection(ConnectionInterface $connection)
|
public function disconnection(ConnectionInterface $connection)
|
||||||
{
|
{
|
||||||
$this->initializeStatistics($connection->app->id);
|
$this
|
||||||
|
->findOrMakeStatisticForAppId($connection->app->id)
|
||||||
$this->statistics[$connection->app->id]->disconnection();
|
->disconnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function initializeStatistics($id)
|
protected function findOrMakeStatisticForAppId($appId): Statistic
|
||||||
{
|
{
|
||||||
if (!isset($this->statistics[$id])) {
|
if (!isset($this->statistics[$appId])) {
|
||||||
$this->statistics[$id] = new Statistic($id);
|
$this->statistics[$appId] = new Statistic($appId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this->statistics[$appId];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function save()
|
public function save()
|
||||||
|
|
@ -70,19 +72,15 @@ class HttpStatisticsLogger implements StatisticsLogger
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->browser
|
$this
|
||||||
|
->browser
|
||||||
->post(
|
->post(
|
||||||
action([WebSocketStatisticsEntriesController::class, 'store']),
|
action([WebSocketStatisticsEntriesController::class, 'store']),
|
||||||
['Content-Type' => 'application/json'],
|
['Content-Type' => 'application/json'],
|
||||||
stream_for(json_encode($statistic->toArray()))
|
stream_for(json_encode($statistic->toArray()))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Reset connection and message count
|
$currentConnectionCount = $this->channelManager->getConnectionCount($appId);
|
||||||
$currentConnectionCount = collect($this->channelManager->getChannels($appId))
|
|
||||||
->sum(function ($channel) {
|
|
||||||
return count($channel->getSubscribedConnections());
|
|
||||||
});
|
|
||||||
|
|
||||||
$statistic->reset($currentConnectionCount);
|
$statistic->reset($currentConnectionCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,12 @@ class ChannelManager
|
||||||
return $this->channels[$appId] ?? [];
|
return $this->channels[$appId] ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getConnectionCount(string $appId): int
|
||||||
|
{
|
||||||
|
return collect($this->getChannels($appId))
|
||||||
|
->sum->getSubscribedConnections();
|
||||||
|
}
|
||||||
|
|
||||||
public function removeFromAllChannels(ConnectionInterface $connection)
|
public function removeFromAllChannels(ConnectionInterface $connection)
|
||||||
{
|
{
|
||||||
if (!isset($connection->app)) {
|
if (!isset($connection->app)) {
|
||||||
|
|
|
||||||
|
|
@ -22,22 +22,21 @@ class WebSocketsServiceProvider extends ServiceProvider
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
$this->publishes([
|
$this->publishes([
|
||||||
__DIR__.'/../config/websockets.php' => base_path('config/websockets.php'),
|
__DIR__ . '/../config/websockets.php' => base_path('config/websockets.php'),
|
||||||
], 'config');
|
], 'config');
|
||||||
|
|
||||||
if (! class_exists('CreateWebSocketsStatisticsEntries')) {
|
if (!class_exists('CreateWebSocketsStatisticsEntries')) {
|
||||||
$this->publishes([
|
$this->publishes([
|
||||||
__DIR__.'/../database/migrations/create_websockets_statistics_entries_table.php.stub' => database_path('migrations/'.date('Y_m_d_His', time()).'_create_websockets_statistics_entries_table.php'),
|
__DIR__ . '/../database/migrations/create_websockets_statistics_entries_table.php.stub' => database_path('migrations/' . date('Y_m_d_His', time()) . '_create_websockets_statistics_entries_table.php'),
|
||||||
], 'migrations');
|
], 'migrations');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->registerRouteMacro();
|
$this
|
||||||
|
->registerRouteMacro()
|
||||||
|
->registerStatisticRoute()
|
||||||
|
->registerDashboardGate();
|
||||||
|
|
||||||
$this->registerStatisticRoute();
|
$this->loadViewsFrom(__DIR__ . '/../resources/views/', 'websockets');
|
||||||
|
|
||||||
$this->registerDashboardGate();
|
|
||||||
|
|
||||||
$this->loadViewsFrom(__DIR__.'/../resources/views/', 'websockets');
|
|
||||||
|
|
||||||
$this->commands([
|
$this->commands([
|
||||||
Console\StartWebSocketServer::class,
|
Console\StartWebSocketServer::class,
|
||||||
|
|
@ -46,38 +45,42 @@ class WebSocketsServiceProvider extends ServiceProvider
|
||||||
|
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
$this->mergeConfigFrom(__DIR__.'/../config/websockets.php', 'websockets');
|
$this->mergeConfigFrom(__DIR__ . '/../config/websockets.php', 'websockets');
|
||||||
|
|
||||||
$this->app->singleton('websockets.router', function() {
|
$this->app->singleton('websockets.router', function () {
|
||||||
return new Router();
|
return new Router();
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->app->singleton(ChannelManager::class, function() {
|
$this->app->singleton(ChannelManager::class, function () {
|
||||||
return new ChannelManager();
|
return new ChannelManager();
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->app->singleton(AppProvider::class, function() {
|
$this->app->singleton(AppProvider::class, function () {
|
||||||
return app(config('websockets.app_provider'));
|
return app(config('websockets.app_provider'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function registerRouteMacro()
|
protected function registerRouteMacro()
|
||||||
{
|
{
|
||||||
Route::macro('webSockets', function($prefix = 'laravel-websockets') {
|
Route::macro('webSockets', function ($prefix = 'laravel-websockets') {
|
||||||
Route::prefix($prefix)->namespace('\\')->middleware(Authorize::class)->group(function() {
|
Route::prefix($prefix)->namespace('\\')->middleware(Authorize::class)->group(function () {
|
||||||
Route::get('/', ShowDashboard::class);
|
Route::get('/', ShowDashboard::class);
|
||||||
Route::get('/api/{appId}/statistics', DashboardApiController::class.'@getStatistics');
|
Route::get('/api/{appId}/statistics', DashboardApiController::class . '@getStatistics');
|
||||||
Route::post('auth', AuthenticateDashboard::class);
|
Route::post('auth', AuthenticateDashboard::class);
|
||||||
Route::post('event', SendMessage::class);
|
Route::post('event', SendMessage::class);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function registerStatisticRoute()
|
protected function registerStatisticRoute()
|
||||||
{
|
{
|
||||||
Route::prefix('/laravel-websockets')->namespace('\\')->group(function() {
|
Route::prefix('/laravel-websockets')->namespace('\\')->group(function () {
|
||||||
Route::post('statistics', [WebSocketStatisticsEntriesController::class, 'store']);
|
Route::post('statistics', [WebSocketStatisticsEntriesController::class, 'store']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function registerDashboardGate()
|
protected function registerDashboardGate()
|
||||||
|
|
@ -85,5 +88,7 @@ class WebSocketsServiceProvider extends ServiceProvider
|
||||||
Gate::define('viewWebSocketsDashboard', function ($user = null) {
|
Gate::define('viewWebSocketsDashboard', function ($user = null) {
|
||||||
return app()->environment('local');
|
return app()->environment('local');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue