4.4 KiB
[AIFriendlyLogging] Tags: LOGGING, TRACEABILITY, STRUCTURED_LOG, DEBUG, CLEAN_ARCHITECTURE
Логирование — это мой критически важный механизм для декларации
belief state(внутреннего состояния/намерения) и трассировки выполнения кода. Каждая значимая операция, проверка контракта или изменение состояния ДОЛЖНЫ сопровождаться структурированной записью в лог. Это делает поведение кода в рантайме полностью прозрачным и отлаживаемым.
Rules
ArchitecturalBoundaryCompliance
Логирование в его прямой реализации (т.е. вызов logger.info, Timber.i и т.д.) КАТЕГОРИЧЕСКИ ЗАПРЕЩЕНО внутри модуля :domain.
Согласно принципам чистой архитектуры, слойdomainдолжен быть полностью независим от внешних фреймворков и платформ (включая Android). Его задача — содержать исключительно бизнес-логику. Логирование, как и другие инфраструктурные задачи, должно выполняться в более внешних слоях, таких как:dataили:app.
StructuredLogFormat
Все записи в лог должны строго следовать этому формату для обеспечения машиночитаемости и консистентности.
`logger.level("[LEVEL][ANCHOR_NAME][BELIEF_STATE] Message with {} placeholders for data.")`
ComponentDefinitions
Components
- [LEVEL]: Один из стандартных уровней логирования:
DEBUG,INFO,WARN,ERROR. Я также использую специальный уровеньCONTRACT_VIOLATIONдля логов, связанных с проваломrequireилиcheck. - [ANCHOR_NAME]: Точное имя семантического якоря из кода, к которому относится данный лог. Это создает неразрывную связь между статическим кодом и его выполнением. Например:
[ENTRYPOINT],[ACTION],[PRECONDITION],[FALLBACK]. - [BELIEF_STATE]: Краткое, четкое описание моего намерения в
snake_case. Это отвечает на вопрос 'почему' я выполняю этот код. Примеры:validating_input,calling_external_api,mutating_state,persisting_data,handling_exception,mapping_dto.
Example
Вот как я применяю этот стандарт на практике внутри функции:
// ...
// [ENTRYPOINT]
suspend fun processPayment(request: PaymentRequest): Result {
logger.info("[INFO][ENTRYPOINT][processing_payment] Starting payment process for request '{}'.", request.id)
// [PRECONDITION]
logger.debug("[DEBUG][PRECONDITION][validating_input] Validating payment request.")
require(request.amount > 0) { "Payment amount must be positive." }
// [ACTION]
logger.info("[INFO][ACTION][calling_external_api] Calling payment gateway for amount {}."), request.amount)
val result = paymentGateway.execute(request)
// ...
}
TraceabilityIsMandatory
Каждая запись в логе ДОЛЖНА быть семантически привязана к якорю в коде. Логи без якоря запрещены. Это не опция, а фундаментальное требование для обеспечения полной трассируемости потока выполнения.
DataAsArguments_NotStrings
Данные (переменные, значения) должны передаваться в логгер как отдельные аргументы, а не встраиваться в строку сообщения. Я использую плейсхолдеры {}. Это повышает производительность и позволяет системам сбора логов индексировать эти данные.
[/End AIFriendlyLogging]