Skip to content

Commit

Permalink
로깅을 지표전송처럼
Browse files Browse the repository at this point in the history
  • Loading branch information
jojoldu committed Mar 11, 2024
1 parent 836169b commit a617c2a
Showing 1 changed file with 34 additions and 28 deletions.
62 changes: 34 additions & 28 deletions posts/logging/loggin_is_feature/README.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,34 @@
# 로깅을 나누기
# 로깅과 도메인


1. 코드 대 로그/메트릭 비율이 낮다.
실제 예약 관련 코드 수만큼이나 많은 계측 코드 라인이 있다.

2. 계측 세부 정보에 대해 더 알아야 한다.
코드에는 사용해야 하는 메트릭 이름과 전달해야 하는 정확한 컨텍스트 내용 등이 참조되어 있다.
시스템을 구축하다보면 다음과 같이 크게 2개의 로그를 남긴다.

```ts
logger.error(`Lost touch with Reality after ${timeout} seconds`);
logger.trace(`Distance traveled in the wilderness: ${distance}`);
```
logger.error(`API Timeout: ${timeout} seconds`, e);
logger.info(`Ordered Food Product Id: ${product.id}`);

이 두 기능은 하나의 구현을 공유하는 별개의 기능이다.
logger.trace(`Total Order Price Amount: ${sum(products.amount)}`);
```

- 에러 로깅(오류 및 정보)은 애플리케이션의 사용자 인터페이스의 일부이다.
- 이는 시스템 관리자 및 운영자뿐만 아니라 에러 담당자가 장애를 디버깅하거나 실행 중인 시스템의 진행 상황을 모니터링하기 위해 추적하기 위한 것이다.
(error 와 info 로그는 앞으로 에러 로그로 통칭한다.)

이 2개의 로그 모두 로깅을 표현하지만, 실상은 목적이 다르다.

- 디버깅 로깅(디버그 및 추적)은 프로그래머를 위한 인프라이다.
- 이는 프로그래머가 개발 중인 시스템 내부에서 어떤 일이 일어나고 있는지 이해하는 데 도움을 주기 위한 것이므로 프로덕션 환경에서는 켜지 말아야 한다.
- 에러 (정보) 로깅은 운영 환경에서 장애를 디버깅하거나 실행 중인 시스템의 진행 상황을 모니터링하기 위해 추적하기 위한 것이다.
- 디버깅 로깅은 프로그래머가 개발 중인 시스템 내부에서 어떤 일이 일어나고 있는지 이해하는 데 도움을 주기 위한 것이므로 프로덕션 환경에서는 실행되지 말아야 한다.

이러한 차이점을 고려할 때 이 두 가지 유형의 로깅에 서로 다른 기술을 사용하는 것을 고려해야 한다.
이러한 차이점을 고려할 때 이 **두 가지 유형의 로깅에 서로 다른 방법을 사용하는 것을 고려**해야 한다.

에러 로깅은 감사 로그나 장애 복구와 같은 누군가의 요구 사항에 따라 테스트 중심으로 이루어져야 한다.
테스트를 통해 각 메시지의 용도를 고려하고 제대로 작동하는지 확인할 수 있다.
또한 테스트는 다른 사람들이 이러한 로그 메시지를 분석하기 위해 작성한 도구와 스크립트가 손상되지 않도록 보호한다.
반면에 디버깅 로깅은 시스템에서 일어나는 일을 세밀하게 추적해야 하는 프로그래머의 필요성으로 적용 한다.
디버깅 로깅은 스캐폴딩이므로 테스트를 거칠 필요가 없으며 에러 로그처럼 메시지가 일관적일 필요도 없다.
결국 이러한 메시지를 운영 환경에서 사용하지 않는다.

로깅이 아닌 알림
또한 목적이 명확하니 메시지 역시 일관적이어야 한다.
운영 환경에서 올바르게 작동하는 것을 보장하기 위해 **테스트 코드 역시 작성이 필요하다**.

로거를 포함한 정적 전역 객체에 대한 단위 테스트를 작성하는 것은 서투른 작업이다.
파일 시스템에서 읽거나 테스트를 위해 추가 애펜더 객체를 관리해야 하며, 테스트가 서로 간섭하지 않도록 나중에 정리하고 올바른 로거에 올바른 수준을 설정해야 한다는 점을 기억해야 한다.
테스트의 노이즈는 코드가 도메인과 로깅 인프라의 두 가지 수준에서 작동하고 있음을 알려준다.
반면에 디버깅 로깅은 **운영 환경에서의 올바른 작동이 필요하지 않다**.
오로지 프로그래머가 개발 단계에서 시스템 내부의 작동 방식을 확인하기 위한 용도이므로 **테스트를 거칠 필요가 없으며 에러 로그처럼 메시지가 일관적일 필요도 없다**.

똑같은 로그인데 굳이 이 2개를 구분해서 관리가 필요할까? 라는 생각이 든다면, **에러 (정보) 로그는 로그 보다는 지표 전송**으로 생각해보자.
로그를 남기는게 아니라 지표전송 혹은 알람으로 보내야 한다고 생각하면 좀 더 해당 로그를 도메인처럼 생각할 수 있다.

예를 들어 다음과 같이 운영 환경에서의 상황을 모니터링 하기 위해 다음과 같이 "카트에서 음식 상품을 삭제 처리할때만 추적"이 필요하다고 해보자.

```ts
function removeCart(product: Product) {
Expand All @@ -43,13 +39,23 @@ function removeCart(product: Product) {
}
```

위 코드에서는 카트 속 상품을 지우는 기능과 더불어서 로깅 인프라가 함께 포함되어 있다.
이 에러 (정보) 로깅은 **운영 환경에서 꼭 정상 작동해야하는 기능**이다.

하지만, Java와 같은 환경에서는 `static logger` 는 테스트 검증이 어렵다.
또한
이 코드는 위치와 렌더링 에러 정보라는 두 가지 작업을 동시에 수행하므로 단일 책임 원칙을 위반한다.

테스트의 노이즈는 코드가 도메인과 로깅 인프라의 두 가지 수준에서 작동하고 있음을 알려준다.
므로 테스트로 기능 검증이 필수적**이다.

루프의 기능적인 부분과 로깅 부분 사이의 어휘와 스타일이 달라진 것을 주목해보자.
이 코드는 위치와 렌더링 에러 정보라는 두 가지 작업을 동시에 수행하므로 단일 책임 원칙을 위반한다.


```ts
function removeCart(product: Product) {
httpClient.removeProduct(product.id);
probe.removeFood();
cartProbe.remove();
}
```

Expand Down

0 comments on commit a617c2a

Please sign in to comment.