X-Ray 기본 동작 Overview
Application 에서 X-Ray SDK 를 활용하여 Trace 하고자 하는 구간을 작성하면,
X-Ray SDK는 X-Ray daemon 에 해당 구간 메세지를 전달. X-Ray daemon 은 이를 X-Ray API 에 전달.
X-Ray API 는 다른 client 의 Trace 정보도 취합하여 X-Ray console 에서 보여줌
- X-Ray daemon: https://docs.aws.amazon.com/xray/latest/devguide/xray-daemon-ec2.html
- X-Ray SDK: https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-go.html
Lambda의 경우 자동으로 daemon 이 실행되지만, EC2 는 직접 실행 필요
EC2 에서 X-Ray 활성화하기
download daemon
curl https://s3.ap-northeast-2.amazonaws.com/aws-xray-assets.ap-northeast-2/xray-daemon/aws-xray-daemon-3.x.rpm -o /home/commonadm/xray.rpm
sudo apt install alien
sudo alien xray.rpm
sudo dpkg -i xray_3.3.8-2_amd64.deb
# 설치 확인
xray -n ap-northeast-2
permission 획득
EC2에서 X-Ray daemon을 통해 X-Ray API에 데이터를 보내기 위해서는 AWSXRayDaemonWriteAccess 권한이 필요
$ xray -n ap-northeast-2
2023-09-21T13:41:00Z [Info] Initializing AWS X-Ray daemon 3.3.8
...
2023-09-21T13:41:03Z [Error] Sending segment batch failed with: AccessDeniedException: User: arn:aws:iam::... is not authorized to perform: xray:PutTraceSegments because no identity-based policy allows the xray:PutTraceSegments action
status code: 403, request id: cb539924-e6f8-46e0-b6ab-6f817034fc5e
X-Ray SDK 로 원하는 구간 추가
Install x-ray sdk
go get github.com/aws/aws-xray-sdk-go
Incoming Request
참고: https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-go-handler.html
Trace 의 시작 정보는 handler 함수에 추가. echo 서버의 middleware 를 활용
func main() {
...
e := echo.New()
e.Use(log.LoggerWrapper(config))
e.Use(middleware.Recover())
e.Use(xRay())
...
}
func xRay() echo.MiddlewareFunc {
return echo.WrapMiddleware(func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
xray.Handler(xray.NewFixedSegmentNamer("my-ec2-go"), h).ServeHTTP(w, r)
})
})
}
Tracing AWS SDK Call
AWS SDK 를 사용하는 경우 간편하게 Trace 코드 추가 가능
https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-go-awssdkclients.html
- xray.AWS() 로 client wrapping 하기
- AWS SDK에서는 trace 를 위해 모든 method의 ...WithContext 버전을 제공. i.e) lambda 의 경우, invoke() 와 invokeWithContext()
func createLambdaClient(endpoint string, region string) *lambda.Lambda {
sess, err := CreateSession(endpoint, region)
if err != nil {
return nil
}
client := lambda.New(sess)
xray.AWS(client.Client)
return client
}
func (l *Lambda) InvokeLambdaWithRole(ctx context.Context, lambdaName string, qualifier string, invokationType string, payload []byte, roleArn string, roleSessionName string) error {
...
sess := session.Must(session.NewSession())
creds := stscreds.NewCredentials(sess, lambdaName, func(provider *stscreds.AssumeRoleProvider) {
provider.RoleARN = roleArn
provider.RoleSessionName = roleSessionName
})
conf := aws.Config{
Region: aws.String(l.region),
Credentials: creds,
MaxRetries: aws.Int(0),
}
assumedRoleLambdaClient := lambda.New(sess, &conf)
if _, err := assumedRoleLambdaClient.InvokeWithContext(ctx, params); err != nil {
return err
}
return nil
}
Tracing Outgoing HTTP calls
Go 에서 제공하는 org/x/net/context/ctxhttp 를 사용하여 3rd party server로 Rest 요청하는것을 trace 가능
참고: https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-go-httpclients.html
func InitHTTPClient() {
if httpClient == nil {
httpClient = xray.Client(createHTTPClient())
}
}
func post(ctx context.Context, url string, body string, headers map[string]string) (*http.Response, error) {
req, err := http.NewRequest("POST", url, strings.NewReader(body))
...
return ctxhttp.Do(ctx, httpClient, req)
}
Custom Subsegments
별도로 context 저장을 제공하지 않는 경우, 원하는 위치에 subsegments 추가하기 위해서는 xray.BeginSubsegment() 활용
func (m *M) testTrace(a map[string]interface{}) error {
...
_, subSeg := xray.BeginSubsegment(m.context, fmt.Sprintf("%s %s", "Get", a["b"]))
cachedData, _ := cache.Get(cacheKey)
subSeg.Close(nil)
...
}
'자습' 카테고리의 다른 글
AWS ASG lifecycle Hook (remotely run shell command on EC2) (0) | 2024.03.29 |
---|---|
Go Thread-Safety : sync.Mutex, sync.Map (0) | 2023.08.26 |
Spring Native (0) | 2022.05.14 |
go gRPC Server & gRPC Gateway (0) | 2021.09.20 |
Kong Gateway + Konga (0) | 2021.08.29 |