Skip to content

Commit 7190f4a

Browse files
matheus-carvalhoMatheus Carvalhojessarchertimacdonald
authored
[1.x] Allow thresholds of slow queries, jobs and requests to be customised by regex pattern (#340)
* allow thresholds of slow queries, jobs and requests to be customised by regex pattern * Fix lint and tests * Prevent error when Livewire payload contains no components * Improvements customised thresholds * Format slow requests * Revert default config * slow requests UI * format slow jobs recorder * format slow jobs config * format slow jobs ui * formatting * formatting * format slow outgoing config * format slow outgoing recorder * format slow outgoing ui * format slow queries config * format slow queries recorder * Format slow queries threshold * Format usage UI * use @js directive * Remove comment * Only resolve value once * Fix CI * Fix tests * Formatting * Formatting --------- Co-authored-by: Matheus Carvalho <matheus.carvalho@tray.net.br> Co-authored-by: Jess Archer <jess@jessarcher.com> Co-authored-by: Tim MacDonald <hello@timacdonald.me>
1 parent df05d74 commit 7190f4a

24 files changed

+275
-32
lines changed

resources/views/livewire/cache.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
Str::plural('group', $count)
2121
);
2222
@endphp
23-
<button title="{{ $message }}" @click="alert('{{ str_replace("\n", '\n', $message) }}')">
23+
<button title="{{ $message }}" @click="alert(@js($message))">
2424
<x-pulse::icons.information-circle class="w-5 h-5 stroke-gray-400 dark:stroke-gray-600" />
2525
</button>
2626
</x-slot:actions>

resources/views/livewire/slow-jobs.blade.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<x-pulse::card-header
33
name="Slow Jobs"
44
title="Time: {{ number_format($time, 0) }}ms; Run at: {{ $runAt }};"
5-
details="{{ $config['threshold'] }}ms threshold, past {{ $this->periodForHumans() }}"
5+
details="{{ is_array($config['threshold']) ? '' : $config['threshold'].'ms threshold, ' }}past {{ $this->periodForHumans() }}"
66
>
77
<x-slot:icon>
88
<x-pulse::icons.command-line />
@@ -45,6 +45,11 @@
4545
<code class="block text-xs text-gray-900 dark:text-gray-100 truncate" title="{{ $job->job }}">
4646
{{ $job->job }}
4747
</code>
48+
@if (is_array($config['threshold']))
49+
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
50+
{{ $job->threshold }}ms threshold
51+
</p>
52+
@endif
4853
</x-pulse::td>
4954
<x-pulse::td numeric class="text-gray-700 dark:text-gray-300 font-bold">
5055
@if ($config['sample_rate'] < 1)

resources/views/livewire/slow-outgoing-requests.blade.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<x-pulse::card-header
66
name="Slow Outgoing Requests"
77
title="Time: {{ number_format($time) }}ms; Run at: {{ $runAt }};"
8-
details="{{ $config['threshold'] }}ms threshold, past {{ $this->periodForHumans() }}"
8+
details="{{ is_array($config['threshold']) ? '' : $config['threshold'].'ms threshold, ' }}past {{ $this->periodForHumans() }}"
99
>
1010
<x-slot:icon>
1111
<x-pulse::icons.cloud-arrow-up />
@@ -20,7 +20,7 @@
2020
Str::plural('group', $count)
2121
);
2222
@endphp
23-
<button title="{{ $message }}" @click="alert('{{ str_replace("\n", '\n', $message) }}')">
23+
<button title="{{ $message }}" @click="alert(@js($message))">
2424
<x-pulse::icons.information-circle class="w-5 h-5 stroke-gray-400 dark:stroke-gray-600" />
2525
</button>
2626

@@ -71,6 +71,11 @@
7171
{{ $request->uri }}
7272
</code>
7373
</div>
74+
@if (is_array($config['threshold']))
75+
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
76+
{{ $request->threshold }}ms threshold
77+
</p>
78+
@endif
7479
</x-pulse::td>
7580
<x-pulse::td numeric class="text-gray-700 dark:text-gray-300 font-bold">
7681
@if ($config['sample_rate'] < 1)

resources/views/livewire/slow-queries.blade.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<x-pulse::card-header
2121
name="Slow Queries"
2222
title="Time: {{ number_format($time) }}ms; Run at: {{ $runAt }};"
23-
details="{{ $config['threshold'] }}ms threshold, past {{ $this->periodForHumans() }}"
23+
details="{{ is_array($config['threshold']) ? '' : $config['threshold'].'ms threshold, ' }}past {{ $this->periodForHumans() }}"
2424
>
2525
<x-slot:icon>
2626
<x-pulse::icons.circle-stack />
@@ -68,6 +68,11 @@
6868
{{ $query->location }}
6969
</p>
7070
@endif
71+
@if (is_array($config['threshold']))
72+
<p class="px-3 mt-3 text-xs leading-none text-gray-400 dark:text-gray-500">
73+
{{ $query->threshold }}ms threshold
74+
</p>
75+
@endif
7176
</div>
7277
<div class="absolute top-0 right-0 bottom-0 rounded-r-md w-3 bg-gradient-to-r from-transparent to-gray-700 dark:to-gray-800 pointer-events-none"></div>
7378
</div>

resources/views/livewire/slow-requests.blade.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<x-pulse::card-header
33
name="Slow Requests"
44
title="Time: {{ number_format($time) }}ms; Run at: {{ $runAt }};"
5-
details="{{ $config['threshold'] }}ms threshold, past {{ $this->periodForHumans() }}"
5+
details="{{ is_array($config['threshold']) ? '' : $config['threshold'].'ms threshold, ' }}past {{ $this->periodForHumans() }}"
66
>
77
<x-slot:icon>
88
<x-pulse::icons.arrows-left-right />
@@ -55,6 +55,11 @@
5555
{{ $slowRequest->action }}
5656
</p>
5757
@endif
58+
@if (is_array($config['threshold']))
59+
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
60+
{{ $slowRequest->threshold }}ms threshold
61+
</p>
62+
@endif
5863
</x-pulse::td>
5964
<x-pulse::td numeric class="text-gray-700 dark:text-gray-300 font-bold">
6065
@if ($config['sample_rate'] < 1)

resources/views/livewire/usage.blade.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
default => 'Application Usage'
88
}"
99
title="Time: {{ number_format($time) }}ms; Run at: {{ $runAt }};"
10-
details="{{ $this->usage === 'slow_requests' ? ($slowRequestsConfig['threshold'].'ms threshold, ') : '' }}past {{ $this->periodForHumans() }}"
10+
details="{{ $this->usage === 'slow_requests' ? (is_array($slowRequestsConfig['threshold']) ? '' : $slowRequestsConfig['threshold'].'ms threshold, ') : '' }}past {{ $this->periodForHumans() }}"
1111
>
1212
<x-slot:icon>
1313
<x-dynamic-component :component="'pulse::icons.' . match ($this->type) {
@@ -31,6 +31,14 @@ class="flex-1"
3131
@change="loading = true"
3232
/>
3333
@endif
34+
@if ($this->usage === 'slow_requests' && is_array($slowRequestsConfig['threshold']))
35+
@php
36+
$message = 'You have per-route thresholds configured.';
37+
@endphp
38+
<button title="{{ $message }}" @click="alert(@js($message))">
39+
<x-pulse::icons.information-circle class="w-5 h-5 stroke-gray-400 dark:stroke-gray-600" />
40+
</button>
41+
@endif
3442
</x-slot:actions>
3543
</x-pulse::card-header>
3644

src/Livewire/SlowJobs.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Contracts\Support\Renderable;
66
use Illuminate\Support\Facades\Config;
77
use Illuminate\Support\Facades\View;
8+
use Laravel\Pulse\Recorders\Concerns\Thresholds;
89
use Laravel\Pulse\Recorders\SlowJobs as SlowJobsRecorder;
910
use Livewire\Attributes\Lazy;
1011
use Livewire\Attributes\Url;
@@ -15,6 +16,8 @@
1516
#[Lazy]
1617
class SlowJobs extends Card
1718
{
19+
use Thresholds;
20+
1821
/**
1922
* Ordering.
2023
*
@@ -40,6 +43,7 @@ public function render(): Renderable
4043
'job' => $row->key,
4144
'slowest' => $row->max,
4245
'count' => $row->count,
46+
'threshold' => $this->threshold($row->key, SlowJobsRecorder::class),
4347
]),
4448
$this->orderBy,
4549
);

src/Livewire/SlowOutgoingRequests.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Contracts\Support\Renderable;
66
use Illuminate\Support\Facades\Config;
77
use Illuminate\Support\Facades\View;
8+
use Laravel\Pulse\Recorders\Concerns\Thresholds;
89
use Laravel\Pulse\Recorders\SlowOutgoingRequests as SlowOutgoingRequestsRecorder;
910
use Livewire\Attributes\Lazy;
1011
use Livewire\Attributes\Url;
@@ -15,6 +16,8 @@
1516
#[Lazy]
1617
class SlowOutgoingRequests extends Card
1718
{
19+
use Thresholds;
20+
1821
/**
1922
* Ordering.
2023
*
@@ -44,6 +47,7 @@ public function render(): Renderable
4447
'uri' => $uri,
4548
'slowest' => $row->max,
4649
'count' => $row->count,
50+
'threshold' => $this->threshold($uri, SlowOutgoingRequestsRecorder::class),
4751
];
4852
}),
4953
$this->orderBy,

src/Livewire/SlowQueries.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Contracts\Support\Renderable;
66
use Illuminate\Support\Facades\Config;
77
use Illuminate\Support\Facades\View;
8+
use Laravel\Pulse\Recorders\Concerns\Thresholds;
89
use Laravel\Pulse\Recorders\SlowQueries as SlowQueriesRecorder;
910
use Livewire\Attributes\Lazy;
1011
use Livewire\Attributes\Url;
@@ -15,6 +16,8 @@
1516
#[Lazy]
1617
class SlowQueries extends Card
1718
{
19+
use Thresholds;
20+
1821
/**
1922
* Ordering.
2023
*
@@ -56,6 +59,7 @@ public function render(): Renderable
5659
'location' => $location,
5760
'slowest' => $row->max,
5861
'count' => $row->count,
62+
'threshold' => $this->threshold($sql, SlowQueriesRecorder::class),
5963
];
6064
}),
6165
$this->orderBy,

src/Livewire/SlowRequests.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Contracts\Support\Renderable;
66
use Illuminate\Support\Facades\Config;
77
use Illuminate\Support\Facades\View;
8+
use Laravel\Pulse\Recorders\Concerns\Thresholds;
89
use Laravel\Pulse\Recorders\SlowRequests as SlowRequestsRecorder;
910
use Livewire\Attributes\Lazy;
1011
use Livewire\Attributes\Url;
@@ -15,6 +16,8 @@
1516
#[Lazy]
1617
class SlowRequests extends Card
1718
{
19+
use Thresholds;
20+
1821
/**
1922
* Ordering.
2023
*
@@ -45,6 +48,7 @@ public function render(): Renderable
4548
'action' => $action,
4649
'count' => $row->count,
4750
'slowest' => $row->max,
51+
'threshold' => $this->threshold($uri, SlowRequestsRecorder::class),
4852
];
4953
}),
5054
$this->orderBy,

src/Recorders/Concerns/LivewireRoutes.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ protected function resolveRoutePath(Request $request): array
2020
$path = $route->getDomain().Str::start($route->uri(), '/');
2121
$via = $route->getActionName();
2222

23-
if ($route->named('*livewire.update')) {
24-
$snapshot = json_decode($request->input('components.0.snapshot'), flags: JSON_THROW_ON_ERROR);
23+
if ($route->named('*livewire.update') && ($snapshot = $request->input('components.0.snapshot'))) {
24+
$snapshot = json_decode($snapshot, flags: JSON_THROW_ON_ERROR);
2525

2626
if (isset($snapshot->memo->path)) {
2727
$via = 'via '.$path;

src/Recorders/Concerns/Thresholds.php

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,36 @@
22

33
namespace Laravel\Pulse\Recorders\Concerns;
44

5+
use Illuminate\Support\Facades\Config;
6+
57
trait Thresholds
68
{
79
/**
810
* Determine if the duration is under the configured threshold.
911
*/
10-
protected function underThreshold(int|float $duration): bool
12+
protected function underThreshold(int|float $duration, string $key): bool
13+
{
14+
return $duration < $this->threshold($key);
15+
}
16+
17+
/**
18+
* Get the threshold for the given key.
19+
*/
20+
protected function threshold(string $key, ?string $recorder = null): int
1121
{
12-
return $duration < $this->config->get('pulse.recorders.'.static::class.'.threshold');
22+
$recorder ??= static::class;
23+
24+
$config = Config::get("pulse.recorders.{$recorder}.threshold");
25+
26+
if (! is_array($config)) {
27+
return $config;
28+
}
29+
30+
// @phpstan-ignore argument.templateType, argument.templateType
31+
$custom = collect($config)
32+
->except(['default'])
33+
->first(fn ($threshold, $pattern) => preg_match($pattern, $key) === 1);
34+
35+
return $custom ?? $config['default'] ?? 1_000;
1336
}
1437
}

src/Recorders/SlowJobs.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ public function record(JobReleasedAfterException|JobFailed|JobProcessed|JobProce
7474

7575
$this->pulse->lazy(function () use ($timestamp, $timestampMs, $name, $lastJobStartedProcessingAt) {
7676
if (
77-
$this->underThreshold($duration = $timestampMs - $lastJobStartedProcessingAt) ||
7877
! $this->shouldSample() ||
79-
$this->shouldIgnore($name)
78+
$this->shouldIgnore($name) ||
79+
$this->underThreshold($duration = $timestampMs - $lastJobStartedProcessingAt, $name)
8080
) {
8181
return;
8282
}

src/Recorders/SlowOutgoingRequests.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ public function record(RequestInterface $request, int $startedAt): void
5656

5757
$this->pulse->lazy(function () use ($startedAt, $timestamp, $endedAt, $method, $uri) {
5858
if (
59-
$this->underThreshold($duration = $endedAt - $startedAt) ||
6059
! $this->shouldSample() ||
61-
$this->shouldIgnore($uri)
60+
$this->shouldIgnore($uri) ||
61+
$this->underThreshold($duration = $endedAt - $startedAt, $uri)
6262
) {
6363
return;
6464
}

src/Recorders/SlowQueries.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ public function record(QueryExecuted $event): void
4848

4949
$this->pulse->lazy(function () use ($timestampMs, $duration, $sql, $location) {
5050
if (
51-
$this->underThreshold($duration) ||
5251
! $this->shouldSample() ||
53-
$this->shouldIgnore($sql)
52+
$this->shouldIgnore($sql) ||
53+
$this->underThreshold($duration, $sql)
5454
) {
5555
return;
5656
}

src/Recorders/SlowRequests.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,16 @@ public function register(callable $record, Application $app): void
5050
*/
5151
public function record(Carbon $startedAt, Request $request, Response $response): void
5252
{
53-
if (
54-
! $request->route() instanceof Route ||
55-
$this->underThreshold($duration = ((int) $startedAt->diffInMilliseconds())) ||
56-
! $this->shouldSample()
57-
) {
53+
if (! $request->route() instanceof Route || ! $this->shouldSample()) {
5854
return;
5955
}
6056

6157
[$path, $via] = $this->resolveRoutePath($request);
6258

63-
if ($this->shouldIgnore($path)) {
59+
if (
60+
$this->shouldIgnore($path) ||
61+
$this->underThreshold($duration = ((int) $startedAt->diffInMilliseconds()), $path)
62+
) {
6463
return;
6564
}
6665

tests/Feature/Livewire/SlowJobsTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
Livewire::test(SlowJobs::class, ['lazy' => false])
3535
->assertViewHas('slowJobs', collect([
36-
(object) ['job' => 'App\Jobs\MyJob', 'count' => 4, 'slowest' => 2468],
37-
(object) ['job' => 'App\Jobs\MyOtherJob', 'count' => 2, 'slowest' => 1234],
36+
(object) ['job' => 'App\Jobs\MyJob', 'count' => 4, 'slowest' => 2468, 'threshold' => 1_000],
37+
(object) ['job' => 'App\Jobs\MyOtherJob', 'count' => 2, 'slowest' => 1234, 'threshold' => 1_000],
3838
]));
3939
});

tests/Feature/Livewire/SlowOutgoingRequestsTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
Livewire::test(SlowOutgoingRequests::class, ['lazy' => false])
3535
->assertViewHas('slowOutgoingRequests', collect([
36-
(object) ['method' => 'GET', 'uri' => 'http://example.com', 'count' => 4, 'slowest' => 2468],
37-
(object) ['method' => 'GET', 'uri' => 'http://example.org', 'count' => 2, 'slowest' => 1234],
36+
(object) ['method' => 'GET', 'uri' => 'http://example.com', 'count' => 4, 'slowest' => 2468, 'threshold' => 1_000],
37+
(object) ['method' => 'GET', 'uri' => 'http://example.org', 'count' => 2, 'slowest' => 1234, 'threshold' => 1_000],
3838
]));
3939
});

tests/Feature/Livewire/SlowQueriesTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636

3737
Livewire::test(SlowQueries::class, ['lazy' => false])
3838
->assertViewHas('slowQueries', collect([
39-
(object) ['sql' => 'select * from `users`', 'location' => 'app/Foo.php:123', 'count' => 4, 'slowest' => 2468],
40-
(object) ['sql' => 'select * from `users` where `id` = ?', 'location' => 'app/Bar.php:456', 'count' => 2, 'slowest' => 1234],
39+
(object) ['sql' => 'select * from `users`', 'location' => 'app/Foo.php:123', 'count' => 4, 'slowest' => 2468, 'threshold' => 1_000],
40+
(object) ['sql' => 'select * from `users` where `id` = ?', 'location' => 'app/Bar.php:456', 'count' => 2, 'slowest' => 1234, 'threshold' => 1_000],
4141
]));
4242
});
4343

tests/Feature/Livewire/SlowRequestsTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
Livewire::test(SlowRequests::class, ['lazy' => false])
3838
->assertViewHas('slowRequests', collect([
39-
(object) ['method' => 'GET', 'uri' => '/users', 'action' => 'FooController@index', 'count' => 4, 'slowest' => 2468],
40-
(object) ['method' => 'GET', 'uri' => '/users/{user}', 'action' => 'Closure', 'count' => 2, 'slowest' => 1234],
39+
(object) ['method' => 'GET', 'uri' => '/users', 'action' => 'FooController@index', 'count' => 4, 'slowest' => 2468, 'threshold' => 1_000],
40+
(object) ['method' => 'GET', 'uri' => '/users/{user}', 'action' => 'Closure', 'count' => 2, 'slowest' => 1234, 'threshold' => 1_000],
4141
]));
4242
});

0 commit comments

Comments
 (0)