Log Rotation and File Splitting in Go: logrus, zap 및 slog의 통찰력
James Reed
Infrastructure Engineer · Leapcell

서문
Go의 내장 log/slog
로깅 라이브러리를 포함한 기존 로깅 라이브러리에서 일반적으로 로그 파일 로테이션 및 분할을 지원합니다. 그러나 이러한 기능은 직접 내장되어 있지 않으며 활성화하려면 저희가 적극적으로 구성해야 합니다.
이 문서에서는 logrus, zap 및 공식 slog와 같은 여러 인기 있는 로깅 라이브러리를 살펴봅니다. 이러한 라이브러리의 주요 설계 요소를 분석하고 로그 로테이션 및 분할 구성을 어떻게 지원하는지 논의합니다.
logrus, zap 및 slog 설계에 대한 간략한 분석
logrus, zap 및 slog의 설계를 비교할 때 눈에 띄는 공통점은 모두 io.Writer
의 중요한 속성을 포함한다는 것입니다. 이 속성은 로그 출력의 대상 위치를 결정하므로 로깅 프레임워크 설계에서 중심적인 역할을 합니다.
logrus 로깅 라이브러리
logrus는 구조화된 로깅, 로그 수준 제어 및 기타 기능을 제공하는 Go용 기능이 풍부한 로깅 라이브러리입니다.
logrus를 사용할 때 logrus.New()
를 호출하여 Logger 인스턴스를 만들 수 있습니다. 이 인스턴스를 사용하면 로그 출력 위치 사용자 지정 및 로그 인쇄와 같은 많은 작업을 수행할 수 있습니다. 다음 코드를 살펴보겠습니다.
logger := logrus.New() logger.Out = os.Stdout // 표준 출력 // 또는 파일로 리디렉션 // out, err := os.OpenFile("file.log", os.O_CREATE|os.O_WRONLY, 0666) // if err != nil { // panic(err) // } // logger.Out = out
Logger 구조체의 정의는 다음과 같습니다.
type Logger struct { Out io.Writer Hooks LevelHooks Formatter Formatter // 기타 필드... }
핵심 속성은 유형이 io.Writer
인 Out
입니다. 이 속성은 표준 출력, 파일 또는 기타 사용자 지정 출력 매체를 포함하여 로그 출력 대상을 지정하는 데 사용됩니다.
zap 로깅 라이브러리
zap은 성능이 뛰어난 로깅 라이브러리입니다. 구조화된 로깅, 다단계 로그 제어 및 유연한 구성 옵션을 제공합니다.
logrus와 유사하게 zap을 사용하면 구성을 통해 로그 출력 위치를 결정할 수도 있지만 구현은 약간 다릅니다. zap에서 로그 출력은 zapcore.Core
를 통해 구성됩니다. zapcore.Core
인스턴스를 만들 때 zapcore.WriteSyncer
인터페이스의 구현을 매개변수로 지정해야 하며, 이는 로그 출력 대상을 직접 결정합니다. zapcore.WriteSyncer
인스턴스를 만들려면 일반적으로 io.Writer
유형 매개변수를 사용하는 zapcore.AddSync()
함수를 사용합니다.
다음은 zap으로 로그 인스턴스를 만드는 기본 예제입니다.
writer := zapcore.AddSync(os.Stdout) // 표준 출력을 로그 대상으로 사용 core := zapcore.NewCore( zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), writer, zap.InfoLevel, ) logger := zap.New(core) defer logger.Sync() // 버퍼링된 로그 항목 플러시 // 로거를 사용하여 로그 기록
핵심은 io.Writer
유형 매개변수를 사용하여 표준 출력, 파일 또는 기타 사용자 지정 출력 매체를 포함하여 로그 출력 대상을 지정하는 데 사용되는 zapcore.AddSync()
함수입니다.
slog 로깅 라이브러리
slog는 Go 1.21.0에 도입된 공식 로깅 라이브러리로, 구조화된 로깅을 제공합니다. slog 로깅 라이브러리에 대해 자세히 알아보려면 이전 기사를 확인하십시오.
logrus 및 zap과 유사하게 slog는 io.Writer
매개변수를 제공하여 사용자가 로그 출력 대상을 지정할 수도 있습니다. 이 설정은 slog.Handler
인터페이스의 구현을 만들 때 이루어집니다.
textLogger := slog.New(slog.NewTextHandler(os.Stdout, nil)) jsonLogger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
이러한 두 함수에서 slog.NewTextHandler
및 slog.NewJSONHandler
의 첫 번째 매개변수는 io.Writer
유형입니다.
분석 요약
세 가지 주요 로깅 라이브러리인 logrus, zap 및 slog에 대한 분석에서 핵심 공통점을 확인할 수 있습니다. 로그 출력을 처리할 때 모두 io.Writer
인터페이스에 의존합니다. 이러한 로깅 라이브러리는 로그 출력 대상을 설정할 수 있도록 io.Writer
인터페이스를 중요한 매개변수의 유형으로 사용합니다.
로그 로테이션 및 분할의 구현 메커니즘 및 사례
구현 메커니즘
logrus, zap 및 slog의 설계를 분석한 후 공통점을 발견했습니다. 이제 로그 로테이션 및 분할의 메커니즘에 대해 더 자세히 살펴보겠습니다.
로그 파일 로테이션 및 분할을 구현하려면 일반적으로 lumberjack과 같은 타사 라이브러리를 활용합니다. 물론 다른 유사한 라이브러리도 있지만 여기서는 모두 나열하지 않습니다.
lumberjack은 로그 로테이션 및 분할을 위해 특별히 설계된 라이브러리입니다. 이 기능은 플러그형 구성 요소와 유사합니다. 이 구성 요소Configure를 구성하고 선택한 로깅 라이브러리와 통합하면 로그 파일 로테이션 및 분할을 달성할 수 있습니다.
다음은 lumberjack 구성 요소를 초기화하는 코드입니다.
log := &lumberjack.Logger{ Filename: "/path/file.log", // 로그 파일 위치 MaxSize: 10, // 최대 파일 크기(MB 단위) MaxBackups: 3, // 보관할 이전 파일의 최대 수 MaxAge: 28, // 이전 파일을 보관할 최대 일수 Compress: true, // 이전 파일을 압축/보관할지 여부 LocalTime: true, // 타임스탬프에 현지 시간 사용 }
이 예제에서는 lumberjack.Logger
인스턴스를 만들고 다음 매개변수를 설정합니다.
- Filename: 로그 파일의 저장 경로를 지정합니다.
- MaxSize: 파일이 이 MB에 도달하면 로테이션됩니다.
- MaxBackups: 유지할 이전 로그 파일의 최대 수입니다.
- MaxAge: 이전 파일의 최대 보존 기간(일)입니다.
- Compress: 이전 파일을 압축할지 여부(예: .gz로 변환).
lumberjack의 Logger
구조체는 io.Writer
인터페이스를 구현한다는 점에 유의하는 것이 중요합니다. 즉, 로그 파일 로테이션 및 분할의 모든 핵심 논리는 Write
메서드 내에 캡슐화됩니다. 이 구현을 통해 Logger 구조체를 io.Writer
매개변수를 지원하는 로깅 라이브러리에 쉽게 통합할 수 있습니다.
이것을 이해하면 로그 로테이션 및 분할을 구현하는 방법을 이미 알고 있을 것입니다. lumberjack의 로거 구조체는 io.Writer
인터페이스를 구현하므로 타사 라이브러리에 전달하면 통합 및 구성을 완료할 수 있습니다.
사례
logrus 로깅 라이브러리를 사용한 구현
log := &lumberjack.Logger{ Filename: "/path/file.log", // 로그 파일 위치 MaxSize: 10, // 최대 파일 크기(MB 단위) MaxBackups: 3, // 보관할 이전 파일의 최대 수 MaxAge: 28, // 이전 파일을 보관할 최대 일수 Compress: true, // 이전 파일을 압축/보관할지 여부 LocalTime: true, // 타임스탬프에 현지 시간 사용 } logger := logrus.New() logger.Out = log
zap 로깅 라이브러리를 사용한 구현
log := &lumberjack.Logger{ Filename: "/path/file.log", // 로그 파일 위치 MaxSize: 10, // 최대 파일 크기(MB 단위) MaxBackups: 3, // 보관할 이전 파일의 최대 수 MaxAge: 28, // 이전 파일을 보관할 최대 일수 Compress: true, // 이전 파일을 압축/보관할지 여부 LocalTime: true, // 타임스탬프에 현지 시간 사용 } writer := zapcore.AddSync(log) core := zapcore.NewCore( zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), writer, zap.InfoLevel, ) logger := zap.New(core) defer logger.Sync() // 버퍼링된 로그 항목 플러시
slog 로깅 라이브러리를 사용한 구현
log := &lumberjack.Logger{ Filename: "/path/file.log", // 로그 파일 위치 MaxSize: 10, // 최대 파일 크기(MB 단위) MaxBackups: 3, // 보관할 이전 파일의 최대 수 MaxAge: 28, // 이전 파일을 보관할 최대 일수 Compress: true, // 이전 파일을 압축/보관할지 여부 LocalTime: true, // 타임스탬프에 현지 시간 사용 } textLogger := slog.New(slog.NewTextHandler(log, nil)) jsonLogger := slog.New(slog.NewJSONHandler(log, nil))
결론
이 문서에서는 세 가지 인기 있는 로깅 라이브러리인 logrus, zap 및 slog의 설계 요소에 대한 간략한 분석을 제공했습니다. 로깅 인스턴스를 만드는 방법의 세부 사항은 다르지만 로그 출력을 처리하기 위해 모두 io.Writer
인터페이스 매개변수에 의존한다는 것을 알았습니다. io.Writer
매개변수를 구성하는 방법을 마스터하고 lumberjack 라이브러리와 결합하면 로그 파일 로테이션 및 분할을 달성할 수 있습니다.
향후 새로운 로깅 라이브러리가 도입되더라도 유사한 방법을 사용하여 로그 파일 로테이션 및 분할을 신속하게 통합할 수 있습니다.
Go 프로젝트 호스팅을 위한 최고의 선택, Leapcell입니다.
Leapcell은 웹 호스팅, 비동기 작업 및 Redis를 위한 차세대 서버리스 플랫폼입니다.
다국어 지원
- Node.js, Python, Go 또는 Rust로 개발하십시오.
무료로 무제한 프로젝트 배포
- 사용량에 대해서만 지불하십시오 — 요청 없음, 요금 없음.
탁월한 비용 효율성
- 미사용 요금 없이 종량제로 지불하십시오.
- 예: $25는 평균 응답 시간 60ms에서 694만 건의 요청을 지원합니다.
간소화된 개발자 경험
- 간편한 설정을 위한 직관적인 UI.
- 완전 자동화된 CI/CD 파이프라인 및 GitOps 통합.
- 실행 가능한 통찰력을 위한 실시간 메트릭 및 로깅.
손쉬운 확장성 및 고성능
- 높은 동시성을 쉽게 처리하기 위한 자동 크기 조정.
- 운영 오버헤드가 없으므로 구축에만 집중하십시오.
설명서에서 자세히 알아보십시오!
X에서 저희를 팔로우하십시오: @LeapcellHQ