Go를 활용해 AWS Cloud Watch에 나만의 커스텀 Metric 넣어보기

임태빈·2022년 4월 17일
0

go

목록 보기
12/13

INTRO

안녕하세요.

cloudwatch에 나만의 커스텀 Metric을 넣어보려고 합니다.

Aws SDK를 보던 중 Metric을 보내는 방법이 있어서 이를 테스트 하게 되었고

제가 간단하게 만든 데이터가 CloudWatch에서 만드는 데이터와 동일하다는 것을 볼 수 있었습니다.

어떻게 제가 만들었는지에 대해서 설명드리겠습니다.

Cloud Watch agent 내부 간단하게 파해쳐보기

AWS Cloud Watch agent가 github에 공개되어 있어 내부 코드를 잠깐이나마 뜯어보았습니다.
그러면서 agent에서 telegraf기능을 사용하고 있다는 것을 발견하게 되었습니다.

	ag, err := agent.NewAgent(c)
	if err != nil {
		return err
	}

	// Setup logging as configured.
	logConfig := logger.LogConfig{
		Debug:               ag.Config.Agent.Debug || *fDebug,
		Quiet:               ag.Config.Agent.Quiet || *fQuiet,
		LogTarget:           ag.Config.Agent.LogTarget,
		Logfile:             ag.Config.Agent.Logfile,
		RotationInterval:    ag.Config.Agent.LogfileRotationInterval,
		RotationMaxSize:     ag.Config.Agent.LogfileRotationMaxSize,
		RotationMaxArchives: ag.Config.Agent.LogfileRotationMaxArchives,
	}

	logger.SetupLogging(logConfig)

	if *fTest || *fTestWait != 0 {
		testWaitDuration := time.Duration(*fTestWait) * time.Second
		return ag.Test(ctx, testWaitDuration)
	}

	log.Printf("I! Loaded inputs: %s", strings.Join(c.InputNames(), " "))
	log.Printf("I! Loaded aggregators: %s", strings.Join(c.AggregatorNames(), " "))
	log.Printf("I! Loaded processors: %s", strings.Join(c.ProcessorNames(), " "))
	log.Printf("I! Loaded outputs: %s", strings.Join(c.OutputNames(), " "))
	log.Printf("I! Tags enabled: %s", c.ListTags())

	agentinfo.InputPlugins = c.InputNames()
	agentinfo.OutputPlugins = c.OutputNames()

	if *fPidfile != "" {
		f, err := os.OpenFile(*fPidfile, os.O_CREATE|os.O_WRONLY, 0644)
		if err != nil {
			log.Printf("E! Unable to create pidfile: %s", err)
		} else {
			fmt.Fprintf(f, "%d\n", os.Getpid())

			f.Close()

			defer func() {
				err := os.Remove(*fPidfile)
				if err != nil {
					log.Printf("E! Unable to remove pidfile: %s", err)
				}
			}()
		}
	}
	logAgent := logs.NewLogAgent(c)
	go logAgent.Run(ctx)
	return ag.Run(ctx)

여기에 들어가보시면 telegraf agent를 실행하는 코드를 보실 수 있습니다.

telegraf 데이터 수집 방법

Cloudwatchagent는 telegraf를 활용해서 데이터를 수집하고 있습니다.
그렇다면 telegraf는 어떻게 데이터를 수집하고 있을까요?

이 부분이 저또한 궁금해서 telegraf 내부 코드를 조금 뜯어보았습니다.

telegraf에 경우, 이 오픈 소스를 활용해서 메트릭을 수집하는 것을 확인할 수 있었습니다.
Go개발자 분들에 경우 한번쯤은 써보셨을 오픈 소스 라이브러리인데
여기서 보니 반갑다는 생각이 들었습니다.

telegraf에서 이 코드를 어떻게 활용하고 있는지에 대해서는 여기를 확인해주시면 좋을 거 같습니다.

나만의 Custom Metric 만들기

aws sdk에 경우 Cloud watch에 metric을 직접 생성해서 전달하는 함수가 존재합니다.
저는 이를 활용해서 제 메모리 정보를 전달할 수 있었습니다.

만들기 전에 앞서 NameSpace에 대해 알아야합니다.
NameSpace는 여러 지표에 대한 공간이라고 생각하시면 좋습니다.
예를 들어, instance에 대한 지표들이 있는데 이를 모아둔 곳이 Instance NameSpace라고 생각하시면 좋습니다.

이제 만들어 보도록하겠습니다.

라이브러리 다운로드를 하겠습니다.

go get "github.com/tae2089/goAws"

위 라이브러리는 제가 aws를 쉽게 사용해보려고 커스텀하고 있는 라이브러리입니다:)
현재는 s3와 cloud watch에 관련된 부분이 있습니다 ㅎㅎ

라이브러리 다운이 되었다면 이제 코드를 입력해보겠습니다.

코드는 간단합니다.

package main

import (
	"github.com/tae2089/goAws/cloudwatch"
	"time"
)

func main() {

	instanceName := "<인스턴스이름>"
	instanceId := "<인스턴스 id>"

	c := cloudwatch.CloudwatchInfo{
		AwsRegion:       "<aws region>",
		AwsAccessKey:    "<AwsAccessKey>",
		AwsSecretKey:    "<AwsSecretKey>",
		AwsInstanceName: instanceName,
		AwsInstanceId:   instanceId,
		AwsProfileName:  "default",
		AwsNamespace:    "<Namespace name>",
	}

	err := c.SetConfigByKey()
	if err != nil {
		panic(err)
	}
	for {
		_, err := c.PutMetricData(cloudwatch.MemoryPercent)
		if err != nil {
			panic(err)
		}
		time.Sleep(1 * time.Second)
	}

}

CloudwatchInfo에 원하는 region,accesskey,secretkey,namespace를 입력해주시면 됩니다.
accesskey,secretkey를 박은 사용자의 권한에는 cloudwatch를 사용할 수 있는 권한이 필요합니다.
이를 사용하시면 다음과 같은 결과들을 얻을 수 있습니다.

첫번째 사진은 namespace 내부에 생긴 것입니다.

두번째 사진은 모니터링한 것을 보여주는 사진입니다.

궁금하신 부분이 있다면 댓글 부탁드립니다:)

profile
golang과 서버 개발을 하고 있는 개발자입니다.

0개의 댓글