master

laravel/framework

Last updated at: 29/12/2023 09:21

MonitorCommand.php

TLDR

The provided file contains the MonitorCommand class, which is part of the Illuminate\Database\Console namespace. This class is a command that monitors the number of connections on specified databases and dispatches events when the number of connections exceeds a certain maximum limit.

Methods

handle

This method executes the console command. It parses the databases to monitor, displays the connections for each database, and dispatches events if a maximum number of connections is specified.

parseDatabases

This method parses the database parameter and returns a collection of arrays, where each array represents a database connection. It also checks if a database is not specified and uses the default database connection in that case.

displayConnections

This method displays the databases and their connection counts in the console.

dispatchEvents

This method dispatches the database monitoring events if the status of a database connection is not "OK".

Classes

Class MonitorCommand

This class extends the DatabaseInspectionCommand class and represents a console command to monitor the number of connections on specified databases. It has the following properties:

  • $signature: The name and signature of the console command.
  • $description: The console command description.
  • $connection: The connection resolver instance.
  • $events: The events dispatcher instance.

The class has the following methods:

  • __construct: Creates a new instance of the MonitorCommand class.
  • handle: Executes the console command.
  • parseDatabases: Parses the database parameter into an array of connections.
  • displayConnections: Displays the databases and their connection counts in the console.
  • dispatchEvents: Dispatches the database monitoring events.
<?php

namespace Illuminate\Database\Console;

use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\ConnectionResolverInterface;
use Illuminate\Database\Events\DatabaseBusy;
use Illuminate\Support\Composer;
use Symfony\Component\Console\Attribute\AsCommand;

#[AsCommand(name: 'db:monitor')]
class MonitorCommand extends DatabaseInspectionCommand
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'db:monitor
                {--databases= : The database connections to monitor}
                {--max= : The maximum number of connections that can be open before an event is dispatched}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Monitor the number of connections on the specified database';

    /**
     * The connection resolver instance.
     *
     * @var \Illuminate\Database\ConnectionResolverInterface
     */
    protected $connection;

    /**
     * The events dispatcher instance.
     *
     * @var \Illuminate\Contracts\Events\Dispatcher
     */
    protected $events;

    /**
     * Create a new command instance.
     *
     * @param  \Illuminate\Database\ConnectionResolverInterface  $connection
     * @param  \Illuminate\Contracts\Events\Dispatcher  $events
     * @param  \Illuminate\Support\Composer  $composer
     */
    public function __construct(ConnectionResolverInterface $connection, Dispatcher $events, Composer $composer)
    {
        parent::__construct($composer);

        $this->connection = $connection;
        $this->events = $events;
    }

    /**
     * Execute the console command.
     *
     * @return void
     */
    public function handle()
    {
        $databases = $this->parseDatabases($this->option('databases'));

        $this->displayConnections($databases);

        if ($this->option('max')) {
            $this->dispatchEvents($databases);
        }
    }

    /**
     * Parse the database into an array of the connections.
     *
     * @param  string  $databases
     * @return \Illuminate\Support\Collection
     */
    protected function parseDatabases($databases)
    {
        return collect(explode(',', $databases))->map(function ($database) {
            if (! $database) {
                $database = $this->laravel['config']['database.default'];
            }

            $maxConnections = $this->option('max');

            return [
                'database' => $database,
                'connections' => $connections = $this->getConnectionCount($this->connection->connection($database)),
                'status' => $maxConnections && $connections >= $maxConnections ? '<fg=yellow;options=bold>ALERT</>' : '<fg=green;options=bold>OK</>',
            ];
        });
    }

    /**
     * Display the databases and their connection counts in the console.
     *
     * @param  \Illuminate\Support\Collection  $databases
     * @return void
     */
    protected function displayConnections($databases)
    {
        $this->newLine();

        $this->components->twoColumnDetail('<fg=gray>Database name</>', '<fg=gray>Connections</>');

        $databases->each(function ($database) {
            $status = '['.$database['connections'].'] '.$database['status'];

            $this->components->twoColumnDetail($database['database'], $status);
        });

        $this->newLine();
    }

    /**
     * Dispatch the database monitoring events.
     *
     * @param  \Illuminate\Support\Collection  $databases
     * @return void
     */
    protected function dispatchEvents($databases)
    {
        $databases->each(function ($database) {
            if ($database['status'] === '<fg=green;options=bold>OK</>') {
                return;
            }

            $this->events->dispatch(
                new DatabaseBusy(
                    $database['database'],
                    $database['connections']
                )
            );
        });
    }
}