LogTape 0.6.0 릴리스: 무엇이 바뀌었을까?

홍민희·2024년 9월 24일
2
post-thumbnail
post-custom-banner

JavaScript 및 TypeScript용 제로 의존성 구조적 로깅 라이브러리인 LogTape가 v0.6.0을 릴리스했습니다. 무엇이 바뀌었을까요?

부모 로거의 싱크를 오버라이드 가능

LogTape의 특징 중 하나는 계층적 카테고리를 통한 싱크의 상속입니다. 예를 들어, 아래와 같이 두 개의 로거를 설정했다고 하면:

import { configure, getConsoleSink, getFileSink } from "@logtape/logtape";

await configure({
  sinks: {
    console: getConsoleSink(),
    file:    getFileSink("app.log"),
  },
  loggers: [
    { category: ["app"],           level: "debug", sinks: ["file"] },
    { category: ["app", "module"], level: "debug", sinks: ["console"] },
  ],
});

["app"] 로거에 남긴 로그는 app.log 파일에만 남지만, ["app", "module"] 로거에 남긴 로그는 app.log 파일에도 남고 콘솔에도 출력되게 됩니다. ["app", "module"] 로거가 ["app"] 로거의 자식 카테고리이기 때문에 부모 로거의 싱크를 상속 받기 때문입니다.

하지만, 가끔은 이러한 동작을 원치 않을 수도 있습니다. 그래서 LogTape 0.6.0부터는 부모 로거의 싱크를 오버라이드할 수 있게 되었습니다. 예를 들어 아래와 같이 자식 로거에서 parentSinks: "override" 옵션을 켜 주게 되면:

await configure({
  sinks: { /* 생략; 위와 같음 */ },
  loggers: [
    { category: ["app"],           level: "debug", sinks: ["file"] },
    { category: ["app", "module"], level: "debug", sinks: ["console"], parentSinks: "override" },
  ],
});

["app"] 로거에 남긴 로그는 app.log 파일에만 남고, ["app", "module"] 로거에 남긴 로그는 콘솔에만 출력됩니다. 자식 로거인 ["app", "module"] 로거가 ["app"] 로거의 싱크를 오버라이드했기 때문입니다.

물론, 기본값은 parentSinks: "inherit", 즉 상속이므로, 굳이 옵션을 주지 않으면 기존처럼 동작하게 됩니다.

이 기능의 추가에 관한 배경이 궁금하신 분은 GitHub의 이슈 #15(영어)도 참고하시기 바랍니다.

메시지 템플릿에서 플레이스홀더의 처음과 끝에 공백 허용

이전 버전까지는 아래와 같이 로그를 남길 경우:

logger.info("Hello, { name }!", { name: "Alice" });

기대와 달리 Hello, undefined!라는 로그가 남겨졌습니다. 왜냐하면 플레이스홀더인 { name }에 공백 문자가 포함되어 있기 때문에, "name" 속성을 찾는 대신 " name " 속성을 찾기 때문입니다. 즉, 아래와 같이 플레이스홀더에 공백을 제거하거나:

logger.info("Hello, {name}!", { name: "Alice" });

아래와 같이 실제 속성 이름에 공백을 똑같이 넣어줘야 했습니다:

logger.info("Hello, { name }!", { " name ": "Alice" });

이는 엄밀하게는 버그가 아니었지만, 코딩 습관에 따라 실수하기 좋은 동작이었습니다.

하지만 LogTape 0.6.0부터는 플레이스홀더의 처음과 끝에 공백이 있어도 공백이 없는 속성 이름을 찾게 됩니다. 예를 들어 아래와 같이 로그를 남길 경우:

logger.info("Hello, { name }!", { name: "Alice" });

기대처럼 Hello, Alice!라는 로그가 남게 됩니다.

단, 실제로 공백 문자까지 정확하게 일치하는 속성이 있다면, 그쪽을 우선해서 찾게 됩니다. 예를 들어 아래와 같이 로그를 남길 경우:

logger.info("Hello, { name }!", { name: "Alice", " name ": "Bob" });

Hello, Alice!가 아니라 Hello, Bob!이 로깅됩니다.

이 기능의 추가에 관한 배경이 궁금하신 분은 GitHub의 이슈 #16(영어)도 참고하시기 바랍니다.

LogRecord.rawMessage 속성 추가

LogRecord는 LogTape이 출력 및 서식화되기 전의 로그를 표현하는 자료형입니다.

기존에도 LogRecord.message 속성은 존재했지만, 이 속성에는 이미 메시지 템플릿의 플레이스홀더가 실제 속성 값으로 치환된 다음의 결과가 들어 있었습니다. 대부분의 경우에는 그걸로도 충분하지만, 로그의 출력 대상(sink)이 또다른 로깅 시스템일 경우에는 원본 메시지 템플릿과 속성 값을 따로 출력하고, 해당 출력을 처리하는 로깅 시스템이 직접 메시지 템플릿의 플레이스홀더를 속성 값으로 치환하길 바랄 수도 있습니다.

LogTape 0.6.0에서 추가된 LogRecord.rawMessage는 바로 그럴 때를 위한 속성으로서, 메시지 템플릿에 플레이스홀더가 치환되지 않은 원본 상태가 그대로 담겨 있습니다. 예를 들어, 아래와 같이 로그를 남길 경우:

logger.info("Hello, {name}!", { name: "Alice" });

LogRecord.message에는 ["Hello, ", "Alice", "!"] 값이 들어가는 반면, LogRecord.rawMessage에는 "Hello, {name}!" 값이 들어가게 됩니다.

이 기능의 추가에 관한 배경이 궁금하신 분은 GitHub의 이슈 #17(영어)도 참고하시기 바랍니다.

내장 텍스트 포매터에 다양한 설정이 가능

텍스트 포매터스트림 싱크, 파일 싱크 등에서 각 로그를 어떠한 텍스트로 서식화할 것인지를 결정하는 인터페이스로, 실제 자료형의 정의는 제법 간단합니다:

export type TextFormatter = (record: LogRecord) => string;

하지만 매번 직접 텍스트 포매터를 정의해서 쓰기는 귀찮으므로, LogTape에는 defaultTextFormatteransiColorFormatter가 내장되어 있어서, 이를 사용할 수 있습니다. 다만, 여태까지는 별다른 설정이 불가능하기 때문에 정해진 서식을 그대로 받아들여야만 했습니다. 예를 들어, "warning"과 같은 로그 레벨을 WRN이라는 세 글자 약자 형태로 출력하는 게 마음에 들지 않으면, 아예 처음부터 TextFormatter를 구현해야 했습니다.

하지만 LogTape 0.6.0부터는 getDefaultTextFormatter()getAnsiColorFormatter() 함수를 통해 직접 TextFormatter를 처음부터 구현하지 않고도 다양한 서식 설정을 입맛대로 할 수 있게 되었습니다

예를 들어, "warning"과 같은 로그 레벨을 W라는 대문자 한 글자로 표현하고 싶다면, 아래와 같이 설정하면 됩니다:

const myFormatter = getDefaultTextFormatter({ level: "L" });

또는 타임스탬프의 날짜와 시간대를 생략하고 시각만 표시하고 싶다면, 아래와 같이 설정하면 됩니다:

const myFormatter = getDefaultTextFormatter({ timestamp: "time" });

더 많은 서식 옵션에 대한 설명은 관련 문서를 참고하시기 바랍니다.

이 기능의 추가에 관한 배경이 궁금하신 분은 GitHub의 이슈 #13(영어)도 참고하시기 바랍니다.

JSR 및 npm에서 받기

LogTape 0.6.0은 이미 JSRnpm에 올라가 있으니, 지금 바로 받아보시기 바랍니다!

deno add @logtape/logtape@0.6.0  # Deno
npm  add @logtape/logtape@0.6.0  # npm
pnpm add @logtape/logtape@0.6.0  # pnpm
yarn add @logtape/logtape@0.6.0  # Yarn
bun  add @logtape/logtape@0.6.0  # Bun

그럼, 즐거운 로깅 되세요!

profile
서울에서 소프트웨어 프로그래머로 일하고 있습니다. 자유·오픈 소스 소프트웨어를 만들며, 주로 Haskell, Python, TypeScript 같은 언어로 코딩합니다.
post-custom-banner

0개의 댓글