안녕하세요.
이번 포스팅에서는 log 찍는 방법에 대해 작성해보려고 합니다.
대부분의 회사에 웹 서비스는 로깅합니다.
그렇다면 로깅은 이 웹 서비스를 운영하는 데 있을까요?
버그 발견과 디버깅 과정을 쉽게 만드는 무엇이든 기록하면 됩니다. 로그 메시지에는 타임스탬프, 오류 메시지 등과 같은 디버깅에 유용한 정보가 포함될 수 있습니다.
보안과 관련된 정보는 특히 실제 서비스 환경에서 권장되지 않습니다.
예시로, 신용카드 정보, 사용자의 개인정보 등이 있습니다.
로그가 유출되면 해커가 이를 악용할 수 있기 때문에 조심해야 합니다.
다음과 같이 Go의 기본 제공 패키지를 활용해 로그를 찍을 수 있습니다.
package main
import "log"
func main() {
log.Println("This is logging")
}
이 코드를 실행하면 로그 메시지와 함께 시간 정보를 보실 수 있습니다.
만약 로그를 파일에 남기고 싶으시다면 다음과 같은 코드를 사용하시면 됩니다.
package main
import (
"log"
"os"
)
func main() {
logFile := openLogFile()
defer logFile.Close()
log.SetOutput(logFile)
log.Println("This is logging!")
}
func openLogFile() *os.File {
f, err := os.OpenFile("access.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
return f
}
이 코드를 실행하면 access.log에 로그 기록이 남겨져 있는 것을 확인하실 수 있습니다.
기본 라이브러리에 경우 너무 단순합니다. 개발 환경에서는 빨리 확인할 수 있어 좋지만 실제 서비스 환경에서는 정확하고 체계적인 내용을 봐야하기 때문에 기본 라이브러리는 적합하지 않습니다.
zap은 Uber에 의해 개발된 오픈소스이며 성능이 정말 좋습니다.
zap은 Debug, Info, Warning, Error, DPanic, Panic, and Fatal 총 7가지 디버깅 레벨을 제공해줍니다.
각각의 레벨의 설명은 다음과 같습니다.
const (
// DebugLevel logs are typically voluminous, and are usually disabled in
// production.
DebugLevel = zapcore.DebugLevel
// InfoLevel is the default logging priority.
InfoLevel = zapcore.InfoLevel
// WarnLevel logs are more important than Info, but don't need individual
// human review.
WarnLevel = zapcore.WarnLevel
// ErrorLevel logs are high-priority. If an application is running smoothly,
// it shouldn't generate any error-level logs.
ErrorLevel = zapcore.ErrorLevel
// DPanicLevel logs are particularly important errors. In development the
// logger panics after writing the message.
DPanicLevel = zapcore.DPanicLevel
// PanicLevel logs a message, then panics.
PanicLevel = zapcore.PanicLevel
// FatalLevel logs a message, then calls os.Exit(1).
FatalLevel = zapcore.FatalLevel
)
go get go.uber.org/zap
package main
import (
"go.uber.org/zap"
)
func main() {
logger, _ := zap.NewDevelopment()
defer logger.Sync()
logger.Info("Hello Zap!")
logger.Warn("Beware of getting Zapped! (Pun)")
logger.Error("I'm out of Zap joke!")
}
위 코드에서 zap.NewDevelopment()는 메시지들을 출력하는 로거의 기본세팅값을 반환해줍니다. 이 코드를 실행하면 다음과 같은 결과를 보실 수 있습니다.
INFO 레벨에 경우 메시지만 출력을 해줍니다. WARN과 ERROR에 경우 stack trace와 메시지를 둘 다 출력해줍니다. 이것을 통해 에러가 어디서 발생했는지 찾는데 유용합니다.
package main
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func main() {
var log *zap.Logger
var err error
config := zap.NewProductionConfig()
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.TimeKey = "timestamp"
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.StacktraceKey = ""
config.EncoderConfig = encoderConfig
log, err = config.Build(zap.AddCallerSkip(1))
if err != nil {
panic(err)
}
log.Info("Hello Zap!")
log.Warn("Beware of getting Zapped! (Pun)")
log.Error("I'm out of Zap joke!")
}
zap에 경우 Config를 활용해서 나만의 로그를 만들 수 있습니다. 위 코드는 프로덕션환경에서 쓸 수 있는 설정을 제공해주며 추가적으로 변경을 원할 경우, Config를 변경해서 사용하시면 됩니다.
결과는 밑에 그림처럼 나왔습니다.
제가 준비한 내용은 여기까지가 끝이며 다음에도 좋은 내용을 가지고 오겠습니다~~