MonitorCommand.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <?php
  2. namespace Illuminate\Database\Console;
  3. use Illuminate\Contracts\Events\Dispatcher;
  4. use Illuminate\Database\ConnectionResolverInterface;
  5. use Illuminate\Database\Events\DatabaseBusy;
  6. use Symfony\Component\Console\Attribute\AsCommand;
  7. #[AsCommand(name: 'db:monitor')]
  8. class MonitorCommand extends DatabaseInspectionCommand
  9. {
  10. /**
  11. * The name and signature of the console command.
  12. *
  13. * @var string
  14. */
  15. protected $signature = 'db:monitor
  16. {--databases= : The database connections to monitor}
  17. {--max= : The maximum number of connections that can be open before an event is dispatched}';
  18. /**
  19. * The console command description.
  20. *
  21. * @var string
  22. */
  23. protected $description = 'Monitor the number of connections on the specified database';
  24. /**
  25. * The connection resolver instance.
  26. *
  27. * @var \Illuminate\Database\ConnectionResolverInterface
  28. */
  29. protected $connection;
  30. /**
  31. * The events dispatcher instance.
  32. *
  33. * @var \Illuminate\Contracts\Events\Dispatcher
  34. */
  35. protected $events;
  36. /**
  37. * Create a new command instance.
  38. *
  39. * @param \Illuminate\Database\ConnectionResolverInterface $connection
  40. * @param \Illuminate\Contracts\Events\Dispatcher $events
  41. */
  42. public function __construct(ConnectionResolverInterface $connection, Dispatcher $events)
  43. {
  44. parent::__construct();
  45. $this->connection = $connection;
  46. $this->events = $events;
  47. }
  48. /**
  49. * Execute the console command.
  50. *
  51. * @return void
  52. */
  53. public function handle()
  54. {
  55. $databases = $this->parseDatabases($this->option('databases'));
  56. $this->displayConnections($databases);
  57. if ($this->option('max')) {
  58. $this->dispatchEvents($databases);
  59. }
  60. }
  61. /**
  62. * Parse the database into an array of the connections.
  63. *
  64. * @param string $databases
  65. * @return \Illuminate\Support\Collection
  66. */
  67. protected function parseDatabases($databases)
  68. {
  69. return collect(explode(',', $databases))->map(function ($database) {
  70. if (! $database) {
  71. $database = $this->laravel['config']['database.default'];
  72. }
  73. $maxConnections = $this->option('max');
  74. return [
  75. 'database' => $database,
  76. 'connections' => $connections = $this->getConnectionCount($this->connection->connection($database)),
  77. 'status' => $maxConnections && $connections >= $maxConnections ? '<fg=yellow;options=bold>ALERT</>' : '<fg=green;options=bold>OK</>',
  78. ];
  79. });
  80. }
  81. /**
  82. * Display the databases and their connection counts in the console.
  83. *
  84. * @param \Illuminate\Support\Collection $databases
  85. * @return void
  86. */
  87. protected function displayConnections($databases)
  88. {
  89. $this->newLine();
  90. $this->components->twoColumnDetail('<fg=gray>Database name</>', '<fg=gray>Connections</>');
  91. $databases->each(function ($database) {
  92. $status = '['.$database['connections'].'] '.$database['status'];
  93. $this->components->twoColumnDetail($database['database'], $status);
  94. });
  95. $this->newLine();
  96. }
  97. /**
  98. * Dispatch the database monitoring events.
  99. *
  100. * @param \Illuminate\Support\Collection $databases
  101. * @return void
  102. */
  103. protected function dispatchEvents($databases)
  104. {
  105. $databases->each(function ($database) {
  106. if ($database['status'] === '<fg=green;options=bold>OK</>') {
  107. return;
  108. }
  109. $this->events->dispatch(
  110. new DatabaseBusy(
  111. $database['database'],
  112. $database['connections']
  113. )
  114. );
  115. });
  116. }
  117. }