diff --git a/src/sentry/publish/sentry.php b/src/sentry/publish/sentry.php index d58338eea..39593fd29 100644 --- a/src/sentry/publish/sentry.php +++ b/src/sentry/publish/sentry.php @@ -65,6 +65,8 @@ 'enable_default_metrics' => env('SENTRY_ENABLE_DEFAULT_METRICS', true), 'enable_command_metrics' => env('SENTRY_ENABLE_COMMAND_METRICS', true), + 'enable_pool_metrics' => env('SENTRY_ENABLE_POOL_METRICS', true), + 'enable_queue_metrics' => env('SENTRY_ENABLE_QUEUE_METRICS', true), 'metrics_interval' => (int) env('SENTRY_METRICS_INTERVAL', 10), // @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#send_default_pii diff --git a/src/sentry/src/Factory/ClientBuilderFactory.php b/src/sentry/src/Factory/ClientBuilderFactory.php index c8ab118dd..c508f7fa2 100644 --- a/src/sentry/src/Factory/ClientBuilderFactory.php +++ b/src/sentry/src/Factory/ClientBuilderFactory.php @@ -33,6 +33,8 @@ class ClientBuilderFactory 'logs_channel_level', 'enable_default_metrics', 'enable_command_metrics', + 'enable_queue_metrics', + 'enable_pool_metrics', 'metrics_interval', 'transport_channel_size', 'transport_concurrent_limit', diff --git a/src/sentry/src/Feature.php b/src/sentry/src/Feature.php index c9e071fab..d14259860 100644 --- a/src/sentry/src/Feature.php +++ b/src/sentry/src/Feature.php @@ -54,6 +54,24 @@ public function isCommandMetricsEnabled(bool $default = true): bool return (bool) $this->config->get('sentry.enable_command_metrics', $default); } + public function isPoolMetricsEnabled(bool $default = true): bool + { + if (! $this->isMetricsEnabled()) { + return false; + } + + return (bool) $this->config->get('sentry.enable_pool_metrics', $default); + } + + public function isQueueMetricsEnabled(bool $default = true): bool + { + if (! $this->isMetricsEnabled()) { + return false; + } + + return (bool) $this->config->get('sentry.enable_queue_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 15472535a..f75d48f57 100644 --- a/src/sentry/src/Metrics/Listener/OnBeforeHandle.php +++ b/src/sentry/src/Metrics/Listener/OnBeforeHandle.php @@ -13,11 +13,14 @@ use FriendsOfHyperf\Sentry\Constants; use FriendsOfHyperf\Sentry\Feature; +use FriendsOfHyperf\Sentry\Metrics\Event\MetricFactoryReady; use FriendsOfHyperf\Sentry\Metrics\Traits\MetricSetter; use FriendsOfHyperf\Sentry\SentryContext; use Hyperf\Command\Event\BeforeHandle; use Hyperf\Coordinator\Timer; use Hyperf\Event\Contract\ListenerInterface; +use Psr\Container\ContainerInterface; +use Psr\EventDispatcher\EventDispatcherInterface; use Sentry\Unit; use function FriendsOfHyperf\Sentry\metrics; @@ -28,8 +31,10 @@ class OnBeforeHandle implements ListenerInterface protected Timer $timer; - public function __construct(protected Feature $feature) - { + public function __construct( + protected ContainerInterface $container, + protected Feature $feature + ) { $this->timer = new Timer(); } @@ -49,13 +54,16 @@ public function process(object $event): void ! $event instanceof BeforeHandle || SentryContext::getCronCheckInId() // Prevent duplicate metrics in cron job. || ! $event->getCommand()->getApplication()->isAutoExitEnabled() // Only enable in the command with auto exit. - || ! $this->feature->isCommandMetricsEnabled() ) { return; } Constants::$runningInCommand = true; + if ($this->feature->isCommandMetricsEnabled() && $this->container->has(EventDispatcherInterface::class)) { + $this->container->get(EventDispatcherInterface::class)->dispatch(new MetricFactoryReady()); + } + if (! $this->feature->isDefaultMetricsEnabled()) { return; } @@ -87,28 +95,27 @@ public function process(object $event): void 'ru_stime_tv_sec', ]; - $this->timer->tick($this->feature->getMetricsInterval(), function ($isClosing = false) use ($metrics) { - if ($isClosing) { - return Timer::STOP; + $this->timer->tick( + $this->feature->getMetricsInterval(), + function () use ($metrics) { + $this->trySet('gc_', $metrics, gc_status()); + $this->trySet('', $metrics, getrusage()); + + metrics()->gauge( + 'memory_usage', + memory_get_usage(true) / 1024 / 1024, + ['worker' => '0'], + Unit::megabyte() + ); + metrics()->gauge( + 'memory_peak_usage', + memory_get_peak_usage(true) / 1024 / 1024, + ['worker' => '0'], + Unit::megabyte() + ); + + metrics()->flush(); } - - $this->trySet('gc_', $metrics, gc_status()); - $this->trySet('', $metrics, getrusage()); - - metrics()->gauge( - 'memory_usage', - memory_get_usage(true) / 1024 / 1024, - ['worker' => '0'], - Unit::megabyte() - ); - metrics()->gauge( - 'memory_peak_usage', - memory_get_peak_usage(true) / 1024 / 1024, - ['worker' => '0'], - Unit::megabyte() - ); - - metrics()->flush(); - }); + ); } } diff --git a/src/sentry/src/Metrics/Listener/OnCoroutineServerStart.php b/src/sentry/src/Metrics/Listener/OnCoroutineServerStart.php index 3fff861b6..aff237387 100644 --- a/src/sentry/src/Metrics/Listener/OnCoroutineServerStart.php +++ b/src/sentry/src/Metrics/Listener/OnCoroutineServerStart.php @@ -50,18 +50,15 @@ public function listen(): array */ public function process(object $event): void { - if (! $this->feature->isMetricsEnabled()) { - return; - } - if ($this->running) { return; } $this->running = true; - $eventDispatcher = $this->container->get(EventDispatcherInterface::class); - $eventDispatcher->dispatch(new MetricFactoryReady()); + if ($this->feature->isMetricsEnabled() && $this->container->has(EventDispatcherInterface::class)) { + $this->container->get(EventDispatcherInterface::class)->dispatch(new MetricFactoryReady()); + } if (! $this->feature->isDefaultMetricsEnabled()) { return; @@ -96,28 +93,27 @@ public function process(object $event): void 'ru_stime_tv_sec', ]; - $this->timer->tick($this->feature->getMetricsInterval(), function ($isClosing = false) use ($metrics) { - if ($isClosing) { - return Timer::STOP; + $this->timer->tick( + $this->feature->getMetricsInterval(), + function () use ($metrics) { + $this->trySet('gc_', $metrics, gc_status()); + $this->trySet('', $metrics, getrusage()); + + metrics()->gauge( + 'memory_usage', + memory_get_usage(true) / 1024 / 1024, + ['worker' => '0'], + Unit::megabyte() + ); + metrics()->gauge( + 'memory_peak_usage', + memory_get_peak_usage(true) / 1024 / 1024, + ['worker' => '0'], + Unit::megabyte() + ); + + metrics()->flush(); } - - $this->trySet('gc_', $metrics, gc_status()); - $this->trySet('', $metrics, getrusage()); - - metrics()->gauge( - 'memory_usage', - memory_get_usage(true) / 1024 / 1024, - ['worker' => '0'], - Unit::megabyte() - ); - metrics()->gauge( - 'memory_peak_usage', - memory_get_peak_usage(true) / 1024 / 1024, - ['worker' => '0'], - Unit::megabyte() - ); - - metrics()->flush(); - }); + ); } } diff --git a/src/sentry/src/Metrics/Listener/OnMetricFactoryReady.php b/src/sentry/src/Metrics/Listener/OnMetricFactoryReady.php index 3496791cc..e34c294a2 100644 --- a/src/sentry/src/Metrics/Listener/OnMetricFactoryReady.php +++ b/src/sentry/src/Metrics/Listener/OnMetricFactoryReady.php @@ -17,7 +17,7 @@ use FriendsOfHyperf\Sentry\Metrics\Event\MetricFactoryReady; use FriendsOfHyperf\Sentry\Metrics\Traits\MetricSetter; use Hyperf\Coordinator\Timer; -use Hyperf\Engine\Coroutine; +use Hyperf\Engine\Coroutine as Co; use Hyperf\Event\Contract\ListenerInterface; use Hyperf\Support\System; use Psr\Container\ContainerInterface; @@ -95,43 +95,42 @@ public function process(object $event): void } } - $this->timer->tick($this->feature->getMetricsInterval(), function ($isClosing = false) use ($metrics, $serverStatsFactory, $workerId) { - if ($isClosing) { - return Timer::STOP; - } + $this->timer->tick( + $this->feature->getMetricsInterval(), + function () use ($metrics, $serverStatsFactory, $workerId) { + $this->trySet('', $metrics, Co::stats(), $workerId); + $this->trySet('timer_', $metrics, Timer::stats(), $workerId); - $this->trySet('', $metrics, Coroutine::stats(), $workerId); - $this->trySet('timer_', $metrics, Timer::stats(), $workerId); + if ($serverStatsFactory) { + $this->trySet('', $metrics, $serverStatsFactory(), $workerId); + } - if ($serverStatsFactory) { - $this->trySet('', $metrics, $serverStatsFactory(), $workerId); - } + if (class_exists('Swoole\Timer')) { + $this->trySet('swoole_timer_', $metrics, \Swoole\Timer::stats(), $workerId); + } - if (class_exists('Swoole\Timer')) { - $this->trySet('swoole_timer_', $metrics, \Swoole\Timer::stats(), $workerId); + $load = sys_getloadavg(); + + metrics()->gauge( + 'sys_load', + round($load[0] / System::getCpuCoresNum(), 2), + ['worker' => (string) $workerId], + ); + metrics()->gauge( + 'metric_process_memory_usage', + memory_get_usage(true) / 1024 / 1024, + ['worker' => (string) $workerId], + Unit::megabyte() + ); + metrics()->gauge( + 'metric_process_memory_peak_usage', + memory_get_peak_usage(true) / 1024 / 1024, + ['worker' => (string) $workerId], + Unit::megabyte() + ); + + metrics()->flush(); } - - $load = sys_getloadavg(); - - metrics()->gauge( - 'sys_load', - round($load[0] / System::getCpuCoresNum(), 2), - ['worker' => (string) $workerId], - ); - metrics()->gauge( - 'metric_process_memory_usage', - memory_get_usage(true) / 1024 / 1024, - ['worker' => (string) $workerId], - Unit::megabyte() - ); - metrics()->gauge( - 'metric_process_memory_peak_usage', - memory_get_peak_usage(true) / 1024 / 1024, - ['worker' => (string) $workerId], - Unit::megabyte() - ); - - metrics()->flush(); - }); + ); } } diff --git a/src/sentry/src/Metrics/Listener/OnWorkerStart.php b/src/sentry/src/Metrics/Listener/OnWorkerStart.php index a038813fc..a2b9d5b60 100644 --- a/src/sentry/src/Metrics/Listener/OnWorkerStart.php +++ b/src/sentry/src/Metrics/Listener/OnWorkerStart.php @@ -49,14 +49,16 @@ public function listen(): array */ public function process(object $event): void { + if ($this->feature->isMetricsEnabled() && $event->workerId == 0) { + $workerId = $event->workerId; + $eventDispatcher = $this->container->get(EventDispatcherInterface::class); + $eventDispatcher->dispatch(new MetricFactoryReady($workerId)); + } + if (! $this->feature->isDefaultMetricsEnabled()) { return; } - $workerId = $event->workerId; - $eventDispatcher = $this->container->get(EventDispatcherInterface::class); - $eventDispatcher->dispatch(new MetricFactoryReady($workerId)); - // The following metrics MUST be collected in worker. $metrics = [ 'worker_request_count', @@ -86,40 +88,39 @@ public function process(object $event): void 'ru_stime_tv_sec', ]; - $this->timer->tick($this->feature->getMetricsInterval(), function ($isClosing = false) use ($metrics, $event) { - if ($isClosing) { - return Timer::STOP; - } - - $server = $this->container->get(Server::class); - $serverStats = $server->stats(); - $this->trySet('gc_', $metrics, gc_status()); - $this->trySet('', $metrics, getrusage()); + $this->timer->tick( + $this->feature->getMetricsInterval(), + function () use ($metrics, $event) { + $server = $this->container->get(Server::class); + $serverStats = $server->stats(); + $this->trySet('gc_', $metrics, gc_status()); + $this->trySet('', $metrics, getrusage()); - metrics()->gauge( - 'worker_request_count', - (float) $serverStats['worker_request_count'], - ['worker' => (string) ($event->workerId ?? 0)], - ); - metrics()->gauge( - 'worker_dispatch_count', - (float) $serverStats['worker_dispatch_count'], - ['worker' => (string) ($event->workerId ?? 0)], - ); - metrics()->gauge( - 'memory_usage', - memory_get_usage(true) / 1024 / 1024, - ['worker' => (string) ($event->workerId ?? 0)], - Unit::megabyte() - ); - metrics()->gauge( - 'memory_peak_usage', - memory_get_peak_usage(true) / 1024 / 1024, - ['worker' => (string) ($event->workerId ?? 0)], - Unit::megabyte() - ); + metrics()->gauge( + 'worker_request_count', + (float) $serverStats['worker_request_count'], + ['worker' => (string) ($event->workerId ?? 0)], + ); + metrics()->gauge( + 'worker_dispatch_count', + (float) $serverStats['worker_dispatch_count'], + ['worker' => (string) ($event->workerId ?? 0)], + ); + metrics()->gauge( + 'memory_usage', + memory_get_usage(true) / 1024 / 1024, + ['worker' => (string) ($event->workerId ?? 0)], + Unit::megabyte() + ); + metrics()->gauge( + 'memory_peak_usage', + memory_get_peak_usage(true) / 1024 / 1024, + ['worker' => (string) ($event->workerId ?? 0)], + Unit::megabyte() + ); - metrics()->flush(); - }); + metrics()->flush(); + } + ); } } diff --git a/src/sentry/src/Metrics/Listener/PoolWatcher.php b/src/sentry/src/Metrics/Listener/PoolWatcher.php index caab50d47..8371d5991 100644 --- a/src/sentry/src/Metrics/Listener/PoolWatcher.php +++ b/src/sentry/src/Metrics/Listener/PoolWatcher.php @@ -57,45 +57,40 @@ abstract public function process(object $event): void; public function watch(Pool $pool, string $poolName, int $workerId): void { - if (! $this->feature->isMetricsEnabled()) { + if (! $this->feature->isPoolMetricsEnabled()) { return; } - $this->timer->tick($this->feature->getMetricsInterval(), function ($isClosing = false) use ( - $pool, - $workerId, - $poolName - ) { - if ($isClosing) { - return Timer::STOP; - } - - metrics()->gauge( - $this->getPrefix() . '_connections_in_use', - (float) $pool->getCurrentConnections(), - [ - 'pool' => $poolName, - 'worker' => (string) $workerId, - ] - ); - metrics()->gauge( - $this->getPrefix() . '_connections_in_waiting', - (float) $pool->getConnectionsInChannel(), - [ - 'pool' => $poolName, - 'worker' => (string) $workerId, - ] - ); - metrics()->gauge( - $this->getPrefix() . '_max_connections', - (float) $pool->getOption()->getMaxConnections(), - [ - 'pool' => $poolName, - 'worker' => (string) $workerId, - ] - ); + $this->timer->tick( + $this->feature->getMetricsInterval(), + function () use ($pool, $workerId, $poolName) { + metrics()->gauge( + $this->getPrefix() . '_connections_in_use', + (float) $pool->getCurrentConnections(), + [ + 'pool' => $poolName, + 'worker' => (string) $workerId, + ] + ); + metrics()->gauge( + $this->getPrefix() . '_connections_in_waiting', + (float) $pool->getConnectionsInChannel(), + [ + 'pool' => $poolName, + 'worker' => (string) $workerId, + ] + ); + metrics()->gauge( + $this->getPrefix() . '_max_connections', + (float) $pool->getOption()->getMaxConnections(), + [ + 'pool' => $poolName, + 'worker' => (string) $workerId, + ] + ); - metrics()->flush(); - }); + metrics()->flush(); + } + ); } } diff --git a/src/sentry/src/Metrics/Listener/QueueWatcher.php b/src/sentry/src/Metrics/Listener/QueueWatcher.php index c25c97699..d58d64762 100644 --- a/src/sentry/src/Metrics/Listener/QueueWatcher.php +++ b/src/sentry/src/Metrics/Listener/QueueWatcher.php @@ -47,45 +47,44 @@ public function listen(): array */ public function process(object $event): void { - if (! $this->feature->isMetricsEnabled()) { + if (! $this->feature->isQueueMetricsEnabled()) { return; } - $this->timer->tick($this->feature->getMetricsInterval(), function ($isClosing = false) { - if ($isClosing) { - return Timer::STOP; - } + $this->timer->tick( + $this->feature->getMetricsInterval(), + function () { + $config = $this->container->get(ConfigInterface::class); + $queues = array_keys($config->get('async_queue', [])); - $config = $this->container->get(ConfigInterface::class); - $queues = array_keys($config->get('async_queue', [])); + foreach ($queues as $name) { + $queue = $this->container->get(DriverFactory::class)->get($name); + $info = $queue->info(); - foreach ($queues as $name) { - $queue = $this->container->get(DriverFactory::class)->get($name); - $info = $queue->info(); + metrics()->gauge( + 'queue_waiting', + (float) $info['waiting'], + ['queue' => $name] + ); + metrics()->gauge( + 'queue_delayed', + (float) $info['delayed'], + ['queue' => $name] + ); + metrics()->gauge( + 'queue_failed', + (float) $info['failed'], + ['queue' => $name] + ); + metrics()->gauge( + 'queue_timeout', + (float) $info['timeout'], + ['queue' => $name] + ); + } - metrics()->gauge( - 'queue_waiting', - (float) $info['waiting'], - ['queue' => $name] - ); - metrics()->gauge( - 'queue_delayed', - (float) $info['delayed'], - ['queue' => $name] - ); - metrics()->gauge( - 'queue_failed', - (float) $info['failed'], - ['queue' => $name] - ); - metrics()->gauge( - 'queue_timeout', - (float) $info['timeout'], - ['queue' => $name] - ); + metrics()->flush(); } - - metrics()->flush(); - }); + ); } }