简体中文 English 繁體中文 日本語 Русский
本文为静态镜像,内容以交互版为准 在交互式文档中心打开 →

Руководство по диагностике модулей

Когда модуль "не отвечает", симптомы можно разделить на три категории проблем, каждая из которых имеет соответствующий инструмент диагностики в рамках фреймворка (RFC EPRFC-2026-001, направление пять):

Симптом Инструмент диагностики Уровень диагностики
Модуль не загружен ErisPulse.runtime.explain_module(name) Цепочка регистрации и загрузки
Событие не обрабатывается ErisPulse.runtime.explain_event(event) Проверка входа в систему распределения
Команда не запускается Цепочка принятия решений о распределении (тестовый DispatchTrace / встроенный в фреймворк trace) Цепочка определения команд

Оба диагностических функции являются чисто чтением операциями, не изменяющими никакого состояния, и могут быть вызваны в любое время; возвращают машинно-читаемый словарь, который можно отформатировать с помощью format_report() для получения текста, удобного для восприятия человеком.

Сценарий 1: Модуль не загружен

from ErisPulse.runtime import explain_module, format_report

report = explain_module("MyModule")
print(format_report(report))

explain_module() проверяет каждый пункт и выдает заключение, охватывая следующие причины:

Проверяемый элемент Описание
Не зарегистрирован Пакет не установлен, имя группы entry-point указано неверно, или имя регистрации не совпадает с именем запроса
Ленивая загрузка не инициализирована Нормальное состояние, а не ошибка: модуль ленивой загрузки инициализируется при первом вызове (например, module.call или запуск команды)
Отключено в конфигурации ErisPulse.modules.status.<имя модуля> = false (если не настроено, по умолчанию включено)
Зависимости не загружены В списке depends, объявленном модулем, есть модули, которые не готовы
Несовместимая версия SDK В метаданных модуля указано значение min_sdk_version, которое выше текущей версии фреймворка
Ошибка при on_load Регистрация прошла успешно, но модуль не загружен, и нет вышеуказанных причин — проверьте записи ERROR в журнале запуска, соответствующие имени модуля

Возвращаемая структурированная структура dict: registered / loaded / lazy / enabled (None означает, что по умолчанию включено, если не настроено) / missing_dependencies / sdk_version_ok / conclusion (заключение в одной фразе) / reasons (список причин).

Сценарий 2: Событие не отвечает

from ErisPulse.runtime import explain_event, format_report

report = explain_event(event)   # Event, полученный внутри обработчика, или исходный словарь события
print(format_report(report))

explain_event() выводит результаты в порядке фактической проверки на входе маршрутизации:

  1. Платформа-адаптер не зарегистрирована: экземпляр адаптера с указанным platform отсутствует — событие вообще не попадает в фреймворк.
  2. Идентификационный измеритель отвергнут пространством действия: пользователь / сессия / Bot / адаптер заблокированы — событие полностью отбрасывается на входе маршрутизации. Конфигурация пространства действия см. в модульной конфигурации.
  3. Модуль заблокирован для текущей сессии: различаются текущая сессия available_modules (доступные) и blocked_modules (заблокированные пространством действия).
  4. Текст напоминает команду, но не соответствует ни одной: текст с префиксом команды, но не соответствует ни одной зарегистрированной команде — проверьте конфигурацию префикса и имена команд.

Если все входные проверки пройдены, но ответа по-прежнему нет, вывод указывает на дальнейшее исследование двух мест:

Сценарий 3: Команда не была запущена (цепочка принятия решений при диспетчеризации)

Для того, чтобы сообщение с префиксом действительно выполнило команду, оно должно последовательно пройти через: определение текста команды → сопоставление команды (с подсказкой по опечатке при неудаче) → область действия → пользовательский ACL → проверка владельца → функция разрешений → охлаждение / ограничение скорости / скрытое отбрасывание из-за лимита использования → отказ и уведомление об устаревании → парсинг параметров → выполнение. Рамка фиксирует каждую точку принятия решения как причинно-следственную цепочку и даёт заключение о том, "почему команда не была запущена".

В процессе тестирования: TestBot.dispatch возвращает DispatchTrace

Рекомендуется использовать тестирование для воспроизведения проблемы и непосредственно читать причинно-следственную цепочку (инструкции по использованию инструментов см. в модульном тестировании):

trace = await bot.dispatch(create_command_event("dailyx", user_id="123"))

trace.verdict          # executed / rejected / dropped / failed / no_match / passed
print(trace.explain()) # построчное описание причинно-следственной цепочки (в текущем языке)
trace.assert_no_match()

Встроенный модуль trace в рамке

Цепочка принятия решений предоставляется ErisPulse.Core.Event.trace и по умолчанию не имеет дополнительных накладных расходов — если не находится в контексте сбора данных, точки принятия решений просто пропускаются, и производственные пути остаются незамеченными:

from ErisPulse.Core.Event import (
    start_dispatch_trace,
    format_dispatch_trace,
    final_verdict,
)

with start_dispatch_trace() as records:
    ...  # сбор данных о диспетчеризации (включая производные задачи обработчиков)

print(format_dispatch_trace(records))   # человекочитаемая причинно-следственная цепочка (в текущем языке)
print(final_verdict(records))           # общий вывод

Значения final_verdict():

Заключение Значение
executed Команда была выполнена
rejected Была отклонена по правилам разрешений (область действия / ACL / владелец / функция разрешений)
dropped Была скрыто отброшена (охлаждение / ограничение скорости / лимит использования / отказ промежуточного слоя)
failed Возникла ошибка при выполнении
no_match С префиксом, но не совпало ни с одной командой
passed Это не текст команды, передано обработчику сообщений

Записи представлены в виде машинно-читаемого словаря (stage / verdict / message_key / params), пользователь может отфильтровать по stage при настройке собственного отображения (например, показать только cooldown).

Определение скрытого срабатывания правил управления

При срабатывании cooldown= / rate_limit= / usage_limit= по умолчанию происходит скрытое отбрасывание (команда всё равно считается активированной, не передаётся низкоприоритетному обработчику), что может быть ошибочно расценено как "команда сломана": наблюдаемое поведение — некоторые пользователи могут использовать команду, а другие получают нулевой ответ, и в причинно-следственной цепочке появляется запись dropped для соответствующего stage. Команда с deprecated= ведёт себя иначе — при вызове автоматически отправляется сообщение об устаревании (отказ от выполнения при deprecated_reject=True).

Общие рекомендации