콘텐츠로 이동
Bluetape4k 문서1.11

운영, 설정과 실전 레시피

최신 안정판 Bluetape4k 1.11.0 릴리스 기준

좋은 API 호출도 backend 설정과 lifecycle이 맞지 않으면 쓸 수 있는 로그가 되지 않습니다. 운영에서는 “호출했는가”보다 “필요한 field가 안전하게 출력되고 종료 전에 전달됐는가”를 확인합니다.

<pattern>%date %-5level [%thread] traceId=%X{traceId} requestId=%X{requestId} %logger - %msg%n</pattern>

structured JSON encoder를 사용하면 같은 key를 structured field로 매핑합니다. 설정은 application repository가 소유하고 library가 root logger를 변경하지 않습니다.

suspend fun handle(call: ApplicationCall) {
val requestId = sanitize(call.request.headers["X-Request-Id"])
?: UUID.randomUUID().toString()
withCoroutineLoggingContext("requestId" to requestId) {
log.info { "Request accepted" }
service.execute()
}
}

외부 값을 길이와 문자 집합으로 제한한 뒤 MDC에 넣습니다. token, cookie, authorization header, raw body는 message와 MDC 모두에서 제외합니다.

MDC test는 다음을 직접 assertion합니다.

  • block 안의 값
  • nested scope 뒤 outer 값 복원
  • exception 뒤 복원
  • restorePrevious=false 뒤 제거
  • null entry 미설치
  • dispatcher 전환 뒤 coroutine context 전파

Channel test는 capturing appender로 level/order/prefix/error를 확인하고 closeAndJoin() 뒤 collector inactive, close idempotency, post-close drop을 검증합니다.

Terminal window
./gradlew :bluetape4k-logging:test --no-configuration-cache
증상확인할 경계조치
requestId가 간헐적으로 없음plain MDC가 coroutine 경계를 넘었는가coroutine helper로 scope를 감쌉니다.
DEBUG가 꺼져도 CPU 사용 증가eager message/serializationlambda extension으로 이동합니다.
종료 직전 log 누락async channel close가 drain으로 오인됨중요한 event는 durable path로 이동합니다.
duplicate log line여러 provider/appender 또는 additive loggerruntime classpath와 Logback hierarchy를 확인합니다.
fallback message 반복supplier exceptionmessage 생성 코드를 별도 테스트하고 단순화합니다.

현재 등록된 logging 전용 workshop은 없습니다. Ktor/Spring request boundary에서 위 recipe를 적용하고 nested MDC와 shutdown test를 추가하는 것이 가장 작은 runnable exercise입니다.