今回はAWS-SDKを用いて、大量のデータを取得するEC2インスタンスの1時間当たりのファイル取得量をCloudWatchでカスタムメトリクス化して取得状況を監視するシステムを作成したので、一部をご紹介します。
AWS関連の部分以外はGoの標準パッケージのみで作るシンプルなものになっています。
Goでファイル取得数を計算する
下記のプログラムで現在のファイル取得数と経過時間を計算します。
コード自体はとてもシンプルです。
package calculator
import (
"fmt"
"io/ioutil"
"math"
"os"
"path/filepath"
"sort"
)
func GetFetchSpeed() (float64, error) {
dir := `取得したいディレクトリ`
//ディレクトリからファイルを取得
files, err := ioutil.ReadDir(filepath.Dir(dir))
if err != nil {
return 0, err
}
//編集日時順にファイルをソートします。
sort.Slice(files, func(i, j int) bool {
return files[i].ModTime().Unix() < files[j].ModTime().Unix()
})
firstFile, err := os.Stat(dir + files[0].Name())
if err != nil {
return 0, err
}
lastFile, _ := os.Stat(dir + files[len(files)-1].Name())
if err != nil {
return 0, err
}
//最初のファイルを取得してからの経過時間を計算
elapsedTime := lastFile.ModTime().Sub(firstFile.ModTime())
if elapsedTime < 0 {
elapsedTime *= -1
}
//1時間ごとのファイル取得数
elapsedMinute := math.Trunc(elapsedTime.Minutes())
fetchedPerHour := len(files) / int(elapsedMinute) * 60
return float64(fetchedPerHour), nil
}
取得した情報をCloudWatchでメトリクス化する。
package metrics
import (
"fmt"
"io/ioutil"
"net/http"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cloudwatch"
)
func getInstanceID() string {
//このアドレスにアクセスするとEC2インスタンスのインスタンスIDを取得することができます。
resp, err := http.Get("http://169.254.169.254/latest/meta-data/instance-id")
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
}
return string(body)
}
//メトリクスを作成します
func CreateMetrics(value float64) {
cw := cloudwatch.New(session.New(), &aws.Config{Region: aws.String("ap-northeast-1")})
dimensionParam := &cloudwatch.Dimension{
Name: aws.String("InstanceId"),
Value: aws.String(getInstanceID()),
}
metricDataParam := &cloudwatch.MetricDatum{
Dimensions: []*cloudwatch.Dimension{dimensionParam},
MetricName: aws.String("Files per 1Hour"),
Unit: aws.String("Count"),
Value: aws.Float64(value),
}
putMetricsDataInput := &cloudwatch.PutMetricDataInput{
MetricData: []*cloudwatch.MetricDatum{metricDataParam},
//メトリクスの名前空間
Namespace: aws.String("EC2"),
}
cw.PutMetricData(putMetricsDataInput)
}
この二つのパッケージをmain.goで実行します。
func main() {
value, err := calculator.GetFetchSpeed()
if err != nil {
fmt.Printf("Error while calculatoring speed:%s\n", err)
}
if value > 0 {
metrics.CreateMetrics(value)
}
}
以上になります。
このメトリクス化する仕組みを用いればいろんなものを可視化することができるので、監視や運用に役立つかと思います。