diff --git a/src/sentry/publish/sentry.php b/src/sentry/publish/sentry.php index dd3187711..b9e47c553 100644 --- a/src/sentry/publish/sentry.php +++ b/src/sentry/publish/sentry.php @@ -42,6 +42,8 @@ // @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#enable_metrics 'enable_metrics' => env('SENTRY_ENABLE_METRICS', true), + 'enable_default_metrics' => env('SENTRY_ENABLE_DEFAULT_METRICS', true), + 'enable_command_metrics' => env('SENTRY_ENABLE_COMMAND_METRICS', true), 'metrics_interval' => (int) env('SENTRY_METRICS_INTERVAL', 10), 'logs_channel_level' => env('SENTRY_LOGS_CHANNEL_LEVEL', Sentry\Logs\LogLevel::debug()), diff --git a/src/sentry/src/Constants.php b/src/sentry/src/Constants.php index 33b344c37..cfa1d7469 100644 --- a/src/sentry/src/Constants.php +++ b/src/sentry/src/Constants.php @@ -39,5 +39,5 @@ class Constants public const TRACEPARENT = 'traceparent'; - public const RUN_IN_COMMAND = 'sentry.run_in_command'; + public static bool $runningInCommand = false; } diff --git a/src/sentry/src/Factory/ClientBuilderFactory.php b/src/sentry/src/Factory/ClientBuilderFactory.php index ce478b03b..c8ab118dd 100644 --- a/src/sentry/src/Factory/ClientBuilderFactory.php +++ b/src/sentry/src/Factory/ClientBuilderFactory.php @@ -31,6 +31,8 @@ class ClientBuilderFactory 'http_chanel_size', // deprecated, will be removed in v3.2 'http_concurrent_limit', // deprecated, will be removed in v3.2 'logs_channel_level', + 'enable_default_metrics', + 'enable_command_metrics', 'metrics_interval', 'transport_channel_size', 'transport_concurrent_limit', diff --git a/src/sentry/src/Feature.php b/src/sentry/src/Feature.php index 6b0169af5..fa89298f1 100644 --- a/src/sentry/src/Feature.php +++ b/src/sentry/src/Feature.php @@ -36,6 +36,24 @@ public function isMetricsEnabled(bool $default = true): bool return (bool) $this->config->get('sentry.enable_metrics', $default); } + public function isDefaultMetricsEnabled(bool $default = true): bool + { + if (! $this->isMetricsEnabled()) { + return false; + } + + return (bool) $this->config->get('sentry.enable_default_metrics', $default); + } + + public function isCommandMetricsEnabled(bool $default = true): bool + { + if (! $this->isMetricsEnabled()) { + return false; + } + + return (bool) $this->config->get('sentry.enable_command_metrics', $default); + } + public function getMetricsInterval(int $default = 10): int { $interval = (int) $this->config->get('sentry.metrics_interval', $default); diff --git a/src/sentry/src/Metrics/Listener/OnBeforeHandle.php b/src/sentry/src/Metrics/Listener/OnBeforeHandle.php index b4954ee83..995cd66f2 100644 --- a/src/sentry/src/Metrics/Listener/OnBeforeHandle.php +++ b/src/sentry/src/Metrics/Listener/OnBeforeHandle.php @@ -12,30 +12,104 @@ namespace FriendsOfHyperf\Sentry\Metrics\Listener; use FriendsOfHyperf\Sentry\Constants; -use Hyperf\Command\Event\AfterExecute; +use FriendsOfHyperf\Sentry\Feature; +use FriendsOfHyperf\Sentry\Metrics\Traits\MetricSetter; use Hyperf\Command\Event\BeforeHandle; -use Hyperf\Context\Context; +use Hyperf\Coordinator\CoordinatorManager; +use Hyperf\Coordinator\Timer; +use Hyperf\Engine\Coroutine; use Hyperf\Event\Contract\ListenerInterface; +use Sentry\Unit; + +use function FriendsOfHyperf\Sentry\metrics; class OnBeforeHandle implements ListenerInterface { + use MetricSetter; + + protected Timer $timer; + + public function __construct(protected Feature $feature) + { + $this->timer = new Timer(); + } + public function listen(): array { return [ BeforeHandle::class, - AfterExecute::class, ]; } /** - * @param object|BeforeHandle|AfterExecute $event + * @param object|BeforeHandle $event */ public function process(object $event): void { - match (true) { - $event instanceof BeforeHandle => Context::set(Constants::RUN_IN_COMMAND, true), - $event instanceof AfterExecute => Context::destroy(Constants::RUN_IN_COMMAND), - default => null, - }; + if ( + ! $event instanceof BeforeHandle + || ! $event->getCommand()->getApplication()->isAutoExitEnabled() // Only enable in the command with auto exit. + || ! $this->feature->isCommandMetricsEnabled() + ) { + return; + } + + Constants::$runningInCommand = true; + + if (! $this->feature->isDefaultMetricsEnabled()) { + return; + } + + // The following metrics MUST be collected in worker. + $metrics = [ + 'memory_usage', + 'memory_peak_usage', + 'gc_runs', + 'gc_collected', + 'gc_threshold', + 'gc_roots', + 'ru_oublock', + 'ru_inblock', + 'ru_msgsnd', + 'ru_msgrcv', + 'ru_maxrss', + 'ru_ixrss', + 'ru_idrss', + 'ru_minflt', + 'ru_majflt', + 'ru_nsignals', + 'ru_nvcsw', + 'ru_nivcsw', + 'ru_nswap', + 'ru_utime_tv_usec', + 'ru_utime_tv_sec', + 'ru_stime_tv_usec', + 'ru_stime_tv_sec', + ]; + + $timerId = $this->timer->tick($this->feature->getMetricsInterval(), function () use ($metrics) { + defer(fn () => metrics()->flush()); + + $this->trySet('gc_', $metrics, gc_status()); + $this->trySet('', $metrics, getrusage()); + + metrics()->gauge( + 'memory_usage', + (float) memory_get_usage(), + ['worker' => '0'], + Unit::byte() + ); + metrics()->gauge( + 'memory_peak_usage', + (float) memory_get_peak_usage(), + ['worker' => '0'], + Unit::byte() + ); + }); + + Coroutine::create(function () use ($timerId) { + CoordinatorManager::until(\Hyperf\Coordinator\Constants::WORKER_EXIT)->yield(); + $this->timer->clear($timerId); + }); } } diff --git a/src/sentry/src/Metrics/Listener/OnCoroutineServerStart.php b/src/sentry/src/Metrics/Listener/OnCoroutineServerStart.php index 53dd0141b..f06287729 100644 --- a/src/sentry/src/Metrics/Listener/OnCoroutineServerStart.php +++ b/src/sentry/src/Metrics/Listener/OnCoroutineServerStart.php @@ -67,6 +67,10 @@ public function process(object $event): void $eventDispatcher = $this->container->get(EventDispatcherInterface::class); $eventDispatcher->dispatch(new MetricFactoryReady()); + if (! $this->feature->isDefaultMetricsEnabled()) { + return; + } + // The following metrics MUST be collected in worker. $metrics = [ // 'worker_request_count', @@ -105,13 +109,13 @@ public function process(object $event): void metrics()->gauge( 'memory_usage', (float) memory_get_usage(), - [], + ['worker' => '0'], Unit::byte() ); metrics()->gauge( 'memory_peak_usage', (float) memory_get_peak_usage(), - [], + ['worker' => '0'], Unit::byte() ); }); diff --git a/src/sentry/src/Metrics/Listener/OnMetricFactoryReady.php b/src/sentry/src/Metrics/Listener/OnMetricFactoryReady.php index 21b65ca82..153bb50fb 100644 --- a/src/sentry/src/Metrics/Listener/OnMetricFactoryReady.php +++ b/src/sentry/src/Metrics/Listener/OnMetricFactoryReady.php @@ -11,11 +11,11 @@ namespace FriendsOfHyperf\Sentry\Metrics\Listener; +use FriendsOfHyperf\Sentry\Constants as SentryConstants; use FriendsOfHyperf\Sentry\Feature; use FriendsOfHyperf\Sentry\Metrics\CoroutineServerStats; use FriendsOfHyperf\Sentry\Metrics\Event\MetricFactoryReady; use FriendsOfHyperf\Sentry\Metrics\Traits\MetricSetter; -use Hyperf\Context\Context; use Hyperf\Coordinator\Constants; use Hyperf\Coordinator\CoordinatorManager; use Hyperf\Coordinator\Timer; @@ -54,7 +54,7 @@ public function listen(): array */ public function process(object $event): void { - if (! $this->feature->isMetricsEnabled()) { + if (! $this->feature->isDefaultMetricsEnabled()) { return; } @@ -86,7 +86,7 @@ public function process(object $event): void $serverStatsFactory = null; - if (! Context::get(\FriendsOfHyperf\Sentry\Constants::RUN_IN_COMMAND, false)) { + if (! SentryConstants::$runningInCommand) { if ($this->container->has(SwooleServer::class) && $server = $this->container->get(SwooleServer::class)) { if ($server instanceof SwooleServer) { $serverStatsFactory = fn (): array => $server->stats(); diff --git a/src/sentry/src/Metrics/Listener/OnWorkerStart.php b/src/sentry/src/Metrics/Listener/OnWorkerStart.php index f6f0c64d1..26372526d 100644 --- a/src/sentry/src/Metrics/Listener/OnWorkerStart.php +++ b/src/sentry/src/Metrics/Listener/OnWorkerStart.php @@ -53,7 +53,7 @@ public function listen(): array */ public function process(object $event): void { - if (! $this->feature->isMetricsEnabled()) { + if (! $this->feature->isDefaultMetricsEnabled()) { return; } diff --git a/src/sentry/src/Metrics/Traits/MetricSetter.php b/src/sentry/src/Metrics/Traits/MetricSetter.php index 9b5a5f9db..89708ae0b 100644 --- a/src/sentry/src/Metrics/Traits/MetricSetter.php +++ b/src/sentry/src/Metrics/Traits/MetricSetter.php @@ -31,4 +31,8 @@ protected function trySet(string $prefix, array $metrics, array $stats, int $wor } } } + + // protected function spawnDefaultMetrics() + // { + // } }