엔지니어링/Kubernetes

Elastic APM으로 Go Application 모니터링

joon95 2024. 10. 9. 00:00
반응형

진행하고 있는 프로젝트의 개발팀에서 Golang 기반 Backend API를 개발하는게 있어서 연초에 VUE, GO Application 샘플을 개발해놓았다. (매우 간단하게...)

 

이후 Application Performance Monitoring을 어떻게 할 것인가?

에 대한 질문들로 Elastic APM을 사용해보기로 했다.

 

지금까지 java APM만을 셋업했었는데 golang은 어떻게 다른지 파악해보자.

Java와의 차이

java application은 javaagent 로 올리면 바이트코드를 읽어 자동으로 수집하지만 go application은 아니다.

 

그래도 http route, gorm 을 통해 어느정도 요청에 대한 그래프를 볼 수 있다.

필자는 라우터 라이브러리로 고릴라, 데이터베이스는 gorm으로 프로젝트를 구성하였다.

  • gorilla/mux
  • gorm

 

적용방법

elastic에서 지원하는 라이브러리를 사용하여 아주 간편하게 적용할 수 있는데, 라우터에는 미들웨어를 추가하고, gorm은 전용 driver를 활용하면 되며, 모두 Elastic 공식 가이드 문서를 참고하여 진행하였다.

 

모듈 다운로드

go get -u go.elastic.co/apm/v2

 

 

goilla/mux 적용

route.go 파일에서 Route 생성 부분에 추가한다.(맨 처음으로 미들웨어 등록 필수)

참고로 golang 에서 지원하는 라우터 종류가 많은데 고릴라를 활용하면 elastic apm 에서 추적하는 것이 많다고 한다.

func NewHttpHandler() http.Hander {
	...
	// Elastic APM 추가 ( gorilla mux 는 자동으로 트랜잭션을 추적하도록 도와줌)
	mux.Use(apmgorilla.Middleware())
	...
}

 

 

gorm 적용

dbConnection.go 파일에서 gorm.io/driver/mysql 라이브러리를 go.elastic.co/apm/module/apmgormv2/v2/driver/mysql 로 교체한 뒤 mysql.Open 을 변경한다..

import (
	...
	apmmysql "go.elastic.co/apm/module/apmgormv2/v2/driver/mysql"
	//"gorm.io/driver/mysql"
	...
)

func InitDB() {
	...
	db, err := gorm.Open(apmmysql.Open(dsn), &gorm.Config{})
	...
}

route.go 파일에서 미들웨어를 추가한다.

func NewHttpHandler() http.Hander {
  ...
	// DB Context 미들웨어 추가
  mux.Use(DBContextMiddleware)
  ...
}
// APM 미들웨어 함수
func DBContextMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()
		DB = DB.WithContext(ctx)
		next.ServeHTTP(w, r)
	})
}

 

환경 변수 설정(Local)

먼저 개발자 PC에서 검증을 거치기 위해 local 테스트를 진행한다.

ELASTIC_APM_SECRET_TOKEN=QnVsV0laRUJ4OWo3QVBpdVZQbTU6MEVkcjJkRklUN2E0NDFCNUY1T3Yydw==
ELASTIC_APM_SERVER_URL=http://{ip}:{port}/
ELASTIC_APM_SERVER_TIMEOUT=60s

ELASTIC_APM_SERVICE_NAME=local-test
ELASTIC_APM_ENVIRONMENT=local

ELASTIC_APM_LOG_FILE=stderr
ELASTIC_APM_LOG_LEVEL=debug

 

설정 후 application 을 구동 하면 아래와 같이 나온다.(주기적으로 트랜잭션을 서버에 전달함)

{"level":"debug","time":"2024-08-07T14:40:39+09:00","message":"sent request with 2 transactions, 1 span, 0 errors, 0 metricsets"}
{"level":"debug","time":"2024-08-07T14:40:53+09:00","message":"gathering metrics"}
{"level":"debug","time":"2024-08-07T14:41:03+09:00","message":"sent request with 0 transactions, 0 spans, 0 errors, 4 metricsets"}

 

환경 변수 설정(Server)

서버에 배포했을 때 연결될 네트워크 정보를 설정한다.

필자의 환경은 애플리케이션을 kubernetes 에 배포하여 서비스명.네임스페이스.svc 경로로 서버를 지정하였고, APM 에서 수집될 명, 환경에 대한 구분을 변경해주었다.

ELASTIC_APM_SECRET_TOKEN=QnVsV0laRUJ4OWo3QVBpdVZQbTU6MEVkcjJkRklUN2E0NDFCNUY1T3Yydw==
ELASTIC_APM_SERVER_URL=http://apm-server-apm-server.logging.svc:8200
ELASTIC_APM_SERVER_TIMEOUT=60s

ELASTIC_APM_SERVICE_NAME=my-goapp-service
ELASTIC_APM_ENVIRONMENT=dev

#ELASTIC_APM_LOG_FILE=stderr
#ELASTIC_APM_LOG_LEVEL=debug

 

 

Kibana에서 확인

Postman API Test

먼저 간단하게 API를 호출하는 스크립트를 작성하였다.

랜덤값을 발생시켜 PUT API(데이터를 insert 하는 로직)에서 일부로 Duplicate Key 에러를 발생시키고자 한다.

Collection Enviroment Variable Setting
body raw data

 

Env Variable Random Rotate

 pm.environment.set("randomNumber", Math.floor(Math.random() * 500000));
 --- body raw
 {
    "UserId":"auto{{randomNumber}}",
    "FirstName":"first{{randomNumber}}",
    "LastName":"lim",
    "Email":"auto@{{randomNumber}}"
}

 

설정을 마친 뒤 Runner 를 통해 API를 자동으로 호출하자.

 

Kibana View

APM 탭에서 이제 아래와 같은 데이터를 확인할 수 있다. 트랜잭션 처리 속도는 분단위(TPM)로 볼 수 있는게 약간 아쉽다.

 

Error 가 발생한 Case를 확인할 수 있다.

Elastic APM Golang Error View

APM의 핵심인 구간별 레이턴시도 확인할 수 있다. 

Elastic APM Trace View

 

 

무료로 이런 기능을 제공한다는 점에서 매우 괜찮게 느꼈다. 그동안 Logging 적재/분석용으로 ElasticSearch를 구축/운영 했었는데, 더 많은 기능들이 있었고, 실제로 사용하는 사례도 적잖게 있다고하니 도입을 검토 해볼만하다고 느낀다.

 

 

 

 

GitHub - joonhyeok95/golang_study2: 배포 환경 변수화

배포 환경 변수화. Contribute to joonhyeok95/golang_study2 development by creating an account on GitHub.

github.com

 

 

Set up the Agent | APM Go Agent Reference [2.x] | Elastic

To start reporting your Go application’s performance to Elastic APM, you need to do a few things: Within a Go module, install the Elastic APM Go agent package using go get: go get -u go.elastic.co/apm/v2 You can find a list of the supported frameworks an

www.elastic.co

 

반응형