ãšã³ãããŒãšã³ãAPIå¯èŠåã®ããã® Go OpenTelemetry ãã¬ãŒã·ã³ã°
Goã§ã®OpenTelemetryãã¬ãŒã·ã³ã°ããHTTPãªã¯ãšã¹ããããã¯ã°ã©ãŠã³ããžã§ããå€éšåŒã³åºãã«ããã£ãŠãã¬ãŒã¹ãã¡ããªã¯ã¹ããã°ãçžé¢ãããããã®å®è·µçãªæé ãšãšãã«è§£èª¬ããŸãã

Go APIã«ããããšã³ãããŒãšã³ããã¬ãŒã·ã³ã°ã®æå³
ãã¬ãŒã¹ã¯ããªã¯ãšã¹ããã·ã¹ãã ãééããéã®ã¿ã€ã ã©ã€ã³ã§ããAPIåŒã³åºããå°çãããšãã«å§ãŸããã¬ã¹ãã³ã¹ãéä¿¡ãããšãã«çµãããŸãã
ãã¬ãŒã¹ã®å åŽã«ã¯ã¹ãã³ããããŸããã¹ãã³ã¯ããªã¯ãšã¹ãè§£æããSQLå®è¡ããæ±ºæžãããã€ãåŒã³åºããã®ãããªã1ã€ã®èšæž¬ãããã¹ãããã§ããã¹ãã³ã«ã¯HTTPã¹ããŒã¿ã¹ã³ãŒããèå¥å¯èœã ãå®å šãªãŠãŒã¶ãŒIDãã¯ãšãªãè¿ããè¡æ°ãªã©ã®æçšãªæ å ±ãä»äžã§ããŸãã
ããšã³ãããŒãšã³ãããšã¯ããã¬ãŒã¹ãæåã®ãã³ãã©ã§æ¢ãŸããªãããšãæå³ããŸããããã«ãŠã§ã¢ãããŒã¿ããŒã¹ã¯ãšãªããã£ãã·ã¥åŒã³åºããããã¯ã°ã©ãŠã³ããžã§ãããµãŒãããŒãã£APIïŒæ±ºæžãã¡ãŒã«ãå°å³ïŒããã®ä»ã®å éšãµãŒãã¹ãšãã£ããåé¡ãé ããã¡ãªç®æãŸã§ãªã¯ãšã¹ãã远ããŸãã
ãã¬ãŒã·ã³ã°ãæã圹ã«ç«ã€ã®ã¯ãåé¡ãæç¶çã«çºçããå Žåã§ãã200åã«1åã ãé ããªã¯ãšã¹ãããããšãããã°ã¯é«éã±ãŒã¹ãšé å»¶ã±ãŒã¹ã§ã»ãšãã©åãã«èŠããã¡ã§ãããã¬ãŒã¹ãããã°éãã¯äžç®çç¶ã§ãïŒãããªã¯ãšã¹ãã¯å€éšåŒã³åºãã§800msåŸ ã¡ã2åãªãã©ã€ãããã®åŸãã©ããŒã¢ãããžã§ããèµ·åããŠããŸããã
ãã°ããµãŒãã¹éã§ã€ãªãã®ãé£ããããšããããŸããAPIã«1è¡ãã¯ãŒã«ãŒã«å¥ã®1è¡ãããããã®éã«äœããªãããšããããããŸãããã¬ãŒã¹ãããã°ããããã®ã€ãã³ãã¯åãtrace IDãå ±æããã®ã§ãæšæž¬ããã«ãã§ãŒã³ããã©ããŸãã
ãã¬ãŒã¹ãã¡ããªã¯ã¹ããã°ïŒåœ¹å²ã®éã
ãã¬ãŒã¹ãã¡ããªã¯ã¹ããã°ã¯ããããå¥ã®çåã«çããŸãã
ãã¬ãŒã¹ã¯1ã€ã®å®éã®ãªã¯ãšã¹ãã§äœãèµ·ãããã瀺ããŸãããã³ãã©ãããŒã¿ããŒã¹åŒã³åºãããã£ãã·ã¥åç §ããµãŒãããŒãã£ãžã®ãªã¯ãšã¹ãã«ããã£ãŠã©ãã«æéã䜿ãããããæããŠãããŸãã
ã¡ããªã¯ã¹ã¯åŸåã瀺ããŸããã¢ã©ãŒãã«æé©ã§ãéèšãå®å®ããŠå®äŸ¡ã§ãïŒã¬ã€ãã³ã·ã®ããŒã»ã³ã¿ã€ã«ããªã¯ãšã¹ãã¬ãŒãããšã©ãŒçããã¥ãŒã®æ·±ãã飜å床ãªã©ã
ãã°ã¯ãã¬ãŒã³ããã¹ãã§ããªããã説æããŸãïŒããªããŒã·ã§ã³ã®å€±æãäºæããªãå ¥åããšããžã±ãŒã¹ãã³ãŒããäžããæ±ºå®ãªã©ã
æ¬åœã®å©ç¹ã¯çžé¢ã§ããåãtrace IDãã¹ãã³ãšæ§é åãã°ã®äž¡æ¹ã«çŸãããšããšã©ãŒãã°ããæ£ç¢ºãªãã¬ãŒã¹ã«ãžã£ã³ãããŠãã©ã®äŸåå ãé ããªã£ãããã©ã®ã¹ãããã倱æããããããã«èŠãããŸãã
ã·ã³ãã«ãªã¡ã³ã¿ã«ã¢ãã«
åä¿¡å·ãåŸæãªçšéã§äœ¿ãåããŸãïŒ
- ã¡ããªã¯ã¹ã¯äœããããããããšãç¥ãããŸãã
- ãã¬ãŒã¹ã¯1ã€ã®ãªã¯ãšã¹ãã§ã©ãã«æéã䜿ããããã瀺ããŸãã
- ãã°ã¯ã³ãŒããäœã決ãããªããããããã説æããŸãã
äŸïŒPOST /checkout ãšã³ããã€ã³ããã¿ã€ã ã¢ãŠããå§ãããšããŸããã¡ããªã¯ã¹ã¯p95ã®ã¬ã€ãã³ã·ãäžæããŠããããšã瀺ããŸãããã¬ãŒã¹ãèŠãã°å€§éšåã®æéãæ±ºæžãããã€ãåŒã³åºãã«è²»ããããŠããããšããããã察å¿ãããã°ã®çžé¢è¡ã«502ã«ãããªãã©ã€ãèšé²ãããŠããã°ãããã¯ãªãèšå®ãäžæµã®ã€ã³ã·ãã³ããçããŸãã
ã³ãŒãã远å ããåã«ïŒåœåããµã³ããªã³ã°ã远跡ããé ç®
äºåã«å°ãèšç»ããŠãããšãåŸã§ãã¬ãŒã¹ãæ€çŽ¢ãããããªããŸããèšç»ããªããšããŒã¿ã¯éãŸããŸãããåºæ¬çãªåããé£ãããªããŸãïŒãããã¯ã¹ããŒãžã³ã°ã§ããæ¬çªã§ããïŒããã©ã®ãµãŒãã¹ãåé¡ãå§ããã®ã§ããïŒã
ãŸãäžè²«ããèå¥ã決ããŠãã ãããåGo APIã«æç¢ºãª service.name ãä»ãïŒäŸãã° checkout-apiïŒãdeployment.environment=dev|staging|prod ã®ãããªåäžã®ç°å¢ãã£ãŒã«ããæãããŸããããããå®å®ãããŠãã ãããé±ã®éäžã§ååãå€ãããšããã£ãŒããæ€çŽ¢ãå¥ã®ã·ã¹ãã ã®ããã«èŠããŸãã
次ã«ãµã³ããªã³ã°ã決ããŸããéçºã§ã¯å šãªã¯ãšã¹ãããã¬ãŒã¹ããã®ãè¯ãã§ãããæ¬çªã§ã¯ã³ã¹ããé«ãããããšãå€ãã§ããäžè¬çãªæ¹æ³ã¯ãéåžžã®ãã©ãã£ãã¯ã®å°ããªå²åããµã³ããªã³ã°ãããšã©ãŒãé ããªã¯ãšã¹ãã¯åžžã«ä¿æããããšã§ãããã«ã¹ãã§ãã¯ãããŒãªã³ã°ã®ãããªé«ãã©ãã£ãã¯ãªãšã³ããã€ã³ãã¯ããã¬ãŒã¹é »åºŠãäžãããç¡èŠãããšããã§ãããã
æåŸã«ãã¹ãã³ã«ä»ããã¿ã°ãšçµ¶å¯Ÿã«åéããªããã®ãåæããŠãã ããããµãŒãã¹éã§ã€ãã³ããã€ãªãã®ã«åœ¹ç«ã€å±æ§ã®ç°¡æœãªèš±å¯ãªã¹ããäœããã·ã³ãã«ãªãã©ã€ãã·ãŒã«ãŒã«ãå®ããŸãã
è¯ãã¿ã°ã¯éåžžãå®å®ããIDãç²ããªã¯ãšã¹ãæ å ±ïŒã«ãŒããã³ãã¬ãŒããã¡ãœãããã¹ããŒã¿ã¹ã³ãŒãïŒãå«ã¿ãŸããæ©å¯ãã€ããŒãã¯å®å šã«é¿ããŠãã ããïŒãã¹ã¯ãŒããæ±ºæžããŒã¿ãã¡ãŒã«å šäœãèªèšŒããŒã¯ã³ããªã¯ãšã¹ãæ¬äœã®çããŒã¿ãªã©ããŠãŒã¶ãŒé¢é£ã®å€ãå«ããå¿ èŠãããå Žåã¯ã远å ããåã«ããã·ã¥åããããã¹ãã³ã°ããŠãã ããã
ã¹ããããã€ã¹ãããïŒGo HTTP APIã«OpenTelemetryãã¬ãŒã·ã³ã°ã远å ãã
èµ·åæã«äžåºŠã ããã¬ãŒãµãŒãããã€ããèšå®ããŸãããããã¹ãã³ã®è¡ãå ãšããã¹ãŠã®ã¹ãã³ã«ä»äžããããªãœãŒã¹å±æ§ã決ããŸãã
1) OpenTelemetryãåæåãã
service.name ãèšå®ããŠããããšãå¿
ã確èªããŠãã ãããããããªããšãç°ãªããµãŒãã¹ã®ãã¬ãŒã¹ãæ··ãã£ãŠãã£ãŒããèªã¿ã¥ãããªããŸãã
// main.go (startup)
exp, _ := stdouttrace.New(stdouttrace.WithPrettyPrint())
res, _ := resource.New(context.Background(),
resource.WithAttributes(
semconv.ServiceName("checkout-api"),
),
)
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exp),
sdktrace.WithResource(res),
)
otel.SetTracerProvider(tp)
ãããGoã®OpenTelemetryãã¬ãŒã·ã³ã°ã®åºç€ã§ããæ¬¡ã«ãåä¿¡ããåãªã¯ãšã¹ãã«å¯ŸããŠã¹ãã³ãäœæããå¿ èŠããããŸãã
2) HTTPããã«ãŠã§ã¢ã远å ããéèŠãªãã£ãŒã«ããååŸãã
èªåã§ã¹ãã³ãéå§ããã¹ããŒã¿ã¹ã³ãŒããšæèŠæéãèšé²ããHTTPããã«ãŠã§ã¢ã䜿ããŸããããã¹ãã³åã¯çã®URLã§ã¯ãªãã«ãŒããã³ãã¬ãŒãïŒ/users/:id ã®ãããªïŒã䜿ã£ãŠèšå®ããŠãã ãããããããªããšãŠããŒã¯ãªãã¹ã倧éã«çãŸããŠããŸããŸãã
ç®æãã¹ãããŒã¹ã©ã€ã³ã¯ã·ã³ãã«ã§ãïŒãªã¯ãšã¹ãããšã«1ã€ã®ãµãŒããŒã¹ãã³ãã«ãŒãããŒã¹ã®ã¹ãã³åãHTTPã¹ããŒã¿ã¹ã®ãã£ããã£ããã³ãã©ã®å€±æãã¹ãã³ã®ãšã©ãŒãšããŠåæ ããã¬ãŒã¹ãã¥ãŒã¢ã§èŠããæèŠæéã
3) é害ãæç€ºçã«ãã
äœãåé¡ãèµ·ãããšãã¯ãšã©ãŒãè¿ããçŸåšã®ã¹ãã³ã倱æãšããŠããŒã¯ããŠãã ãããããã«ããããã°ãèŠãåã«ãã¬ãŒã¹äžã§ãããç®ç«ã€ããã«ãªããŸãã
ãã³ãã©å ã§ã¯æ¬¡ã®ããã«ã§ããŸãïŒ
span := trace.SpanFromContext(r.Context())
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
4) ããŒã«ã«ã§trace IDã確èªãã
APIãå®è¡ããŠãšã³ããã€ã³ããå©ãããªã¯ãšã¹ãã³ã³ããã¹ãããtrace IDã1åãã°åºåããŠããªã¯ãšã¹ãããšã«å€ããããšã確èªããŠãã ãããåžžã«ç©ºãªããããã«ãŠã§ã¢ããã³ãã©ãåãåãã®ãšåãã³ã³ããã¹ãã䜿ã£ãŠããŸããã
DBããµãŒãããŒãã£åŒã³åºãã«ã³ã³ããã¹ããåŒãç¶ã
context.Contextã倱ããšãšã³ãããŒãšã³ãã®å¯èŠåã¯éåããŸããåä¿¡ãããªã¯ãšã¹ãã®ã³ã³ããã¹ãã¯ããã¹ãŠã®DBåŒã³åºããHTTPåŒã³åºãããã«ããŒãžæž¡ãã¹ã¬ããã§ããã¹ãã§ããcontext.Background()ã§çœ®ãæããããäžãžæž¡ãã®ãå¿ãããšããã¬ãŒã¹ã¯å¥åã®ç¡é¢ä¿ãªäœæ¥ã«ãªããŸãã
å€åãHTTPã§ã¯ãDo(req) ã®åŒã³åºãããšã«åã¹ãã³ã«ãªãããèšæž¬æžã¿ã®ãã©ã³ã¹ããŒãã䜿ã£ãŠãã ãããå€åãã®ãªã¯ãšã¹ãã«ã¯W3Cãã¬ãŒã¹ãããã転éããŠãäžæµãµãŒãã¹ãåããã¬ãŒã¹ã«ã¹ãã³ãä»ããããããã«ããŸãã
ããŒã¿ããŒã¹åŒã³åºããåæ§ã§ããèšæž¬æžã¿ãã©ã€ãã䜿ãããQueryContext ã ExecContext ã®åšãã«ã¹ãã³ãäœãã©ãããŒãçšæããŠãã ãããæŒæŽ©ããªãããå®å
šãªæ
å ±ã ããèšé²ããŸããé
ãã¯ãšãªãèŠã€ãããäžæ¹ã§ãããŒã¿ã¯æŒãããããããŸããã
æçšã§äœãªã¹ã¯ãªå±æ§ã«ã¯ãæäœåïŒäŸïŒSELECT user_by_idïŒãããŒãã«ãã¢ãã«åãè¡æ°ïŒæ°ã ãïŒãæèŠæéããªãã©ã€åæ°ãç²ããšã©ãŒçš®å¥ïŒtimeoutãcanceledãconstraintïŒãªã©ããããŸãã
ã¿ã€ã ã¢ãŠããç©èªã®äžéšã§ããDBããµãŒãããŒãã£åŒã³åºãã«ã¯ context.WithTimeout ãèšå®ãããã£ã³ã»ã«ãäžäœã«äŒæãããŠãã ãããåŒã³åºãããã£ã³ã»ã«ããããã¹ãã³ããšã©ãŒãšããŠããŒã¯ããdeadline_exceeded ã®ãããªçãçç±ã远å ããŸãã
ããã¯ã°ã©ãŠã³ããžã§ããšãã¥ãŒã®ãã¬ãŒã·ã³ã°
ããã¯ã°ã©ãŠã³ãäœæ¥ã¯ãã¬ãŒã¹ãéåããããç®æã§ããHTTPãªã¯ãšã¹ããçµãããå¥ã®ãã·ã³äžã®ã¯ãŒã«ãŒãåŸã§ã¡ãã»ãŒãžãæŸããšãå ±æã³ã³ããã¹ãããªããã°2ã€ã®ç¬ç«ããç©èªã«ãªããŸããäœãããªããšAPIãã¬ãŒã¹ãšãã©ãããå§ãŸã£ããããããªããžã§ããã¬ãŒã¹ãå¥ã ã«èŠããŸãã
察åŠã¯ç°¡åã§ãïŒãžã§ãããšã³ãã¥ãŒãããšãã«çŸåšã®ãã¬ãŒã¹ã³ã³ããã¹ãããã£ããã£ããŠãžã§ãã®ã¡ã¿ããŒã¿ïŒãã€ããŒãããããã屿§ãªã©ïŒã«ä¿åããŸããã¯ãŒã«ãŒãéå§ãããšãã«ãã®ã³ã³ããã¹ããæœåºããå ã®ãªã¯ãšã¹ãã®åãšããŠæ°ããã¹ãã³ãéå§ããŠãã ããã
ã³ã³ããã¹ããå®å šã«äŒæ¬ãã
ãã¬ãŒã¹ã³ã³ããã¹ãã ããã³ããŒãããŠãŒã¶ãŒããŒã¿ã¯å«ããªãã§ãã ããã
- ãã¬ãŒã¹èå¥åãšãµã³ããªã³ã°ãã©ã°ïŒW3Cã®traceparentã¹ã¿ã€ã«ïŒã®ã¿ãæ³šå ¥ããã
- ããžãã¹ãã£ãŒã«ããšã¯åé¢ããŠä¿åããïŒäŸïŒå°çšã® "otel" ã "trace" ãã£ãŒã«ãïŒã
- èªã¿æ»ããšãã¯æªæ€èšŒã®å ¥åãšããŠæ±ãïŒãã©ãŒãããæ€èšŒãæ¬ æããŒã¿ã®åŠçïŒã
- ããŒã¯ã³ãã¡ãŒã«ããªã¯ãšã¹ãæ¬äœããžã§ãã¡ã¿ããŒã¿ã«å ¥ããªãã
ãã€ãºåãããã«è¿œå ããã¹ãã³
èªã¿ããããã¬ãŒã¹ã¯ææçŸ©ãªã¹ãã³ãããã€ãããã ãã§ããå¢çããåŸ
ã¡ãã®ãã€ã³ãã®åšãã«ã¹ãã³ãäœæããŠãã ãããåºçºç¹ãšããŠã¯ãAPIãã³ãã©å
ã® enqueue ã¹ãã³ãšã¯ãŒã«ãŒå
ã® job.run ã¹ãã³ãè¯ãã§ãããã
å°éã®ã³ã³ããã¹ãã远å ããŸãïŒè©Šè¡åæ°ããã¥ãŒåããžã§ãã¿ã€ãããã€ããŒããµã€ãºïŒå 容ã§ã¯ãªããµã€ãºã®ã¿ïŒããªãã©ã€ãçºçããå Žåã¯ãããã¯ãªãã®é å»¶ãèŠããããã«ããããå¥ã¹ãã³ãã€ãã³ããšããŠèšé²ããŸãã
ã¹ã±ãžã¥ãŒã«ãããã¿ã¹ã¯ã«ã芪ãå¿ èŠã§ããåä¿¡ãªã¯ãšã¹ãããªãå Žåã¯ãåå®è¡ã§æ°ããã«ãŒãã¹ãã³ãäœããã¹ã±ãžã¥ãŒã«åãã¿ã°ãšããŠä»ããŠãã ããã
ãã°ãšãã¬ãŒã¹ã®çžé¢ïŒãã€ãã°ã®ä¿è·ïŒ
ãã¬ãŒã¹ã¯ã©ãã«æéã䜿ãããããæããŸãããã°ã¯äœãèµ·ãããªãèµ·ãããã説æããŸããããããæ¥ç¶ããæãç°¡åãªæ¹æ³ã¯ããã¹ãŠã®ãã°ãšã³ããªã« trace_id ãš span_id ãæ§é åãã£ãŒã«ããšããŠè¿œå ããããšã§ãã
Goã§ã¯ãcontext.Context ããã¢ã¯ãã£ãã¹ãã³ãååŸããŠãªã¯ãšã¹ãããšïŒãŸãã¯ãžã§ãããšïŒã«ãã¬ãŒã«æ
å ±ã远å ããŸãããããšãã¹ãŠã®ãã°è¡ãç¹å®ã®ãã¬ãŒã¹ãæãããã«ãªããŸãã
span := trace.SpanFromContext(ctx)
sc := span.SpanContext()
logger := baseLogger.With(
"trace_id", sc.TraceID().String(),
"span_id", sc.SpanID().String(),
)
logger.Info("charge_started", "order_id", orderID)
ããã ãã§ãã°ãšã³ããªãããã®æã«å®è¡ãããŠããæ£ç¢ºãªã¹ãã³ã«ãžã£ã³ãã§ããŸããã³ã³ããã¹ããæ¬ ããŠããå Žå㯠trace_id ã空ã«ãªãã®ã§ãããæçœã§ãã
PIIãæŒãããã«ãã°ãæçšã«ä¿ã€
ãã°ã¯ãã¬ãŒã¹ãããé·ãä¿åãããããåºãæµéããããšãå€ãã®ã§ãããå³ããæ±ããŸããããå®å®ããèå¥åãšçµæãåªå
ããŸãïŒuser_idãorder_idãpayment_providerãstatusãerror_codeããŠãŒã¶ãŒå
¥åããã°ããå¿
èŠãããå Žåã¯ãå
ã«ãã¹ãã³ã°ããŠé·ããå¶éããŠãã ããã
ãšã©ãŒãã°ã«ãŒãåãããããã
äžè²«ããã€ãã³ãåãšãšã©ãŒã¿ã€ãã䜿ãã°éèšãæ€çŽ¢ããããããªããŸããæèšãæ¯åå€ãããšåãåé¡ãå€ãã®ç°ãªããã®ã«èŠããŠããŸããŸãã
åé¡ãèŠã€ããããããã¡ããªã¯ã¹ã远å ãã
ã¡ããªã¯ã¹ã¯æ©æèŠæã·ã¹ãã ã§ããGoã®OpenTelemetryãã¬ãŒã·ã³ã°ãæ¢ã«ããèšå®ã§ã¯ãã¡ããªã¯ã¹ã¯ãã©ããããé »ç¹ã«ãã©ãã ãé ·ãããã€ããããçããã¹ãã§ãã
ã»ãšãã©ã®APIã§åœ¹ç«ã€å°ããªã»ããããå§ããŸãïŒãªã¯ãšã¹ãæ°ããšã©ãŒæ°ïŒã¹ããŒã¿ã¹ã¯ã©ã¹å¥ïŒãã¬ã€ãã³ã·ã®ããŒã»ã³ã¿ã€ã«ïŒp50ãp95ãp99ïŒãåæåŠçäžãªã¯ãšã¹ãæ°ãDBãäž»èŠãªãµãŒãããŒãã£åŒã³åºãã®äŸåã¬ã€ãã³ã·ã
ãã¬ãŒã¹ãšã¡ããªã¯ã¹ãæŽåãããããã«ãåãã«ãŒããã³ãã¬ãŒããšååã䜿ã£ãŠãã ãããã¹ãã³ã /users/{id} ã䜿ããªãã¡ããªã¯ã¹ãåæ§ã«ããŸããããããã°ãã£ãŒãã§ã/checkout ã® p95 ãäžãã£ãããšåºããšãã«ããã®ã«ãŒãã§ãã£ã«ã¿ãããã¬ãŒã¹ã«çŽæ¥é£ã¹ãŸãã
ã©ãã«ïŒå±æ§ïŒã«ã¯æ³šæããŠãã ãããäžã€ã®èª€ã£ãã©ãã«ãã³ã¹ããççºãããããã·ã¥ããŒããç¡çšã«ããŸããã«ãŒããã³ãã¬ãŒããã¡ãœãããã¹ããŒã¿ã¹ã¯ã©ã¹ããµãŒãã¹åã¯éåžžå®å šã§ãããŠãŒã¶ãŒIDãã¡ãŒã«ãå®å šãªURLãçã®ãšã©ãŒã¡ãã»ãŒãžã¯éåžžé¿ããŠãã ããã
ããžãã¹äžéèŠãªã€ãã³ãã®ããã«ããã€ãã®ã«ã¹ã¿ã ã¡ããªã¯ã¹ã远å ããŸãïŒäŸïŒcheckout started/completedãæ¯æã倱æãçµæã³ãŒã矀å¥ã«ãããã¯ã°ã©ãŠã³ããžã§ãã®æå察ãªãã©ã€ïŒãã»ããã¯å°ããä¿ã¡ã䜿ããªããã®ã¯åé€ããŠãã ããã
ãã¬ã¡ããªã®ãšã¯ã¹ããŒããšå®å šãªããŒã«ã¢ãŠã
ãšã¯ã¹ããŒãã¯OpenTelemetryãå®çšã«ããéšåã§ãããµãŒãã¹ã¯ã¹ãã³ãã¡ããªã¯ã¹ããã°ãä¿¡é Œã§ããå Žæãžé å»¶ãããã«éãå¿ èŠããããŸãã
ããŒã«ã«éçºã§ã¯ã·ã³ãã«ã«ä¿ã¡ãŸããããã³ã³ãœãŒã«ãšã¯ã¹ããŒã¿ïŒãŸãã¯ããŒã«ã«ã³ã¬ã¯ã¿ãžã®OTLPïŒã¯ããã¬ãŒã¹ãçŽ æ©ã確èªããŠã¹ãã³åã屿§ãæ€èšŒããã®ã«åœ¹ç«ã¡ãŸããæ¬çªã§ã¯ãµãŒãã¹è¿åã®ãšãŒãžã§ã³ããOpenTelemetry Collectorãžã®OTLPãæšå¥šããŸãããªãã©ã€ãã«ãŒãã£ã³ã°ããã£ã«ã¿ãªã³ã°ãäžãæã§æ±ããŸãã
ãããéä¿¡ãéèŠã§ããçãééã§ãããéä¿¡ããã¿ã€ã ã¢ãŠããå³ããèšå®ããŠãããã¯ãŒã¯ã®è©°ãŸããã¢ããªããããã¯ããªãããã«ããŸãããã¬ã¡ããªã¯ã¯ãªãã£ã«ã«ãã¹äžã«ãã£ãŠã¯ãããŸããããšã¯ã¹ããŒã¿ã远ãã€ããªãå Žåãã¡ã¢ãªãæºã蟌ãããããŒã¿ãæšãŠãã¹ãã§ãã
ãµã³ããªã³ã°ã¯ã³ã¹ããäºæž¬å¯èœã«ä¿ã¡ãŸãããŸããããããŒã¹ãµã³ããªã³ã°ïŒäŸïŒ1ã10%ïŒã§å§ããç°¡åãªã«ãŒã«ã远å ããŸãïŒãšã©ãŒã¯åžžã«ãµã³ãã«ããããå€ãè¶ ããé ããªã¯ãšã¹ãã¯åžžã«ãµã³ãã«ãé«é »åºŠã®ããã¯ã°ã©ãŠã³ããžã§ããããå Žåã¯ããããäœãã¬ãŒãã§ãµã³ãã«ããŸãã
段éçã«ããŒã«ã¢ãŠãããŠãã ããïŒéçºã§ã¯100%ãµã³ããªã³ã°ãã¹ããŒãžã³ã°ã§ã¯çŸå®çãªãã©ãã£ãã¯ã§äœãã®ãµã³ããªã³ã°ãæ¬çªã§ã¯ä¿å®çãªãµã³ããªã³ã°ãšãšã¯ã¹ããŒã¿éå®³ãæ€åºããã¢ã©ãŒãã
ãšã³ãããŒãšã³ãå¯èŠåãå°ç¡ãã«ããäžè¬çãªééã
ãšã³ãããŒãšã³ãã®å¯èŠåã倱æããã®ã¯å€ãã®å ŽååçŽãªçç±ããã§ãïŒããŒã¿ã¯ãããç¹ãããªãã
Goã§åæ£ãã¬ãŒã·ã³ã°ãå£ãå žåçãªåé¡ã¯ä»¥äžã§ãïŒ
- ã¬ã€ã€ãŒéã§ã³ã³ããã¹ããèœãšãããã³ãã©ãã¹ãã³ãäœãããDBåŒã³åºããHTTPã¯ã©ã€ã¢ã³ãããŽã«ãŒãã³ã
context.Background()ã䜿ãã - ãšã©ãŒãè¿ãã ãã§ã¹ãã³ã«ããŒã¯ããªãããšã©ãŒãèšé²ããŠã¹ãã³ã¹ããŒã¿ã¹ãèšå®ããªããšããŠãŒã¶ãŒã500ãèŠãŠããŠããã¬ãŒã¹ã¯ãç·ãã«ãªããŸãã
- ãã¹ãŠãèšæž¬ããããã¹ãŠã®ãã«ããŒãã¹ãã³ã«ãªããšãã€ãºãšã³ã¹ããå¢ããŸãã
- é«ã«ãŒãinalityãªå±æ§ã远å ãããIDå ¥ãã®å®å šãªURLãã¡ãŒã«ãçã®SQLå€ããªã¯ãšã¹ãæ¬äœãçã®ãšã©ãŒã¹ããªã³ã°ã¯æ°çŸäžã®ãŠããŒã¯å€ãçã¿ãŸãã
- å¹³åå€ã§ããã©ãŒãã³ã¹ã倿ãããã€ã³ã·ãã³ãã¯å¹³åã§ã¯ãªãããŒã»ã³ã¿ã€ã«ïŒp95/p99ïŒããšã©ãŒçã«çŸããŸãã
ç°¡åãªå¥å šæ§ãã§ãã¯ã¯ãå®éã®1ã€ã®ãªã¯ãšã¹ããéžãã§å¢çãè¶ããŠè¿œãããšã§ããåä¿¡ãªã¯ãšã¹ããDBã¯ãšãªããµãŒãããŒãã£åŒã³åºããéåæã¯ãŒã«ãŒãéããŠ1ã€ã®trace IDãæµããŠããã®ãèŠããªããã°ããŸã ãšã³ãããŒãšã³ãã®å¯èŠåã¯ã§ããŠããŸããã
å®çšçãªãå®äºããã§ãã¯ãªã¹ã
ãŠãŒã¶ãŒå ±åããæ£ç¢ºãªãªã¯ãšã¹ããç¹å®ãããã¹ãŠã®ãããã远ããããã«ãªãã°ã»ãŒå®äºã§ãã
- 1ã€ã®APIãã°è¡ãéžã³ã
trace_idã§æ£ç¢ºãªãã¬ãŒã¹ãèŠã€ãããDBãHTTPã¯ã©ã€ã¢ã³ããã¯ãŒã«ãŒãªã©åããªã¯ãšã¹ãã®æ·±ããã°ãåããã¬ãŒã¹ã³ã³ããã¹ããæã€ããšã確èªããã - ãã¬ãŒã¹ãéãããã¹ãã確èªããïŒãããã«HTTPãµãŒããŒã¹ãã³ããããåã«DBåŒã³åºãããµãŒãããŒãã£APIã®ã¹ãã³ãããããšããã©ãããªäžèЧã¯ã³ã³ããã¹ãã倱ãããŠããããšãæå³ããŸãã
- APIãªã¯ãšã¹ãããããã¯ã°ã©ãŠã³ããžã§ããèµ·åãïŒäŸïŒã¬ã·ãŒãã¡ãŒã«éä¿¡ïŒãã¯ãŒã«ãŒã¹ãã³ããªã¯ãšã¹ãã«ç¹ãã£ãŠããããšã確èªããã
- ã¡ããªã¯ã¹ã®åºæ¬ããã§ãã¯ããïŒãªã¯ãšã¹ãæ°ããšã©ãŒçãã¬ã€ãã³ã·ã®ããŒã»ã³ã¿ã€ã«ãã«ãŒããæäœã§ãã£ã«ã¿ã§ããã確èªããã
- 屿§ãšãã°ãã¹ãã£ã³ããŠå®å šæ§ã確èªããïŒãã¹ã¯ãŒããããŒã¯ã³ãå®å šãªã¯ã¬ãžããã«ãŒãçªå·ãçã®å人ããŒã¿ããªãããšã
ç°¡åãªãªã¢ãªãã£ãã¹ãã¯ã決æžãããã€ããé å»¶ããããã«ããŠé ããã§ãã¯ã¢ãŠããã·ãã¥ã¬ãŒãããããšã§ãã1ã€ã®ãã¬ãŒã¹ã«å€éšåŒã³åºãã¹ãã³ãæç¢ºã«ã©ãã«ä»ããããcheckout ã«ãŒãã® p95 ã¬ã€ãã³ã·ãã¹ãã€ã¯ããŠããã®ãèŠããã¯ãã§ãã
AppMasterïŒappmaster.ioïŒã®ããã«Goããã¯ãšã³ããçæããŠããå Žåã¯ããã®ãã§ãã¯ãªã¹ãããªãªãŒã¹æé ã®äžéšã«ãããšãæ°ãããšã³ããã€ã³ããã¯ãŒã«ãŒãã¢ããªã®æé·ã«äŒŽã£ãŠè¿œè·¡å¯èœãªãŸãŸã«ãªããŸããAppMasterã¯å®éã®GoãµãŒãã¹ãçæããã®ã§ã1ã€ã®OpenTelemetryã»ããã¢ãããæšæºåããŠãµãŒãã¹ãããã¯ã°ã©ãŠã³ããžã§ãã«æã¡éã¹ãŸãã
äŸïŒãµãŒãã¹éã§é ããã§ãã¯ã¢ãŠãããããã°ãã
顧客ããããã§ãã¯ã¢ãŠããæã ãã³ã°ããããšèšãããŸãããåçŸãé£ããã±ãŒã¹ã§ã¯ããŸãã«Goã®OpenTelemetryãã¬ãŒã·ã³ã°ãåšåãçºæ®ããŸãã
ãŸãã¡ããªã¯ã¹ã§åé¡ã®åœ¢ãææ¡ããŸãããã§ãã¯ã¢ãŠãã®ãªã¯ãšã¹ãã¬ãŒãããšã©ãŒçãp95ãp99ã¬ã€ãã³ã·ãèŠãŸããé å»¶ãçæéã®ããŒã¹ãã§äžéšã®ãªã¯ãšã¹ãã«ã®ã¿èµ·ããŠãããªããéåžžã¯äŸåå ããã¥ãŒã€ã³ã°ããŸãã¯ãªãã©ã€æåãåå ã§ãCPUãããã«ããã¯ãšã¯éããŸããã
次ã«åãæé垯ã®é ããã¬ãŒã¹ãéããŸãã1ã€ã®ãã¬ãŒã¹ã§ååãªããšãå€ãã§ããæ£åžžãªãã§ãã¯ã¢ãŠãã¯ãšã³ãããŒãšã³ãã§300ã600msãããããŸãããæªããã®ã¯8ã12ç§ã§ã倧éšåãåäžã®ã¹ãã³ã«è²»ããããŠããããšããããŸãã
ãããããã¿ãŒã³ã¯ããã§ãïŒAPIãã³ãã©èªäœã¯éããDBã¯æŠãåé¡ãªããæ¬¡ã«æ±ºæžãããã€ãã®ã¹ãã³ããªãã©ã€ãšããã¯ãªãã瀺ãããã®éã«äžæµåŒã³åºããããã¯ããã¥ãŒã®èåŸã§åŸ ã£ãŠãããã¬ã¹ãã³ã¹ã¯200ãè¿ãããšãããããšã©ãŒã ãã«åºã¥ãã¢ã©ãŒãã§ã¯æ€åºã§ããŸããã
çžé¢ããããã°ã¯ãã®çµè·¯ãå¹³æã«æããŠãããŸãïŒãretrying Stripe charge: timeoutããdb tx aborted: serialization failureããretry checkout flowãã®ããã«ç¶ãã°ãããã€ãã®å°ããªåé¡ãçµã¿åããã£ãŠæªããŠãŒã¶ãŒäœéšã«ãªã£ãŠããããšãæçœã§ãã
ããã«ããã¯ãèŠã€ããããèªã¿ããããç¶æããããã«äžè²«æ§ãä¿ã£ãŠãã ãããã¹ãã³åã屿§ïŒå®å šãªãŠãŒã¶ãŒIDããã·ã¥ã泚æIDãäŸååïŒããµã³ããªã³ã°ã«ãŒã«ããµãŒãã¹éã§æšæºåããã°ã誰ããåãæ¹æ³ã§ãã¬ãŒã¹ãèªãããšãã§ããŸãã


