Skip to content

Commit e3d4c01

Browse files
committed
wip
1 parent dbdaff8 commit e3d4c01

File tree

4 files changed

+80
-64
lines changed

4 files changed

+80
-64
lines changed

src/Commands/CheckCommand.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Illuminate\Contracts\Cache\LockProvider;
99
use Illuminate\Events\Dispatcher;
1010
use Illuminate\Support\Sleep;
11+
use Illuminate\Support\Str;
1112
use Laravel\Pulse\Events\IsolatedBeat;
1213
use Laravel\Pulse\Events\SharedBeat;
1314
use Laravel\Pulse\Pulse;
@@ -48,6 +49,8 @@ public function handle(
4849
? $store->lock('laravel:pulse:check', 5)
4950
: null;
5051

52+
$key = Str::random();
53+
5154
while (true) {
5255
$now = CarbonImmutable::now();
5356

@@ -59,7 +62,7 @@ public function handle(
5962
$event->dispatch(new IsolatedBeat($now));
6063
}
6164

62-
$event->dispatch(new SharedBeat($now));
65+
$event->dispatch(new SharedBeat($now, $key));
6366

6467
$pulse->ingest();
6568

src/Events/SharedBeat.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class SharedBeat
1212
*/
1313
public function __construct(
1414
public CarbonImmutable $time,
15+
public string $key,
1516
) {
1617
//
1718
}

src/Recorders/Concerns/Intervals.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Laravel\Pulse\Recorders\Concerns;
4+
5+
use DateInterval;
6+
use DateTimeInterface;
7+
use Illuminate\Support\Facades\App;
8+
use Illuminate\Support\Facades\RateLimiter;
9+
use Illuminate\Support\Str;
10+
use Laravel\Pulse\Events\IsolatedBeat;
11+
use Laravel\Pulse\Events\SharedBeat;
12+
use Laravel\Pulse\Support\CacheStoreResolver;
13+
14+
trait Intervals
15+
{
16+
/**
17+
* Determine if the recorder is ready to record another snapshot.
18+
*/
19+
protected function throttle(DateInterval|int $interval, SharedBeat|IsolatedBeat $event, callable $callback, ?string $key = null): void
20+
{
21+
if ($event instanceof SharedBeat) {
22+
$key = $event->key.($key === null ? '' : ":{$key}");
23+
}
24+
25+
RateLimiter::attempt($key, 1, fn () => $callback($event), $this->secondsUntil($interval));
26+
}
27+
}

src/Recorders/Servers.php

Lines changed: 48 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@
22

33
namespace Laravel\Pulse\Recorders;
44

5+
use Carbon\CarbonInterval as Interval;
6+
use DateInterval;
7+
use DateTimeInterface;
58
use Illuminate\Config\Repository;
9+
use Illuminate\Support\Facades\App;
10+
use Illuminate\Support\InteractsWithTime;
611
use Illuminate\Support\Str;
12+
use Laravel\Pulse\Events\IsolatedBeat;
713
use Laravel\Pulse\Events\SharedBeat;
814
use Laravel\Pulse\Pulse;
915
use Laravel\Pulse\Support\CacheStoreResolver;
@@ -14,6 +20,8 @@
1420
*/
1521
class Servers
1622
{
23+
use InteractsWithTime, Concerns\Intervals;
24+
1725
/**
1826
* The events to listen for.
1927
*
@@ -37,73 +45,50 @@ public function __construct(
3745
*/
3846
public function record(SharedBeat $event): void
3947
{
40-
if (! $this->readyToRecord($event)) {
41-
return;
42-
}
43-
44-
$server = $this->config->get('pulse.recorders.'.self::class.'.server_name');
45-
$slug = Str::slug($server);
48+
$this->throttle(Interval::seconds(15), $event, function ($event) {
49+
echo 'checking'.PHP_EOL.now()->toDateTimeString().PHP_EOL;
50+
$server = $this->config->get('pulse.recorders.'.self::class.'.server_name');
51+
$slug = Str::slug($server);
4652

47-
$memoryTotal = match (PHP_OS_FAMILY) {
48-
'Darwin' => intval(`sysctl hw.memsize | grep -Eo '[0-9]+'` / 1024 / 1024),
49-
'Linux' => intval(`cat /proc/meminfo | grep MemTotal | grep -E -o '[0-9]+'` / 1024),
50-
'Windows' => intval(((int) trim(`wmic ComputerSystem get TotalPhysicalMemory | more +1`)) / 1024 / 1024),
51-
'BSD' => intval(`sysctl hw.physmem | grep -Eo '[0-9]+'` / 1024 / 1024),
52-
default => throw new RuntimeException('The pulse:check command does not currently support '.PHP_OS_FAMILY),
53-
};
53+
$memoryTotal = match (PHP_OS_FAMILY) {
54+
'Darwin' => intval(`sysctl hw.memsize | grep -Eo '[0-9]+'` / 1024 / 1024),
55+
'Linux' => intval(`cat /proc/meminfo | grep MemTotal | grep -E -o '[0-9]+'` / 1024),
56+
'Windows' => intval(((int) trim(`wmic ComputerSystem get TotalPhysicalMemory | more +1`)) / 1024 / 1024),
57+
'BSD' => intval(`sysctl hw.physmem | grep -Eo '[0-9]+'` / 1024 / 1024),
58+
default => throw new RuntimeException('The pulse:check command does not currently support '.PHP_OS_FAMILY),
59+
};
5460

55-
$memoryUsed = match (PHP_OS_FAMILY) {
56-
'Darwin' => $memoryTotal - intval(intval(`vm_stat | grep 'Pages free' | grep -Eo '[0-9]+'`) * intval(`pagesize`) / 1024 / 1024), // MB
57-
'Linux' => $memoryTotal - intval(`cat /proc/meminfo | grep MemAvailable | grep -E -o '[0-9]+'` / 1024), // MB
58-
'Windows' => $memoryTotal - intval(((int) trim(`wmic OS get FreePhysicalMemory | more +1`)) / 1024), // MB
59-
'BSD' => intval(intval(`( sysctl vm.stats.vm.v_cache_count | grep -Eo '[0-9]+' ; sysctl vm.stats.vm.v_inactive_count | grep -Eo '[0-9]+' ; sysctl vm.stats.vm.v_active_count | grep -Eo '[0-9]+' ) | awk '{s+=$1} END {print s}'`) * intval(`pagesize`) / 1024 / 1024), // MB
60-
default => throw new RuntimeException('The pulse:check command does not currently support '.PHP_OS_FAMILY),
61-
};
61+
$memoryUsed = match (PHP_OS_FAMILY) {
62+
'Darwin' => $memoryTotal - intval(intval(`vm_stat | grep 'Pages free' | grep -Eo '[0-9]+'`) * intval(`pagesize`) / 1024 / 1024), // MB
63+
'Linux' => $memoryTotal - intval(`cat /proc/meminfo | grep MemAvailable | grep -E -o '[0-9]+'` / 1024), // MB
64+
'Windows' => $memoryTotal - intval(((int) trim(`wmic OS get FreePhysicalMemory | more +1`)) / 1024), // MB
65+
'BSD' => intval(intval(`( sysctl vm.stats.vm.v_cache_count | grep -Eo '[0-9]+' ; sysctl vm.stats.vm.v_inactive_count | grep -Eo '[0-9]+' ; sysctl vm.stats.vm.v_active_count | grep -Eo '[0-9]+' ) | awk '{s+=$1} END {print s}'`) * intval(`pagesize`) / 1024 / 1024), // MB
66+
default => throw new RuntimeException('The pulse:check command does not currently support '.PHP_OS_FAMILY),
67+
};
6268

63-
$cpu = match (PHP_OS_FAMILY) {
64-
'Darwin' => (int) `top -l 1 | grep -E "^CPU" | tail -1 | awk '{ print $3 + $5 }'`,
65-
'Linux' => (int) `top -bn1 | grep -E '^(%Cpu|CPU)' | awk '{ print $2 + $4 }'`,
66-
'Windows' => (int) trim(`wmic cpu get loadpercentage | more +1`),
67-
'BSD' => (int) `top -b -d 2| grep 'CPU: ' | tail -1 | awk '{print$10}' | grep -Eo '[0-9]+\.[0-9]+' | awk '{ print 100 - $1 }'`,
68-
default => throw new RuntimeException('The pulse:check command does not currently support '.PHP_OS_FAMILY),
69-
};
69+
$cpu = match (PHP_OS_FAMILY) {
70+
'Darwin' => (int) `top -l 1 | grep -E "^CPU" | tail -1 | awk '{ print $3 + $5 }'`,
71+
'Linux' => (int) `top -bn1 | grep -E '^(%Cpu|CPU)' | awk '{ print $2 + $4 }'`,
72+
'Windows' => (int) trim(`wmic cpu get loadpercentage | more +1`),
73+
'BSD' => (int) `top -b -d 2| grep 'CPU: ' | tail -1 | awk '{print$10}' | grep -Eo '[0-9]+\.[0-9]+' | awk '{ print 100 - $1 }'`,
74+
default => throw new RuntimeException('The pulse:check command does not currently support '.PHP_OS_FAMILY),
75+
};
7076

71-
$this->pulse->record('cpu', $slug, $cpu, $event->time)->avg()->onlyBuckets();
72-
$this->pulse->record('memory', $slug, $memoryUsed, $event->time)->avg()->onlyBuckets();
73-
$this->pulse->set('system', $slug, json_encode([
74-
'name' => $server,
75-
'cpu' => $cpu,
76-
'memory_used' => $memoryUsed,
77-
'memory_total' => $memoryTotal,
78-
'storage' => collect($this->config->get('pulse.recorders.'.self::class.'.directories')) // @phpstan-ignore argument.templateType argument.templateType
79-
->map(fn (string $directory) => [
80-
'directory' => $directory,
81-
'total' => $total = intval(round(disk_total_space($directory) / 1024 / 1024)), // MB
82-
'used' => intval(round($total - (disk_free_space($directory) / 1024 / 1024))), // MB
83-
])
84-
->all(),
85-
], flags: JSON_THROW_ON_ERROR), $event->time);
86-
87-
$this->cache->store()->forever($this->key(), $event->time->timestamp);
88-
}
89-
90-
/**
91-
* Determine if the recorder is ready to take another snapshot.
92-
*/
93-
protected function readyToRecord(SharedBeat $event): bool
94-
{
95-
return with($this->cache->store()->get($this->key()), function ($lastChecked) use ($event) {
96-
return $lastChecked === null || $lastChecked <= ($event->time->timestamp - 15);
77+
$this->pulse->record('cpu', $slug, $cpu, $event->time)->avg()->onlyBuckets();
78+
$this->pulse->record('memory', $slug, $memoryUsed, $event->time)->avg()->onlyBuckets();
79+
$this->pulse->set('system', $slug, json_encode([
80+
'name' => $server,
81+
'cpu' => $cpu,
82+
'memory_used' => $memoryUsed,
83+
'memory_total' => $memoryTotal,
84+
'storage' => collect($this->config->get('pulse.recorders.'.self::class.'.directories')) // @phpstan-ignore argument.templateType argument.templateType
85+
->map(fn (string $directory) => [
86+
'directory' => $directory,
87+
'total' => $total = intval(round(disk_total_space($directory) / 1024 / 1024)), // MB
88+
'used' => intval(round($total - (disk_free_space($directory) / 1024 / 1024))), // MB
89+
])
90+
->all(),
91+
], flags: JSON_THROW_ON_ERROR), $event->time);
9792
});
9893
}
99-
100-
/**
101-
* The last checked at cache key.
102-
*/
103-
protected function key(): string
104-
{
105-
$slug = Str::slug($this->config->get('pulse.recorders.'.self::class.'.server_name'));
106-
107-
return "laravel:pulse:recorders:servers:{$slug}:last_snapshot_at";
108-
}
10994
}

0 commit comments

Comments
 (0)