[go] Go에서 zap logging package 사용하기

sujin·2022년 9월 27일
0

Golang

목록 보기
2/3

zap을 활용한 logging

zap은 Time, Time % to zap을 보았을 때 가장 빠르게 작동한다. 다만,Objects Allcated를 보았을 때는 object당 할당되는 것이 구조화되게끔 작성해야한다는 것을 알 수 있다.
https://github.com/uber-go/zap

  • SugaredLogger
    구조화된 로깅 패키지보다 4-10배 정도 빠르기를 가지며 구조화된 logging, printf style logging지원, key-value 쌍을 허용한다.

    sugar := zap.NewExample().Sugar()
    	defer sugar.Sync()
    	sugar.Infow("failed to fetch URL",
    		"url", "http://example.com",
    		"attempt", 3,
    		"backoff", time.Second,
    	)
    	sugar.Infof("failed to fetch URL: %s", "http://example.com") // printf형식도 지원
    

    https://github.com/uber-go/zap/blob/master/sugar.go 에서 supar logger 확인이 가능하다.

    // Infow logs a message with some additional context. The variadic key-value
    // pairs are treated as they are in With.
    func (s *SugaredLogger) Infow(msg string, keysAndValues ...interface{}) {
    	s.log(InfoLevel, msg, nil, keysAndValues)
    }
    

    sugar.Infow를 확인해보면 위와 같다. infow는 method and receiver 구성이 되어있고 sugar를 pointer를 통해 참조하여 그 값을 사용할 수 있다.
    msg를 첫번재 arg로 이후에는 keyAndValues...interface()를 두번째 ars로 가진다. 따라서 sugar.Infow에 key-value 구성이 3가지 존재하는 것을 확인할 수 있다. 또한 코드에서 Infof를 통해 printf형식도 지원하는 것을 알 수 있다.
    결과는 아래와 같다.
    {"level":"info","msg":"failed to fetch URL","url":"http://example.com" ,"attempt":3,"backoff":"1s"}
    {"level":"info","msg":"failed to fetch URL: http://example.com"}

  • Logger
    할당량이 적지만 훨씬 빠르고 강력한 형식의 구조화된 로딩만 지원한다.

    logger := zap.NewExample()
    	defer logger.Sync()
    	logger.Info("failed to fetch URL",
    		zap.String("url", "http://example.com"),
    		zap.Int("attempt", 3),
    		zap.Duration("backoff", time.Second),
    	)

    sugar는 key-value였고 infow였던 것에 비해서 keyAndValues와 다르게 더욱 구조화되어있다는 것을 확인할 수 있다.
    결과는 아래와 같다 :
    {"level":"info","msg":"failed to fetch URL","url":"http://example.com" ,"attempt":3,"backoff":"1s"}

추가) pflag package로 flag 설정

flag란 깃발. 즉, 무엇에 대해서 서로의 약속을 정하거나 기억해야할 때 사용한다.
https://pkg.go.dev/github.com/spf13/pflag#section-readme

  • pointer를 활용해 flag를 설정

    package안에 활용할 수 있는 func이 많지만 그 하나를 살펴보자.

    StringVarP 는 receiver와 함께 사용되고 있다.

     // StringVarP is like StringVar, but accepts a shorthand letter that can be used after a single dash.
    func StringVarP(p *string, name, shorthand string, value string, usage string) {
    	CommandLine.VarP(newStringValue(value, p), name, shorthand, usage)
    }

    FlagSet struct를 pointer를 통해서 접근하여 그 값을 건드린다. args에는 가장 처음으로 문자열 그 다음으로는 설정할 이름을 적는다. 이후 shorthand string값으로 약식 문자를 적는다. flag의 value가 될 value를 마지막으로 string usage를 넘겨준다.

추가) Viper

viper는 구성 형식에 대해서 걱정하지 않기 위해 사용한다. config file을 빌드하고 비정렬화를 진행한다.

  • pointer와 receiver를 활용한 viper활용

     func SetConfigFile(in string) { v.SetConfigFile(in) }
    
     func (v *Viper) SetConfigFile(in string) {
         if in != "" {
             v.configFile = in
         }
     }
    

    이때, SetconfigFile을 v object에 접근하여 configFile값을 argument인 string type in 변수로 configFile이 넣어진다.

struct와 receiver를 활용한 관리

type Option struct{}를 만들어 구성요소에 logger, flag, viper, loglevel 등을 넣을 수 있다.
그렇다면 Option struct를 활용하여 객체로 만들고 sugar logger와 pflag, 그리고 viper를 활용할 수 있다.
생성한 객체에 대한 setting이 다 되었다면 sugar를 통해서 logging을 진행한다.


logging을 진행할때, sugar를 사용하면 되지만 컨테이너 환경에서 관리할 때 환경 설정을 바꾸거나 더 편리한 세팅을 위하여 pflag, viper를 함께 struct로 관리하여 객체지향적으로 관리하기에 참고하면 좋겠다!

0개의 댓글