private function attachEventHandlers()
    {
        $out = function ($string) {
            $this->stdout(Console::renderColoredString($string));
        };

        Event::on(Queue::class, Queue::EVENT_BEFORE_EXEC, function ($event) use ($out) {
            /** @var JobEvent $event */
            $out("%GNew job%n '" . get_class($event->job) . "'\n");
            $this->ensureLimits();
        });

        Event::on(Queue::class, Queue::EVENT_AFTER_EXEC, function ($event) use ($out) {
            /** @var JobEvent $event */
            $out("%GJob%n '" . get_class($event->job) . "' %Gis completed%n\n");
        });

        Event::on(Queue::class, Queue::EVENT_AFTER_ERROR, function ($event) use ($out) {
            /** @var ErrorEvent $event */
            $out("%RJob '" . get_class($event->job) . "' finished with error:%n '" . $event->error . "'\n");
        });

        Event::on(Queue::class, CliQueue::EVENT_WORKER_LOOP, function (\yii\queue\cli\WorkerEvent $event) use ($out) {
            $exitCode = $this->ensureLimits();
            if ($exitCode !== null) {
                $out('Reached limit of ' . static::MAX_EXECUTED_JOBS . " executed jobs. Stopping process.\n");
                $event->exitCode = $exitCode;
            }
        });

        Event::on(AbstractPackageCommand::class, AbstractPackageCommand::EVENT_BEFORE_RUN, function ($event) use ($out) {
            /** @var AbstractPackageCommand $command */
            $command = $event->sender;
            $out('%g[' . get_class($command) . ']%n Working on package %N' . $command->getPackage()->getFullName() . "%n\n");
        });
    }