Setup โปรเจค Spring Boot 3.3 กับ OpenTelemetry + LGTM stack (โค้ด Template เอาไปใช้กันได้เลย)
สวัสดีครับทุกคน กลับมาพบกับผมอีกแล้ว สำหรับบทความที่เป็น Technical หลังจากห่างไป 2–3 เดือน บทความนี้มีที่มาจากทีม Grafana ได้อัพบทความเกี่ยวกับ otel-lgtm container ที่ package ตัว OpenTelemetry Collector และ LGTM stack (โดยตัวนี้คือ Loki/Grafana/Tempo/Prometheus จริง ๆ มันควรจะเป็น Mimir แต่ใช้เป็น Metric ละกันตรงนี้)
แน่นอน ถ้าผมมีความรู้สึกอยากลอง มันนอก Tutorial แน่นอน 😅 ผมก็เลยสร้างตัวโปรเจคเล็ก ๆ ขึ้นมา เพื่อลองใช้ไอ container เนี้ยแหละ กับ Spring Boot 3.3 ก็เลยเกิดขึ้นมาเป็นบทความนี้ 😁
และใช่ครับ จริง ๆ ตัว Template ก็เอามาใช้กับ Side Project แต่ปรับนิดหน่อยก็ใช้ใน Production ได้แล้วครับ ก็มันคือ Spring Boot นี่นา
Getting Started
GitHub Repository
โค้ดส่วนที่เป็น Java ผมจะไม่ได้แนบมานะครับ สามารถดูเพิ่มเติมได้ที่ Repository นะ
Tech Stack
- Spring Boot 3.3
- Java 21
- Gradle
- PostgreSQL
- OpenTelemetry agent เอาไว้ใช้กับ Collector
Gradle build with OpenTelemetry Agent
โดย approach นี้จะไม่ได้ไปโหลด Agent ตอน build container นะครับ แต่กลายเป็นว่าไปเอามาตอน build JAR แทน โดย project structure จะมีหน้าตาแบบนี้
Dockerfile และ Compose file
Note
ผมใช้ podman แล้วไม่รู้มันไปติดอะไรกับตัว Testcontainer ก็เลยใส่ Flag ด้านล่างกับ Terminal ที่จะใช้ podman
export TESTCONTAINERS_RYUK_DISABLED=true
ผมคิดว่าคนที่ใช้ Docker บนเครื่อง ชีวิตน่าจะง่ายขึ้นครับ 😆
ตัวอย่าง HTTP Client ด้วย Intellij IDEA
Note
- GET /coupons — จะสุ่ม Delay เพื่อทำ Long process traffic
- GET /coupons/active — จะสุ่ม 500 เพื่อสร้าง Failure response
Dashboard สำเร็จรูปจาก LGTM container
เนื่องจากว่าพอเปิดขึ้นมา ก็มี Dashboard ตัวนี้มาให้เลย ก็เลยปล่อย Traffic ไว้ตลอดทั้งคืน (เพื่อจะทำบทความนี้แหละ) โดย Dashboard ตัวด้านล่างมีที่มาจาก Dashboard ที่สามารถ import ได้ที่นี่
อีกอันนึงที่ติดมาด้วยคือ RED Metrics โดยตัวที่มี Traffic คือตัว classic histrogram ถ้าเกิดอยากได้ตัว Native ให้ใช้อีก Flag นึง ก็คือ Flag นี้ แต่ผมไม่ได้ใช้ในโปรเจคนี้นะ
export OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION=base2_exponential_bucket_histogram
Custom Dashboard ตัวเอง
ก็อาจจะไม่ได้วางตัว variable อะไรมากครับ แต่จะได้เอาไปปรับใช้กันเวลาทำ Side project
Loki — Logging purpose
โดยอันแรกคือทำ Loki Dashboard เพื่อการ Logging ตัวอย่างด้านล่างคือสร้าง Debug log เอาไว้ดูนู่นนี่
{job="coupon", level="DEBUG"} | json | line_format "{{.body}}"
แล้วก็ Error Log เอาไว้ดูพวก error level
{job="coupon", level="ERROR"} | json | line_format "{{.body}} | traceId: {{.traceid}}"
ทุกคนสามารถมาเอา Logging Dashboard นี้ได้ที่นี่ https://github.com/marttp/spring-boot-lgtm-opentelemetry-template/blob/main/dashboard/loki-log.json
Tempo — Tracing purpose
โดยตัวนี้ผมสร้างเป็นแบบเล็ก ๆ เอาไว้ Tracking by Trace ID โดยแบ่งเป็น 2 ตาราง
Failed response tracer
{.service.name="coupon" && .http.response.status_code=500}
Tracer longer than 4 seconds
{.service.name="coupon" && duration>4s}
โดยสามารถเอา Import Dashboard ได้ที่นี่ https://github.com/marttp/spring-boot-lgtm-opentelemetry-template/blob/main/dashboard/tracer-fail-long.json
สุดท้าย ก็พยายามหาตัว Dashboard สำเร็จรูปมาใช้ด้วย โดยผมเลือกเอา JMX Overview มาใช้
ผลลัพธ์ที่ได้หลังจาก Import Dashboard เข้ามา
สรุปส่งท้าย
ก็อย่างที่ผมบอกในโพสต์ Facebook เลย ผมคิดว่าเอามาใช้กับตระกูล Homelab หรือ Side project ได้ดีเลยนะ แต่ข้อควรระวังก็คือ ถ้าเราจะทำ Configuration ด้วยตัวเอง อยากจะให้ Mapping volume เอาไว้ด้วย
ปัจจุบันในโลกของ Cloud Native ก็จะมีส่วนของ Backend Application และด้วยความต้องการให้มัน Vendor agnostic ก็เลยจะมี OpenTelemetry Collector เพื่อที่จะสามารถกระจายตัว Observability data ไปยังบริการต่าง ๆ ได้
ในทาง Enterprise ก็ยังคงแนะนำให้ใช้เป็น Deployment แยก Service อยู่นะครับ หรือไปใช้ Grafana Cloud ก็ได้เช่นเดียวกัน แต่ด้วย container นี้ ทำให้เราสามารถใช้กับการ Development ได้สะดวกขึ้น 😁
ขอบคุณที่อ่านจนจบ ไว้เจอกันใหม่บทความหน้าครับ ขอให้ทุกคนมีความสุข 🙇♂️
Facebook: Thanaphoom Babparn
FB Page: TP Coder
LinkedIn: Thanaphoom Babparn
Website: TP Coder — Portfolio