Replacing event with continously statistics polling

This commit is contained in:
Alex Renoki 2020-08-20 11:27:55 +03:00
parent f9cf723c0e
commit 70ce44e635
7 changed files with 118 additions and 125 deletions

View File

@ -84,8 +84,28 @@
v-if="connected && app.statisticsEnabled"
class="w-full my-6 px-6"
>
<div class="font-semibold uppercase text-gray-700">
<div class="flex justify-between items-center">
<span class="font-semibold uppercase text-gray-700">
Live statistics
</span>
<div class="space-x-3 flex items-center">
<div>
<input
type="checkbox"
v-model="autoRefresh"
class="mr-2"
/>
Refresh automatically
</div>
<button
@click="loadChart"
class="rounded-full bg-blue-500 hover:bg-blue-600 focus:outline-none text-white px-3 py-1"
>
Refresh
</button>
</div>
</div>
<div
@ -222,6 +242,9 @@
connected: false,
connecting: false,
sendingEvent: false,
autoRefresh: true,
refreshInterval: {{ $refreshInterval }},
refreshTicker: null,
chart: null,
pusher: null,
app: null,
@ -236,6 +259,19 @@
mounted () {
this.app = this.apps[0] || null;
},
destroyed () {
if (this.refreshTicker) {
this.clearRefreshInterval();
}
},
watch: {
connected (newVal) {
newVal ? this.startRefreshInterval() : this.clearRefreshInterval();
},
autoRefresh (newVal) {
newVal ? this.startRefreshInterval() : this.clearRefreshInterval();
},
},
methods: {
connect () {
this.connecting = true;
@ -274,12 +310,14 @@
this.connected = false;
this.connecting = false;
this.logs = [];
this.chart = null;
});
this.pusher.connection.bind('error', event => {
if (event.error.data.code === 4100) {
this.connected = false;
this.logs = [];
this.chart = null;
throw new Error("Over capacity");
}
@ -288,12 +326,12 @@
});
this.subscribeToAllChannels();
this.subscribeToStatistics();
},
disconnect () {
this.pusher.disconnect();
this.connecting = false;
this.chart = null;
},
loadChart () {
@ -333,7 +371,10 @@
autosize: true,
};
this.chart = Plotly.newPlot('statisticsChart', chartData, layout);
this.chart = this.chart
? Plotly.react('statisticsChart', chartData, layout)
: Plotly.newPlot('statisticsChart', chartData, layout);
});
},
@ -348,18 +389,6 @@
});
},
subscribeToStatistics () {
this.pusher.subscribe('{{ $logPrefix }}statistics')
.bind('statistics-updated', (data) => {
var update = {
x: [[data.time], [data.time], [data.time]],
y: [[data.peak_connection_count], [data.websocket_message_count], [data.api_message_count]],
};
Plotly.extendTraces('statisticsChart', update, [0, 1, 2]);
});
},
sendEvent () {
if (! this.sendingEvent) {
this.sendingEvent = true;
@ -415,6 +444,17 @@
return 'bg-gray-700 text-white';
},
startRefreshInterval () {
this.refreshTicker = setInterval(function () {
this.loadChart();
}.bind(this), this.refreshInterval * 1000);
},
stopRefreshInterval () {
clearInterval(this.refreshTicker);
this.refreshTicker = null;
},
},
});
</script>

View File

@ -2,45 +2,21 @@
namespace BeyondCode\LaravelWebSockets\Dashboard\Http\Controllers;
use BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver;
use Illuminate\Http\Request;
class DashboardApiController
{
/**
* Get statistics for an app ID.
*
* @param \Illuminate\Http\Request $request
* @param \BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver $driver
* @param mixed $appId
* @return \Illuminate\Http\Response
*/
public function getStatistics($appId)
public function getStatistics(Request $request, StatisticsDriver $driver, $appId)
{
$model = config('websockets.statistics.model');
$statistics = $model::where('app_id', $appId)
->latest()
->limit(120)
->get();
$statisticData = $statistics->map(function ($statistic) {
return [
'timestamp' => (string) $statistic->created_at,
'peak_connection_count' => $statistic->peak_connection_count,
'websocket_message_count' => $statistic->websocket_message_count,
'api_message_count' => $statistic->api_message_count,
];
})->reverse();
return [
'peak_connections' => [
'x' => $statisticData->pluck('timestamp'),
'y' => $statisticData->pluck('peak_connection_count'),
],
'websocket_message_count' => [
'x' => $statisticData->pluck('timestamp'),
'y' => $statisticData->pluck('websocket_message_count'),
],
'api_message_count' => [
'x' => $statisticData->pluck('timestamp'),
'y' => $statisticData->pluck('api_message_count'),
],
];
return $driver::get($appId, $request);
}
}

View File

@ -22,6 +22,7 @@ class ShowDashboard
'port' => config('websockets.dashboard.port', 6001),
'channels' => DashboardLogger::$channels,
'logPrefix' => DashboardLogger::LOG_CHANNEL_PREFIX,
'refreshInterval' => config('websockets.statistics.interval_in_seconds'),
]);
}
}

View File

@ -3,6 +3,7 @@
namespace BeyondCode\LaravelWebSockets\Statistics\Drivers;
use Carbon\Carbon;
use Illuminate\Http\Request;
class DatabaseDriver implements StatisticsDriver
{
@ -87,6 +88,46 @@ class DatabaseDriver implements StatisticsDriver
return new static($class::create($data));
}
/**
* Get the records to show to the dashboard.
*
* @param mixed $appId
* @param \Illuminate\Http\Request $request
* @return array
*/
public static function get($appId, Request $request): array
{
$class = config('websockets.statistics.database.model');
$statistics = $class::whereAppId($appId)
->latest()
->limit(120)
->get()
->map(function ($statistic) {
return [
'timestamp' => (string) $statistic->created_at,
'peak_connection_count' => $statistic->peak_connection_count,
'websocket_message_count' => $statistic->websocket_message_count,
'api_message_count' => $statistic->api_message_count,
];
})->reverse();
return [
'peak_connections' => [
'x' => $statistics->pluck('timestamp'),
'y' => $statistics->pluck('peak_connection_count'),
],
'websocket_message_count' => [
'x' => $statistics->pluck('timestamp'),
'y' => $statistics->pluck('websocket_message_count'),
],
'api_message_count' => [
'x' => $statistics->pluck('timestamp'),
'y' => $statistics->pluck('api_message_count'),
],
];
}
/**
* Delete statistics from the store,
* optionally by app id, returning

View File

@ -2,6 +2,8 @@
namespace BeyondCode\LaravelWebSockets\Statistics\Drivers;
use Illuminate\Http\Request;
interface StatisticsDriver
{
/**
@ -55,6 +57,15 @@ interface StatisticsDriver
*/
public static function create(array $data): StatisticsDriver;
/**
* Get the records to show to the dashboard.
*
* @param mixed $appId
* @param \Illuminate\Http\Request $request
* @return void
*/
public static function get($appId, Request $request);
/**
* Delete statistics from the store,
* optionally by app id, returning

View File

@ -1,73 +0,0 @@
<?php
namespace BeyondCode\LaravelWebSockets\Statistics\Events;
use BeyondCode\LaravelWebSockets\Dashboard\DashboardLogger;
use BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Str;
class StatisticsUpdated implements ShouldBroadcast
{
use SerializesModels;
/**
* The statistics driver instance.
*
* @var \BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver
*/
protected $driver;
/**
* Initialize the event.
*
* @param \BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver $driver
* @return void
*/
public function __construct(StatisticsDriver $driver)
{
$this->driver = $driver;
}
/**
* Format the broadcasting message.
*
* @return array
*/
public function broadcastWith()
{
return [
'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(),
];
}
/**
* Specify the channel to broadcast on.
*
* @return \Illuminate\Broadcasting\Channel
*/
public function broadcastOn()
{
$channelName = Str::after(DashboardLogger::LOG_CHANNEL_PREFIX.'statistics', 'private-');
return new PrivateChannel(
Str::after(DashboardLogger::LOG_CHANNEL_PREFIX.'statistics', 'private-')
);
}
/**
* Define the broadcasted event name.
*
* @return string
*/
public function broadcastAs()
{
return 'statistics-updated';
}
}

View File

@ -4,7 +4,6 @@ namespace BeyondCode\LaravelWebSockets\Statistics\Logger;
use BeyondCode\LaravelWebSockets\Apps\App;
use BeyondCode\LaravelWebSockets\Statistics\Drivers\StatisticsDriver;
use BeyondCode\LaravelWebSockets\Statistics\Events\StatisticsUpdated;
use BeyondCode\LaravelWebSockets\Statistics\Statistic;
use BeyondCode\LaravelWebSockets\WebSockets\Channels\ChannelManager;
use Ratchet\ConnectionInterface;
@ -105,9 +104,7 @@ class MemoryStatisticsLogger implements StatisticsLogger
continue;
}
/* broadcast(new StatisticsUpdated(
$this->driver::create($statistic->toArray())
)); */
$this->driver::create($statistic->toArray());
$currentConnectionCount = $this->channelManager->getConnectionCount($appId);