← Назад к справке

Бизнес-процессы

Журнал, отладка и ошибки

Как писать сообщения в журнал бизнес-процесса, отлаживать PHP-код, ловить ошибки и разбирать зависшие процессы.

Если в PHP-блоке ошибка, процесс может остановиться без понятного сообщения в интерфейсе. Поэтому рабочий минимум — писать ключевые шаги в журнал процесса и оборачивать PHP-код в try-catch.

Журнал процесса

Журнал бизнес-процесса помогает понять, какие данные были внутри конкретного запуска.

WriteToTrackingService

Для записи в отчёт используется WriteToTrackingService(). Первый параметр должен быть строкой.

$this->WriteToTrackingService(
    'PHP-блок начал выполнение',
    0,
    \CBPTrackingType::Report
);
Тип Когда использовать
\CBPTrackingType::Report Обычные сообщения для отчёта.
\CBPTrackingType::Error Ошибка, которую нужно явно показать.
\CBPTrackingType::FaultActivity Критическая ошибка действия.
\CBPTrackingType::Custom Пользовательское сообщение.

Массивы и JSON

Массив нужно сначала преобразовать в строку: через print_r() или json_encode().

/**
 * Пишет массив в журнал процесса.
 */
function writeArrayToTracking($context, array $items): void
{
    $context->WriteToTrackingService(
        print_r($items, true),
        0,
        \CBPTrackingType::Report
    );
}

/**
 * Пишет массив в журнал процесса как JSON.
 */
function writeJsonToTracking($context, array $items): void
{
    $context->WriteToTrackingService(
        json_encode($items, JSON_UNESCAPED_UNICODE),
        0,
        \CBPTrackingType::Report
    );
}

writeArrayToTracking($this, ['deal_id' => 123]);
writeJsonToTracking($this, ['deal_id' => 123]);

Отладка

Для PHP-кода в бизнес-процессе лучше сразу закладывать обработку ошибок.

try-catch

/**
 * Пишет ошибку в журнал бизнес-процесса.
 */
function writeBpException($context, \Throwable $exception): void
{
    $message = sprintf(
        'Ошибка: %s. Файл: %s. Строка: %s',
        $exception->getMessage(),
        $exception->getFile(),
        $exception->getLine()
    );

    $context->WriteToTrackingService(
        $message,
        0,
        \CBPTrackingType::FaultActivity
    );
}

try {
    $this->WriteToTrackingService(
        'Начало PHP-блока',
        0,
        \CBPTrackingType::Report
    );

    // Основной код

    $this->WriteToTrackingService(
        'Конец PHP-блока',
        0,
        \CBPTrackingType::Report
    );
} catch (\Throwable $exception) {
    writeBpException($this, $exception);

    // Если процесс должен остановиться, можно пробросить ошибку дальше.
    // throw $exception;
}

Лог в файл Битрикса

Для технической отладки можно писать в обычный лог Битрикса через AddMessage2Log(). Это не заменяет журнал процесса, но помогает при проверке серверного кода.

/**
 * Пишет сообщение в лог Битрикса.
 */
function writeBitrixLog(string $message, array $context = []): void
{
    AddMessage2Log(
        [
            'message' => $message,
            'context' => $context,
        ],
        'bizproc_debug'
    );
}

writeBitrixLog(
    'Проверка PHP-блока бизнес-процесса',
    [
        'document_id' => $this->getDocumentId(),
    ]
);

Ошибки и зависшие процессы

Если процесс не идёт дальше, нужно понять: он упал с ошибкой, ждёт задание, ждёт паузу, ждёт внешнее событие или завис из-за кода.

Что смотреть первым

  • журнал бизнес-процесса;
  • ошибки PHP в логах сервера;
  • Network в браузере, если процесс стартует от действия в интерфейсе;
  • задания бизнес-процесса, если процесс ждёт пользователя;
  • паузы, ожидания дат и ожидания внешних событий;
  • код пользовательских действий, если они есть в шаблоне.

Найти запущенные процессы

Для технической диагностики можно посмотреть экземпляры бизнес-процессов в таблице экземпляров workflow.

\Bitrix\Main\Loader::includeModule('bizproc');

/**
 * Получает последние запущенные экземпляры бизнес-процессов.
 */
function fetchRecentWorkflowInstances(int $limit): array
{
    $workflows = [];

    $workflow_result = \Bitrix\Bizproc\Workflow\Entity\WorkflowInstanceTable::getList([
        'select' => [
            'ID',
            'WORKFLOW_TEMPLATE_ID',
            'DOCUMENT_ID',
            'STARTED',
            'STARTED_BY',
            'MODIFIED',
            'OWNER_ID',
        ],
        'order' => [
            'MODIFIED' => 'DESC',
        ],
        'limit' => $limit,
    ]);

    while ($workflow = $workflow_result->fetch()) {
        $workflows[] = $workflow;
    }

    return $workflows;
}

$workflows = fetchRecentWorkflowInstances(20);

print_r($workflows);

Остановить процесс

Если нужно аварийно остановить процесс, можно использовать CBPDocument::TerminateWorkflow(). Перед этим лучше сохранить ID процесса и document id в лог.

\Bitrix\Main\Loader::includeModule('bizproc');

/**
 * Останавливает бизнес-процесс.
 */
function terminateWorkflow(string $workflow_id, array $document_id): array
{
    $error_messages = [];

    \CBPDocument::TerminateWorkflow(
        $workflow_id,
        $document_id,
        $error_messages
    );

    return [
        'is_success' => empty($error_messages),
        'error_messages' => $error_messages,
    ];
}

$terminate_result = terminateWorkflow(
    $workflow_id,
    [
        'crm',
        'CCrmDocumentDeal',
        'DEAL_' . $deal_id,
    ]
);

print_r($terminate_result);

Источники