AWS Account Billingを使って毎日の利用額の確認する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWSからの請求を確認する

AWSは、1時間単位やリクエスト数等の使った分だけ請求される従量課金のサービスです。以前までは月末に請求額をお知らせするメールが来てインスタンス落とし忘れてビックリなんてことがありましたがw、今は請求額に関するアラート通知があり、より計画的な運用が可能となっています。そして、このたびAWS Account Billingがリリースされました。

  • 請求確定のメールで確認する
  • アカウント管理画面で確認する
  • 課金アラートの通知で確認する
  • AWS Account Billingを使って確認する

AWS Account BillingのProgrammatic Accessとは

AWS Account Billingは、AWSの利用状況についてプログラムからアクセスできる仕組みです。具体的にはS3にCSV形式で利用状況がアップされるので、プログラムからアクセスして加工することで一覧や詳細などの情報を見る事ができます。

AWS Account BillingのProgrammatic Accessを使ってみる

AWS Account Billingを有効にするためには、AWSアカウント管理画面のBilling PreferenceのProgrammatic Accessを有効にする必要があります。保存先のユニークなS3名を指定して保存します。この際、S3のBucket Policyが作成されますのでテキストをコピーしておきます。次に、AWSマネジメントコンソールからS3を開き、先ほど指定したS3名のBucketを作成します。

作成した後、先ほどコピーしておいたBucket Policyを反映させましょう。

AWSアカウント管理画面に戻りますとProgrammatic Accessが有効になっています。

S3の管理画面を見ると疎通確認用のファイルが生成されています。

そしてじっと待つ。。。。。利用額を確認できるCSVファイルが生成されました!

プログラムからアクセスしてみる

S3からCSV形式で取得できるようになりましたので、プログラムからアクセスしてみます。以下はJavaのソースです。リージョンとプロダクト毎にレコードがありますので、プロダクト名で集約して金額を出力してみました。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;

import au.com.bytecode.opencsv.CSVReader;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.PropertiesCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.S3Object;

public class S3Sample {

	private static String MY_ACCOUNT_NUMBER = "XXXXXXXXXXXX";
	private static String BILLING_BUCKET_NAME = "satoshi-yokota";
	private static String YEAR = "2012";
	private static String MONTH = "06";
	private static int ACCOUNT_COLUMN = 2;
	private static int PRODUCT_COLUMN = 12;
	private static int EXPENSE_COLUMN = 28;

	public static void main(String[] args) throws IOException {

		AmazonS3 s3 = new AmazonS3Client(
				new PropertiesCredentials(S3Sample.class
						.getResourceAsStream("AwsCredentials.properties")));

		String objectName = MY_ACCOUNT_NUMBER + "-aws-billing-csv-"+YEAR+"-"+MONTH+".csv";

		try {
			S3Object object = s3.getObject(new GetObjectRequest(BILLING_BUCKET_NAME,objectName));
			displayTextInputStream(object.getObjectContent());

		} catch (AmazonServiceException ase) {
			System.out.println(ase);
		} catch (AmazonClientException ace) {
			System.out.println(ace);
		}
	}

	private static void displayTextInputStream(InputStream input)
			throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(input));
		CSVReader reader = new CSVReader(br);
		String[] nextLine;
		HashMap<String, BigDecimal> map = new HashMap<String, BigDecimal>();

		while (true) {
			nextLine = reader.readNext();
			if (nextLine == null)
				break;
			if (nextLine[ACCOUNT_COLUMN].equals(MY_ACCOUNT_NUMBER)) {
				BigDecimal currentExpense = map.get(nextLine[PRODUCT_COLUMN]);
				if (isEmpty(currentExpense)){
					currentExpense = new BigDecimal(0);					
				}
				
				String newExpenseString = nextLine[EXPENSE_COLUMN];
				BigDecimal newExpense;
				if (isEmpty(newExpenseString)){
					newExpense = new BigDecimal(0);
				}else{
					newExpense = new BigDecimal(newExpenseString);
				}

				if (!isEmpty(nextLine[PRODUCT_COLUMN])) {
					double value1 = currentExpense.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
					double value2 = newExpense.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
					BigDecimal finalExpense = new BigDecimal(value1+value2);
					map.put(nextLine[PRODUCT_COLUMN],finalExpense.setScale(2, BigDecimal.ROUND_HALF_UP));
				}
			}
		}
		
		Iterator<String> productIterator = map.keySet().iterator();
		while (productIterator.hasNext()) {
			String productName = productIterator.next();
			BigDecimal expenseSum = map.get(productName);
			System.out.println(productName + " " + expenseSum.doubleValue());
		}
	}

	private static boolean isEmpty(Object obj){
		if(obj == null){
			return true;
		}
		if(obj instanceof String){
			if(((String)obj).equals("")){
				return true;
			}
		}
		return false;
	}
}

実行結果はこんな感じ。

AmazonRoute53 0.5
AmazonSNS 0.0
AWSDataTransfer 0.1
AwsPremiumSupportBronze 49.0
AmazonEC2 48.56
AmazonRDS 29.38
AmazonSimpleDB 0.0
AmazonS3 2.1

まとめ

CSVには様々な情報が埋まっていますので色々試してみてはいかがでしょうか。日々の利用額を把握しながら少しでも無駄を減らしましょう。今日から君もMP節約の魔法使い!!

参考資料

AWS Account Billing : Getting Your Bill