Skip to content

Commit 6572cdb

Browse files
committed
average for slow requests
1 parent d081a66 commit 6572cdb

File tree

4 files changed

+53
-9
lines changed

4 files changed

+53
-9
lines changed

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,28 @@
88
<x-pulse::icons.arrows-left-right />
99
</x-slot:icon>
1010
<x-slot:actions>
11+
@php
12+
$message = <<<MESSAGE
13+
Count: X / Y → X requests above threshold out of Y total requests
14+
15+
Average: average request duration across all requests
16+
17+
Slowest: maximum request duration across all requests
18+
MESSAGE;
19+
@endphp
20+
<button title="{{ $message }}" @click="alert(@js($message))">
21+
<x-pulse::icons.information-circle class="w-5 h-5 stroke-gray-400 dark:stroke-gray-600" />
22+
</button>
23+
1124
<x-pulse::select
1225
wire:model.live="orderBy"
1326
id="select-slow-requests-order-by"
1427
label="Sort by"
1528
:options="[
1629
'slowest' => 'slowest',
1730
'count' => 'count',
31+
'average' => 'average',
32+
'total' => 'total',
1833
]"
1934
@change="loading = true"
2035
/>
@@ -31,12 +46,14 @@
3146
<col width="100%" />
3247
<col width="0%" />
3348
<col width="0%" />
49+
<col width="0%" />
3450
</colgroup>
3551
<x-pulse::thead>
3652
<tr>
3753
<x-pulse::th>Method</x-pulse::th>
3854
<x-pulse::th>Route</x-pulse::th>
3955
<x-pulse::th class="text-right">Count</x-pulse::th>
56+
<x-pulse::th class="text-right">Average</x-pulse::th>
4057
<x-pulse::th class="text-right">Slowest</x-pulse::th>
4158
</tr>
4259
</x-pulse::thead>
@@ -66,9 +83,12 @@
6683
@if ($config['sample_rate'] < 1)
6784
<span title="Sample rate: {{ $config['sample_rate'] }}, Raw value: {{ number_format($slowRequest->count) }}">~{{ number_format($slowRequest->count * (1 / $config['sample_rate'])) }}</span>
6885
@else
69-
{{ number_format($slowRequest->count) }}
86+
{{ number_format($slowRequest->count) }} / {{ number_format($slowRequest->total) }}
7087
@endif
7188
</x-pulse::td>
89+
<x-pulse::td numeric class="text-gray-700 dark:text-gray-300">
90+
<strong>{{ number_format($slowRequest->avg) }}</strong> ms
91+
</x-pulse::td>
7292
<x-pulse::td numeric class="text-gray-700 dark:text-gray-300">
7393
@if ($slowRequest->slowest === null)
7494
<strong>Unknown</strong>

src/Livewire/SlowRequests.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,15 @@ public function render(): Renderable
3434
[$slowRequests, $time, $runAt] = $this->remember(
3535
fn () => $this->aggregate(
3636
'slow_request',
37-
['max', 'count'],
37+
['max', 'count', 'avg'],
3838
match ($this->orderBy) {
3939
'count' => 'count',
40+
'average' => 'avg',
41+
'total' => 'avg_count',
4042
default => 'max',
4143
},
42-
)->map(function ($row) {
44+
)
45+
->map(function ($row) {
4346
[$method, $uri, $action] = json_decode($row->key, flags: JSON_THROW_ON_ERROR);
4447

4548
return (object) [
@@ -48,6 +51,8 @@ public function render(): Renderable
4851
'action' => $action,
4952
'count' => $row->count,
5053
'slowest' => $row->max,
54+
'avg' => $row->avg,
55+
'total' => $row->avg_count,
5156
'threshold' => $this->threshold($uri, SlowRequestsRecorder::class),
5257
];
5358
}),

src/Recorders/SlowRequests.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,26 @@ public function record(Carbon $startedAt, Request $request, Response $response):
5454

5555
[$path, $via] = $this->resolveRoutePath($request);
5656

57-
if (
58-
$this->shouldIgnore($path) ||
59-
$this->underThreshold($duration = ((int) $startedAt->diffInMilliseconds()), $path)
60-
) {
57+
if ($this->shouldIgnore($path)) {
6158
return;
6259
}
6360

64-
$this->pulse->record(
61+
$duration = ((int) $startedAt->diffInMilliseconds());
62+
63+
// Record average and max duration for all requests.
64+
$entry = $this->pulse->record(
6565
type: 'slow_request',
6666
key: json_encode([$request->method(), $path, $via], flags: JSON_THROW_ON_ERROR),
6767
value: $duration,
6868
timestamp: $startedAt,
69-
)->max()->count();
69+
)->avg()->max();
70+
71+
if ($this->underThreshold($duration, $path)) {
72+
return;
73+
}
74+
75+
// Record count of slow requests
76+
$entry->count();
7077

7178
if ($userId = $this->pulse->resolveAuthenticatedUserId()) {
7279
$this->pulse->record(

src/Storage/DatabaseStorage.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,10 @@ public function aggregate(
540540

541541
$orderBy ??= $aggregates[0];
542542

543+
if (in_array('avg', $aggregates)) {
544+
$aggregates[] = 'avg_count';
545+
}
546+
543547
/** @phpstan-ignore return.type */
544548
return $this->connection()
545549
->query()
@@ -561,6 +565,7 @@ public function aggregate(
561565
'max' => "max({$this->wrap('max')})",
562566
'sum' => "sum({$this->wrap('sum')})",
563567
'avg' => "avg({$this->wrap('avg')})",
568+
'avg_count' => "sum({$this->wrap('avg_count')})",
564569
}." as {$this->wrap($aggregate)}");
565570
}
566571

@@ -581,6 +586,7 @@ public function aggregate(
581586
'max' => "max({$this->wrap('value')})",
582587
'sum' => "sum({$this->wrap('value')})",
583588
'avg' => "avg({$this->wrap('value')})",
589+
'avg_count' => 'count(*)',
584590
}." as {$this->wrap($aggregate)}");
585591
}
586592

@@ -593,6 +599,10 @@ public function aggregate(
593599

594600
// Buckets
595601
foreach ($aggregates as $currentAggregate) {
602+
if ($currentAggregate === 'avg_count') {
603+
continue;
604+
}
605+
596606
$query->unionAll(function (Builder $query) use ($type, $aggregates, $currentAggregate, $period, $oldestBucket) {
597607
$query->select('key_hash');
598608

@@ -605,6 +615,8 @@ public function aggregate(
605615
'sum' => "sum({$this->wrap('value')})",
606616
'avg' => "avg({$this->wrap('value')})",
607617
}." as {$this->wrap($aggregate)}");
618+
} elseif ($aggregate === 'avg_count' && $currentAggregate === 'avg') {
619+
$query->selectRaw("sum({$this->wrap('count')}) as {$this->wrap('avg_count')}");
608620
} else {
609621
$query->selectRaw("null as {$this->wrap($aggregate)}");
610622
}

0 commit comments

Comments
 (0)