Go 로깅라이브러리 Logrus Hook에 대하여
안녕하세요.
오늘은 Go 로깅라이브러리인 Logrus의 Hook 기능에 대하여 알아보겠습니다.
Logrus란?
Go 언어용으로 널리 사용되는 로깅 라이브러리이다. 확장성과 유연성을 제공하기 위해 Hook 기능을 사용할 수 있다.
Hook이란?
훅 시스템을 통해 개발자는 로깅 프로세스에 추가적인 동작을 주입할 수 있다.
예를들어, 로그 메시지를 파일에 기록하는 동시에 오류 메시지를 Slack으로 전송하거나 로그 데이터를 Elasticsearch 같은 검색 엔진에 인덱싱할 수 있다.
Hook 인터페이스
// logrus에 정의된 Hook 인터페이스
package logrus
// A hook to be fired when logging on the logging levels returned from
// `Levels()` on your implementation of the interface. Note that this is not
// fired in a goroutine or a channel with workers, you should handle such
// functionality yourself if your call is non-blocking and you don't wish for
// the logging calls for levels returned from `Levels()` to block.
type Hook interface {
Levels() []Level
Fire(*Entry) error
}
// logrus에 정의된 LevelHooks 구조체
package logrus
// Internal type for storing the hooks on a logger instance.
type LevelHooks map[Level][]Hook
// Add a hook to an instance of logger. This is called with
// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface.
func (hooks LevelHooks) Add(hook Hook) {
for _, level := range hook.Levels() {
hooks[level] = append(hooks[level], hook)
}
}
// Fire all the hooks for the passed level. Used by `entry.log` to fire
// appropriate hooks for a log entry.
func (hooks LevelHooks) Fire(level Level, entry *Entry) error {
for _, hook := range hooks[level] {
if err := hook.Fire(entry); err != nil {
return err
}
}
return nil
}
Hook 인터페이스는 두 가지 메서드를 정의한다.
- Levels() []Level
- File(*Entry) error
Levels() []Level
이 훅이 활성화되어야 하는 로그 레벨을 반환한다. 예를들어, levels 메서드가 [ErrorLevel, FatalLevel, PanicLevel]을 반환하면, 이 훅은 에러, 치명적 오류, 패닉 레벨의 로그에 대해서만 실행된다.
Fire(*Entry) error
로그 엔트리가 생성될때 호출되는 메서드이다. Entry는 로그 메시지와 관련 데이터를 포함한다. 여기서 개발자는 로그 데이터를 처리하고 필요한 경우 외부 시스템으로 전송하는 등의 작업을 수행할 수 있다.
LevelHooks 구조체
LevelHooks는 로그 레벨별로 훅 리스트를 관리하는 맵이다. 각 로그 레벨에 대해 하나 이상의 훅을 연결할 수 있다.
Add 메서드
Add 메서드는 LevelHooks 맵에 새로운 훅을 추가하는 메서드이다. 이 메서드는 훅이 활성화될 로그 레벨을 Levels() 메서드를 통해 조회하고 해당 레벨의 훅 리스트에 추가한다.
Fire 메서드
Fire 메서드는 특정 로그 레벨에 대해 모든 관련 훅을 실행한다. 로그 엔트리가 생성될때, 해당 엔트리의 레벨에 대해 등록된 모든 훅의 Fire 메서드를 호출한다.
Hook 연동 방법
- Hook 인터페이스를 구현하는 사용자 정의 훅을 개발한다. 이때, Levels와 Fire 메서드를 정의해야한다.
- 로거 인스턴스에 이 훅을 추가한다. 이는 log.AddHook(new(MyHook)) 과 같이 추가한다. MyHook은 사용자가 구현한 훅이다.
- 로깅이 발생할때 Logrus는 등록된 모든 훅을 검사하고 현재 로그 레벨에 해당하는 훅의 Fire 메서드를 호출한다.
예제코드
package main
import (
"fmt"
log "github.com/sirupsen/logrus"
"os"
)
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%s: %d", p.Name, p.Age)
}
type CustomHook struct {
}
func (c CustomHook) Levels() []log.Level {
return log.AllLevels
}
func (c CustomHook) Fire(*log.Entry) error {
fmt.Println("[hook] custom hook fired.")
// DO SOMETHING...
return nil
}
func init() {
// SET LOG CONFIGURATION
log.SetFormatter(&log.JSONFormatter{})
log.SetOutput(os.Stdout)
log.SetLevel(log.TraceLevel)
log.AddHook(CustomHook{})
}
func main() {
people := []Person{
{"Kaye", 35},
{"Jade", 44},
}
log.Debugf("%+v", people)
}