AWS日記22 (AWS Budgets)

# はじめに
今回は AWS Budgets のアラート機能を試します。
[Lambda関数・SAMテンプレート]
(https://github.com/tanaka-takurou/serverless-budgets-page-go)



# 準備
[AWS SAM の準備をします](https://qiita.com/tanaka_takurou/items/cae7c19fc3aaf0031abb)

[AWS Budgetsの資料]
[AWS Budgets](https://aws.amazon.com/jp/aws-cost-management/aws-budgets/)


# AWS SAM テンプレート作成

AWS SAM テンプレートで API-Gateway , Lambda, AWS Budgets の設定をします。

[参考資料]
[AWS SAM テンプレートを作成する](https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/tutorial-lambda-sam-template.html)

### AWS Budgetsの設定は以下の部分
```yaml
  Budget:
    Type: "AWS::Budgets::Budget"
    Properties:
      Budget:
        BudgetLimit:
          Amount: 100
          Unit: USD
        TimeUnit: MONTHLY
        BudgetType: COST
        CostFilters:
          AZ:
            - !Ref 'AWS::Region'
      NotificationsWithSubscribers:
        - Notification:
            NotificationType: ACTUAL
            ComparisonOperator: GREATER_THAN
            Threshold: 99
          Subscribers:
            - SubscriptionType: EMAIL
              Address: !Ref Address
        - Notification:
            NotificationType: ACTUAL
            ComparisonOperator: GREATER_THAN
            Threshold: 50
          Subscribers:
            - SubscriptionType: EMAIL
              Address: !Ref Address
```


# Lambda関数作成

※ Lambda関数は aws-lambda-go を利用しました。
AWS Budgets の操作は aws-sdk-go-v2/service/budgets を利用しました。


### Budgets の一覧を取得するには DescribeBudgets を使う
```golang
func describeBudgets(ctx context.Context)(string, error) {
	if budgetsClient == nil {
		budgetsClient = budgets.NewFromConfig(getConfig(ctx))
	}
	input := &budgets.DescribeBudgetsInput{
		AccountId: aws.String(os.Getenv("ACCOUNT_ID")),
	}

	result, err := budgetsClient.DescribeBudgets(ctx, input)
	if err != nil {
		log.Print(err)
		return "", err
	}
	budgetNameList := []string{}
	for _, v := range result.Budgets {
		budgetNameList = append(budgetNameList, aws.ToString(v.BudgetName))
	}
	resultJson, err := json.Marshal(budgetNameList)
	if err != nil {
		log.Print(err)
		return "", err
	}
	return string(resultJson), nil
}
```


### Budget の内容を取得するには DescribeBudget を使う
```golang
func describeBudget(ctx context.Context, budgetName string)(string, error) {
	if budgetsClient == nil {
		budgetsClient = budgets.NewFromConfig(getConfig(ctx))
	}
	input := &budgets.DescribeBudgetInput{
		AccountId: aws.String(os.Getenv("ACCOUNT_ID")),
		BudgetName: aws.String(budgetName),
	}

	result, err := budgetsClient.DescribeBudget(ctx, input)
	if err != nil {
		log.Print(err)
		return "", err
	}
	resultJson, err := json.Marshal(BudgetData{
		BudgetName: aws.ToString(result.Budget.BudgetName),
		LimitAmount: aws.ToString(result.Budget.BudgetLimit.Amount),
		LimitUnit: aws.ToString(result.Budget.BudgetLimit.Unit),
		SpendAmount: aws.ToString(result.Budget.CalculatedSpend.ActualSpend.Amount),
		SpendUnit: aws.ToString(result.Budget.CalculatedSpend.ActualSpend.Unit),
	})
	if err != nil {
		log.Print(err)
		return "", err
	}
	return string(resultJson), nil
}
```

# 終わりに
AWS Budgets のアラート機能を設定し、Webページ上から状況を確認出来るようにしました。
AWS Budgets ダッシュボードより、分散分析や予算基準サマリーも見ることができるため、今後試していこうと思います。

<details><summary>参考資料</summary><div>
[CloudFormation一撃で予算アラート(Budgets)を作成してみた](https://dev.classmethod.jp/articles/cloudformation-budgets-alart/)

[AWS::Budgets::Budget](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-budgets-budget.html)

[budgets · pkg.go.dev](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/budgets)

[AWS Budgets で月額料金管理!!!](https://qiita.com/r-wakamatsu/items/4c7052d7226d13fee4ae)