ããã«ã¡ã¯ããã¯ã©ã¯ç³è«ã»çµè²»ç²¾ç®ã¨ã³ã¸ãã¢ã®@upamuneã§ããå é±æ«ã¯30kmã®ãã¬ã¤ã«ã¬ã¼ã¹ãããã¾ããããä»é±æ«ã¯ãã«ãã©ã½ã³ãããã®ã§æºèº«åµçã§ãã
ãã®è¨äºã¯LayerXããã¯ã¢ãã«ã¬2023ã®22æ¥ç®ã®è¨äºã§ãã ç§ã¯ãªãã3æ¥åãããã¯ã¢ãã«ã¬ã«å ¥ãã¦ãã¾ã£ãã®ã§ããã2åç®ã®ä»åã¯APIãµã¼ãã¼ã®ã¨ã©ã¼ãã°ã40%åæ¸ãã話ããã¾ãã
æ¨æ¥ã¯@tataneã«ããバクラクの Vue3 移行戦略と詰まったポイント #LayerXテックアドカレ - LayerX エンジニアブログã§ãããææ¥ã¯@trsã«ããå ¥ç¤¾ã¨ã³ããªã¼ã§ãï¼æ¥½ãã¿ã§ããã
ã¯ããã«
å¼ç¤¾ã§ã¯åºæ¬çã«Goè¨èªãå©ç¨ãã¦APIãµã¼ãã¼ãå®è£ ãã¦ãã¾ããã¨ã©ã¼ãçºçãããã調æ»ããããããã«ã¨ã©ã¼ãã°ãåºåãã¦èª¿æ»ãããããã¦ãã¾ããã1ã¤ã®ã¨ã©ã¼ã«å¯¾ãã¦è¤æ°åã®åé·ãªã¨ã©ã¼ãã°ãåºåãããã¨ããåé¡ãããã¾ããã
è¤æ°ã®ã¨ã©ã¼ãã°ã«ããæ
å ±ãå¢ããã®ã§ããã°åé¡ãªãã®ã§ããããã®å ´åçºçããã¨ã©ã¼ã®ä¸èº«ã ãåºåããã¦ããã caller
ãã£ã¼ã«ã1ã ããéããã®ã§ããã
åé·ãªã¨ã©ã¼ãã°ã®åå
ã¨ã©ã¼ãçºçããéã«ã¨ã©ã¼ã®è©³ç´°ãåºåããããã«ããã°ãåºåãã¦ããã®ã§ãããã¹ã¿ãã¯ãã¬ã¼ã¹ãæ¬ä¼¼çã«åºåããããã«ãã¨ã©ã¼ããã³ããªã³ã°ããé¨åã§æ¯åã¨ã©ã¼ãã°åºåãã¦ãã¾ã£ã¦ãã¾ããããããåé·ãªã¨ã©ã¼ãã°ã®åå ã§ãã
if err := doSomething(); err != nil { log.Error(err).Send() // ãããåé·ãªã¨ã©ã¼ãã°ã®åå return err }
以ä¸ã®ã³ã¼ãã¯ä¸ã®ä¾ã示ããGoè¨èªã®æ¬ä¼¼çãªã³ã¼ãã§ããã¨ã©ã¼ãã³ããªã³ã°ã®é¨åã§æ¯åã¨ã©ã¼ãã°ãåºåãã¦ãã¾ããåºåããããã°ã®caller
ãã£ã¼ã«ããåç
§ãããã¨ã§ãã©ã®ãã¡ã¤ã«ã®ä½è¡ç®ã§ã¨ã©ã¼ãçºçããããç¹å®ã§ããããã«ãªã£ã¦ãã¾ãã
å
·ä½çã«ã¯ã Parent
é¢æ°ãå¼ã³åºããæã«ã Grandchild
é¢æ°ã® fuga
å¼ã³åºãã§ã¨ã©ã¼ãèµ·ããå ´åã¯ã fuga
ã®é¨åã®ã¨ã©ã¼ãã³ããªã³ã°ã¨ã Child
é¢æ°ã® Grandchild
å¼ã³åºãã®é¨åã®ã¨ã©ã¼ãã³ããªã³ã°ã¨ã Parent
é¢æ°ã® Child
å¼ã³åºãã®é¨åã®ã¨ã©ã¼ãã³ããªã³ã°ã®åè¨3ç®æã§ã¨ã©ã¼ãã°ãåºåããããã°å
ã® caller
ã®ã¿ãç°ãªããããã©ã®è¡ã§ã¨ã©ã¼ãçºçããããç¹å®ã§ãã¾ãã
func Parent() error { if err := Child(); err != nil { // Output: {"caller":"main.go:4","level":"error","error":"an error occurred"} log.Error().Err(err).Send() return err } return nil } func Child() error { if err := Grandchild(); err != nil { // Output: {"caller":"main.go:13","level":"error","error":"an error occurred"} log.Error().Err(err).Send() return err } return nil } func Grandchild() error { if err := hoge(); err != nil { log.Error().Err(err).Send() return err } if err := fuga(); err != nil { // Output: {"caller":"main.go:26","level":"error","error":"an error occurred"} log.Error().Err(err).Send() return err } if err := piyo(); err != nil { log.Error().Err(err).Send() return err } return nil }
ãã®ãããã¨ã©ã¼ã¯1åããçºçãã¦ããªãã¦ããã¨ã©ã¼ãã³ããªã³ã°ãã¦ããé¨åãã¨ã«ã¨ã©ã¼ãã°ãåºåããã¦ãã¾ãã大ããã«è¨ãã¨1åã¨ã©ã¼ãçºçããã¨10åã®ã¨ã©ã¼ãã°ãåºã¦ãããããcaller
ã®ãã£ã¼ã«ãã ããéãã¨ããç¶æ
ã«ãªã£ã¦ãã¾ããã
åé·ãªã¨ã©ã¼ãã°ã®å½±é¿
åé·ãªã¨ã©ã¼ãã°ã«ããåé¡ã¯ä¸»ã«ä»¥ä¸ã®ç¹ãããã¾ãã
- åé·ãªã¨ã©ã¼ãã°ã«ãããã¨ã©ã¼ãã°ã®ä»¶æ°ãå¢å ããã°å ¨ä½ã®æ¤ç´¢ã³ã¹ãã¨ééçã³ã¹ããå¢å ãã
- ã¨ã©ã¼ãã°ã®ä»¶æ°ãå ã«ã¢ã©ã¼ããè¨å®ãã¦ããå ´åãã¢ã©ã¼ãã®ãããå¤ã決ããã®ãé£ãã
- è¤æ°ã®ã¨ã©ã¼ãã°ãè¦ãªãã¨ã¹ã¿ãã¯ãã¬ã¼ã¹ãè¦ããã¨ãã§ããªãã®ã§ã¨ã©ã¼ã®åå ã追ãã¥ãã
ãããã®åé¡ã解決ããããã«ãåé·ãªã¨ã©ã¼ãã°ãæ¹åãããã¨ã«ãã¾ããã
åé·ãªã¨ã©ã¼ãã°ã®åæ¸æ¹æ³
å ¨ä½çãªæ¹éã¨ãã¦ã¯ãã¹ã¿ãã¯ãã¬ã¼ã¹ã確èªããç®çã§åºåãã¦ããã¨ã©ã¼ãã°ãåé¤ãã¦ããã®ä»£ããã«ã¨ã©ã¼ãWrapãã¦ããã¾ããã¨ã©ã¼ãWrapããæã«ã³ã¼ã«ã¹ã¿ãã¯ãè¨é²ãã¦ãããã¨ã©ã¼ãã³ããªã³ã°ã®ã©ã¤ãã©ãª2ãå©ç¨ããã°ãå¾ããã¹ã¿ãã¯ãã¬ã¼ã¹ãåºåã§ããããã§ãããã®Wrapãããã¨ã©ã¼ãä¸ç®æã§ã¨ã©ã¼ãã°ã¨ãã¦åºåããããã«ãã¾ãã
ã¾ãä¸ã§ç¤ºããæ¹éãå ã«ããæé ã以ä¸ã§ãã
- Wrapãããã¨ã©ã¼ã®ã¹ã¿ãã¯ãã¬ã¼ã¹ãåºåã§ããããã«è¨å®
- Wrapãããã¨ã©ã¼ã«å¯¾å¿ã§ãã¦ãªãé¨åãè¦ã¤ãã¦ä¿®æ£
- ã¨ã©ã¼ãWrapããããã«ä¿®æ£
- åé·ãªã¨ã©ã¼ãã°ãåé¤
1. Wrapãããã¨ã©ã¼ã®ã¹ã¿ãã¯ãã¬ã¼ã¹ãåºåã§ããããã«è¨å®
å¼ç¤¾ã§å©ç¨ãã¦ãããã®ã³ã°ã©ã¤ãã©ãªã¯rs/zerologã使ã£ã¦ããã®ã§ããã®ã©ã¤ãã©ãªã§ã¨ã©ã¼ã®ã¹ã¿ãã¯ãã¬ã¼ã¹ãåºåã§ããããã«è¨å®ããã¨ããããå§ãã¾ããããã®ä¿®æ£ãè¡ãã¨ãã¨ã©ã¼ããã¹ã¿ãã¯ãã¬ã¼ã¹ãåºåãããã¨ãã§ãã¾ãã
Event.Stack ãå©ç¨ããã¨ã渡ããã error
ãè¨å®ãã ErrorStackMarshaler ãå
ã« stack
ãã£ã¼ã«ãã«è¿½å ãã¦ãããããã§ãã
zerolog.ErrorStackMarshaler
ã«è¨å®ããé¢æ°ã¯ãã¨ã©ã¼ãWrapãã¦ããã©ã¤ãã©ãªã«åããã¦å®è£
ãã¾ããzerologãå®è£
ãã¦ããpkg/errorsåãã®å®è£
ãåèã«ãªãã¾ãã
2. Wrapãããã¨ã©ã¼ã«å¯¾å¿ã§ãã¦ãªãé¨åãè¦ã¤ãã¦ä¿®æ£
ã¨ã©ã¼ãWrapãã¦ããåã«ãã¾ãã¨ã©ã¼ãWrapãã¦ãåé¡ãªãããã«ä¿®æ£ãã¦ããã¾ãããå
·ä½çã«ã¯ã¨ã©ã¼ãç´æ¥ ==
ã§æ¯è¼ãã¦ããããType Assertionã«ãã£ã¦ã¨ã©ã¼ãå¤æãã¦ããé¨åãä¿®æ£ãã¾ããã
該å½é¨åãé å¼µã£ã¦è¦ã¤ããã®ã¯éçãããã®ã§ãpolyfloyd/go-errorlintãå©ç¨ãã¦ã該å½é¨åããã¶ãåºãã¾ãããããã»ã©æ°ã¯ç¡ãã£ãã®ã§ä»¥ä¸ã®ããã«æåã§ç½®æãã¦ããã¾ããã
- ã¨ã©ã¼ãç´æ¥
==
ã§æ¯è¼ãã¦ããé¨å âerrors.Is
ãå©ç¨ãã¦æ¯è¼ããããã«ä¿®æ£ - ã¨ã©ã¼ãType Assertionã«ãã£ã¦å¤æãã¦ããé¨å â
errors.As
ãå©ç¨ãã¦å¤æããããã«ä¿®æ£
ãã®ä¿®æ£ãè¡ã£ã¦ãã¨ã©ã¼ãWrapãã¦ãåé¡ãªãã³ã¼ããã¼ã¹ã«ãªãã¾ããã
3. ã¨ã©ã¼ãWrapããããã«ä¿®æ£
ã¨ã©ã¼ãWrapãã¦ãåé¡ãªãããã«ãªã£ãã®ã§ããã¨ã¯ return err
ãã¦ããé¨åã return errors.Wrap(err)
ã«ä¿®æ£ãã¾ããã 3
ããã綺éºã«ããè¯ãæ¹æ³ãæãã¤ããªãã£ãã®ã§ãã¨ã©ã¼ãã³ããªã³ã°ã®ãã¿ã¼ã³ãæ¤ç´¢ãã¦ä¸æ¬ç½®æãã¦ããã¾ãããããã«ãã£ã¦ãã»ã¨ãã©ã®ã±ã¼ã¹ã§ã¨ã©ã¼ãWrapãããã¨ãã§ãã¾ããã
4. åé·ãªã¨ã©ã¼ãã°ãåé¤
æå¾ã«ã¨ã©ã¼ãWrapãã¦ãWrapããéã«è¨é²ãããã³ã¼ã«ã¹ã¿ãã¯ãå
ã«ãã°ã« stack
ãã£ã¼ã«ãã追å ãããããã«ãªã£ãã®ã§ãåé·ãªã¨ã©ã¼ãã°ãå¿
è¦ãªããªã£ãã®ã§åé¤ãã¦ããã¾ããããã㯠log.Error(err).Send()
ãæ¤ç´¢ãã¦ä¸æ¬ã§åé¤ããã ãã§ããã
ã¾ããåé·ãªã¨ã©ã¼ãã°ãä»å¾å¢ãããã¨ãç¡ãããã«PRä½ææã«CIï¼GitHub Actionsï¼ã§å®è¡ããã semgrep ãå©ç¨ãã¦ãåé·ãªã¨ã©ã¼ãã°ãç¦æ¢ããã«ã¼ã«ãä½æãã¦CIã§çºè¦ããããã«ãã¦ãã¾ãã以ä¸ã®ãããªã«ã¼ã«ãè¨å®ãã¦ãã¾ãã
rules: - id: meaningless-error-log patterns: - pattern-either: - pattern: $X.Error($ERR).Send() message: "åé·ãªã¨ã©ã¼ãã°ãåºåããªãã§ãã ãã" languages: [ go ] severity: ERROR
ã¨ã©ã¼ã®Wrapå¿ãã«ãæ°ã¥ããã¨ãã§ããããã«tomarrell/wrapcheckã®linterãæå¹ã«ãã¦ãã¾ãã
æ¹åããçµæ
ä¸ã®ææ³ã§æ®µéçã«ã¨ã©ã¼ãã³ããªã³ã°ãæ¹åãã¦ãåé·ãªã¨ã©ã¼ãã°ãåé¤ããçµæãã¨ã©ã¼ãã°ã40%åæ¸ãããã¨ãã§ãã¾ããã
ããã«ãã£ã¦ã1ã¤ã®ã¨ã©ã¼ã«ãã大éã®ã¨ã©ã¼ãã°ãçºçãããã¨ããªããªããã¨ã©ã¼ã®ã¹ã¿ãã¯ãã¬ã¼ã¹ãè¦ããå ´åã§ã1ã¤ã®ã¨ã©ã¼ãã°4ãè¦ãã°è¯ãã ãã«ãªããä½è¨ãªæéãåæ¸ãããã¨ãã§ãã¾ããã
ãããã«
ä»åã¯ãã¨ã©ã¼ãWrapããã¦ãªãã³ã¼ããã¼ã¹ãå®å ¨ã«å¤æ´ãã¦ãããçµæã¨ãã¦åé·ãªã¨ã©ã¼ãã°ãåæ¸ãã¦ããéç¨ãç´¹ä»ãã¾ããã
Wrapãããã¨ã©ã¼ãã³ããªã³ã°ãæ£ããè¡ãã¦ãªãç®æãè¦ã¤ããããã«ããä»å¾Wrapããã¦ãªãã¨ã©ã¼ãçºè¦ããããã«ãlinterãæ´»èºãã¾ãããlinterã®ãããã§å®å ¨ã«ã³ã¼ãå¤æ´ãè¡ã£ã¦ãããã¨ãã§ããã®ã§ãããããã§ããã
ã¡ãªã¿ã«ããã®åãçµã¿ã¯ãã¼ã ã®æ¹åãã¼ã§å®æ½ããã¾ãããæ¯æãæ¹åãããã¨æã£ã¦ãããã©ãªããªãåãçµãã¦ãªããã¨ã«å¯¾ãã¦ä¸¸ä¸æ¥ããã¦åãçµããã¨ãã§ããã®ã§æ¥½ããã§ãã次ã®æ¹åãã¼ã¯ä½ããããããªã¨æãã馳ãã¦ãã¾ãã
LayerXãªãã£ã¹ã§ã«ã¸ã¥ã¢ã«ã«ããªã³ã¯ã飲ãä¼ãä¼ç»ãã¾ããããã¡ããæ¯éã覧ãã ããï¼
- callerãã£ã¼ã«ãã«ã¯ãã°å¼ã³åºãå ã®ãã¡ã¤ã«åãè¡æ°ãè¨é²ããã¦ãã¾ã↩
- ä¾ãã°pkg/errors, morikuni/failure, cockroachdb/errorsãªã©↩
-
ããã§ã®
errors
ã¯pkg/errors
ã§ã¯ãªããå¼ç¤¾ã®ç¬èªå®è£ ã§ããmorikuni/failure
ãWrapããã©ã¤ãã©ãªã§ã↩ -
ä»åä¿®æ£ããAPIãµã¼ãã¼ã¯gqlgenãå©ç¨ããGraphQLã®APIãµã¼ãã¼ã ã£ãããã
ResponseMiddleware
å ã§ã¨ã©ã¼ãã°åºåããããã«ãã¾ãã↩