|
12 | 12 | namespace FriendsOfHyperf\Sentry\Metrics\Listener; |
13 | 13 |
|
14 | 14 | use FriendsOfHyperf\Sentry\Constants; |
15 | | -use Hyperf\Command\Event\AfterExecute; |
| 15 | +use FriendsOfHyperf\Sentry\Feature; |
| 16 | +use FriendsOfHyperf\Sentry\Metrics\Traits\MetricSetter; |
16 | 17 | use Hyperf\Command\Event\BeforeHandle; |
17 | | -use Hyperf\Context\Context; |
| 18 | +use Hyperf\Coordinator\CoordinatorManager; |
| 19 | +use Hyperf\Coordinator\Timer; |
| 20 | +use Hyperf\Engine\Coroutine; |
18 | 21 | use Hyperf\Event\Contract\ListenerInterface; |
| 22 | +use Sentry\Unit; |
| 23 | + |
| 24 | +use function FriendsOfHyperf\Sentry\metrics; |
19 | 25 |
|
20 | 26 | class OnBeforeHandle implements ListenerInterface |
21 | 27 | { |
| 28 | + use MetricSetter; |
| 29 | + |
| 30 | + protected Timer $timer; |
| 31 | + |
| 32 | + public function __construct(protected Feature $feature) |
| 33 | + { |
| 34 | + $this->timer = new Timer(); |
| 35 | + } |
| 36 | + |
22 | 37 | public function listen(): array |
23 | 38 | { |
24 | 39 | return [ |
25 | 40 | BeforeHandle::class, |
26 | | - AfterExecute::class, |
27 | 41 | ]; |
28 | 42 | } |
29 | 43 |
|
30 | 44 | /** |
31 | | - * @param object|BeforeHandle|AfterExecute $event |
| 45 | + * @param object|BeforeHandle $event |
32 | 46 | */ |
33 | 47 | public function process(object $event): void |
34 | 48 | { |
35 | | - match (true) { |
36 | | - $event instanceof BeforeHandle => Context::set(Constants::RUN_IN_COMMAND, true), |
37 | | - $event instanceof AfterExecute => Context::destroy(Constants::RUN_IN_COMMAND), |
38 | | - default => null, |
39 | | - }; |
| 49 | + if ( |
| 50 | + ! $event instanceof BeforeHandle |
| 51 | + || ! $event->getCommand()->getApplication()->isAutoExitEnabled() // Only enable in the command with auto exit. |
| 52 | + || ! $this->feature->isCommandMetricsEnabled() |
| 53 | + ) { |
| 54 | + return; |
| 55 | + } |
| 56 | + |
| 57 | + Constants::$runningInCommand = true; |
| 58 | + |
| 59 | + if (! $this->feature->isDefaultMetricsEnabled()) { |
| 60 | + return; |
| 61 | + } |
| 62 | + |
| 63 | + // The following metrics MUST be collected in worker. |
| 64 | + $metrics = [ |
| 65 | + 'memory_usage', |
| 66 | + 'memory_peak_usage', |
| 67 | + 'gc_runs', |
| 68 | + 'gc_collected', |
| 69 | + 'gc_threshold', |
| 70 | + 'gc_roots', |
| 71 | + 'ru_oublock', |
| 72 | + 'ru_inblock', |
| 73 | + 'ru_msgsnd', |
| 74 | + 'ru_msgrcv', |
| 75 | + 'ru_maxrss', |
| 76 | + 'ru_ixrss', |
| 77 | + 'ru_idrss', |
| 78 | + 'ru_minflt', |
| 79 | + 'ru_majflt', |
| 80 | + 'ru_nsignals', |
| 81 | + 'ru_nvcsw', |
| 82 | + 'ru_nivcsw', |
| 83 | + 'ru_nswap', |
| 84 | + 'ru_utime_tv_usec', |
| 85 | + 'ru_utime_tv_sec', |
| 86 | + 'ru_stime_tv_usec', |
| 87 | + 'ru_stime_tv_sec', |
| 88 | + ]; |
| 89 | + |
| 90 | + $timerId = $this->timer->tick($this->feature->getMetricsInterval(), function () use ($metrics) { |
| 91 | + defer(fn () => metrics()->flush()); |
| 92 | + |
| 93 | + $this->trySet('gc_', $metrics, gc_status()); |
| 94 | + $this->trySet('', $metrics, getrusage()); |
| 95 | + |
| 96 | + metrics()->gauge( |
| 97 | + 'memory_usage', |
| 98 | + (float) memory_get_usage(), |
| 99 | + ['worker' => '0'], |
| 100 | + Unit::byte() |
| 101 | + ); |
| 102 | + metrics()->gauge( |
| 103 | + 'memory_peak_usage', |
| 104 | + (float) memory_get_peak_usage(), |
| 105 | + ['worker' => '0'], |
| 106 | + Unit::byte() |
| 107 | + ); |
| 108 | + }); |
| 109 | + |
| 110 | + Coroutine::create(function () use ($timerId) { |
| 111 | + CoordinatorManager::until(\Hyperf\Coordinator\Constants::WORKER_EXIT)->yield(); |
| 112 | + $this->timer->clear($timerId); |
| 113 | + }); |
40 | 114 | } |
41 | 115 | } |
0 commit comments