Logging - Как пользоваться логами¶
CPVM has great logging system.
Параметры логирования вне фрагмента¶
Пример конфигурации запуска в виде json (опущено все кроме логирования):
{ fragment: { id: "fr1", version: 240234042 } transactionId: "I1FKJ3389sfdku3e" dam: "1.2.3.255" ... logging: { redirections: { stdout: { id: "myLog" scope: "transaction" strictOrder: true }, stderr: { id: "myLog" scope: "transaction" strictOrder: true } } allowCreateLogs: false } }
- каждый фрагмент по умлочанию имеет переопределнные sys.stderr/sys.stdout, которые будут пытаться писать в логи с идентификаторами "stderr"/"stdout"
- для каждого запуска фрагмента можно сконфигурировать "перенаправления". Например, фрагмент пытается писать свой stderr в лог c ID "stderr", а мы перенаправляем его в лог с другим ID. В примере выше лог фрагмента "stderr" перенаправлялся в общий для всей транзакции лог "myLog" с сохранением порядка
- если перенаправление не заданы - логи пропадают (никуда не выводятся), за исключением случая, когда allowCreateLogs=true.
- allowCreateLogs в параметрах означает, можно ли автоматом создавать логи для фрагмента даже если для него не скнофигурировано ни одного перенаправления
Параметры логирования внутри фрагмента¶
import ap import sys sys.stdout = ap.create_log("myLogId", scope = "transaction") sys.stderr = sys.stdout # можно задать тот-же лог что и для stdout
Конфигурирование логов внутри фрагмента необязательно, по умолчанию для каждого фрагмента перед стартом задается следующая конфигурация:
sys.stdout = ap.create_log("stdout") sys.stderr = ap.create_log("stderr")
3 вида логов¶
- shared - записи в лог одновременно идут из разных процессов/потоков. Лог можно загружать в реальном времени. Могут быть гарантии частичного порядка, в зависимости от конфигурации лога. При перезапусках фрагментов их записи не будут удалятся из лога, поэтому для такого вида логов лучше помечать запуски фрагментов (print("my fragment started")) и включать опцию strictOrder, что теоритически позволит отбросить незавершенные части лога.
- exclusive - только один процесс/поток может писать в данный лог. Лог можно загружать в реальном времени. Строгий порядок гарантирован при любых условиях.
- offline shared - (НЕ ГОТОВО, в TVM io выводить может?) аналогичен shared, но смешивание записей разных процессов/потоков происходит уже после остановки транзакции, что позволяет получать целостный лог с учетом перезапусков. Данный вид лога не поддерживает скоупы user, global, а также загрузку в реальном времени.
Скоупы¶
Пример: scope: "transaction" - это значит, что лог с заданным ID уникален только в пределах транзакции и привязан к ее жизненному циклу
какие еще есть скоупы:
- execution (exclusive) - лог уникален в пределах конретного запуска фрагмента и изолирован от всех других запусков.
- fragment (shared или offline shared) - лог уникален в пределах frId (общий для всех запусков конкретного прототипа фрагмента).
- transaction (shared или offline shared) - лог уникален в пределах транзакции (общий для всех фрагментов конкретной транзакции)
- user (shared) - лог общий для всех транзакций юзера.
Перезапуски¶
При перезапуске фрагмента: exclusive-логи могут стираться (опционально), а для нового запуска создается новый лог. все что фрагмент записал в shared-лог, остается в нем навечно. Удалится записанные данные могут только в случае удаления всего лога целиком, что может произойти для логов со скоупом execution.
Как получить список всех логов¶
GET /vm/transactions/{trId}/logs/
- получить список логов со скоупами execution, fragment, transaction, которые привязаны к кокретной транзакции
GET /vm/logs/
- получить список всех логов со скоупом user
Порядок¶
- для любых параметров запуска, порядок гарнтирован в пределах одного запуска фрагмента.
- если strictOrder в параметрах лога == true, значит в общих логах будет устанавливаться частичный порядок удовлетворяющий отношению "до-после": все записи в лог фрагмента-родителя случившиеся до запуска (call/call_async) будут всегда идти ДО записей в лог запущенного фрагмента.
- это означает, что:
- если все фрагменты запускаются синхронно и strictOrder = true, весь лог будет целиком строго упорядочен
- фрагменты запускающиеся асинхронно при strictOrder = true, будут смешивать свои логи:
- с фрагментом родителем (но только после момента запуска!)
- с параллельно запущенными родственными фрагментами (от того же родителя - тут порядок сохраняется только для каждого фрагмента в отдельности)
- если strictOrder = false - никаких гарантий частичного порядка между записями разных фрагментов не дается. Дебажить по таким логам тяжело, т.к. реально могут быть перемешивания во времени