Lambda関数(Node.js)を使用してAWSの月間コストをLINEに通知する

Lambda関数(Node.js)を使用してAWSの月間コストをLINEに通知する

2024/05/05

2024/05/06

以下のようにLambda関数とLINE Notifyを使用してAWSの月間コストをLINEに通知する方法です。

前提条件

LINE Notifyアカウントが作成されていること
LINE Notify通知用のTOKENを取得していること

Node.jsでソースを作成する

npmインストール

npm i aws-sdk axios


index.mjsを作成

import AWS from 'aws-sdk';
import axios from 'axios';
const costExplorer = new AWS.CostExplorer({ region: 'ap-northeast-1' });

const BASE_URL = 'https://notify-api.line.me/api/notify';
const LINE_TOKEN = process.env.LINE_TOKEN;

export const handler = async (event) => {
    // 今月の初日を計算
    const startDate = new Date();
    startDate.setDate(1); // 月の初日に設定
    const formattedStartDate = startDate.toISOString().split('T')[0];

    // 今日の日付を取得
    const endDate = new Date().toISOString().split('T')[0];

    const params = {
        TimePeriod: {
            Start: formattedStartDate,
            End: endDate,
        },
        Granularity: 'MONTHLY',
        Metrics: ['UnblendedCost'],
        GroupBy: [
            {
                Type: 'DIMENSION',
                Key: 'SERVICE',
            },
        ],
    };

    try {
        // AWS Cost Explorer からコストデータを取得
        const data = await costExplorer.getCostAndUsage(params).promise();

        // サービス別コストを整形して出力
        let totalCost = 0;
        const outputMessage = [];
        outputMessage.push('\n【AWS Cost Report】');
        data.ResultsByTime.forEach((result) => {
            outputMessage.push(`${result.TimePeriod.Start} ~ ${result.TimePeriod.End}\n`);

            result.Groups.forEach((group) => {
                const serviceName = group.Keys[0];
                const amount = group.Metrics.UnblendedCost.Amount;
                const unit = group.Metrics.UnblendedCost.Unit;
                totalCost += parseFloat(amount);

                // 0.01 USD 未満の場合は表示しない
                if (amount < 0.01) return;

                outputMessage.push(`${serviceName}: $${parseFloat(amount).toFixed(2)}`);
            });
            if (result.Groups.length === 0) {
                console.log('No cost data available for this period.');
            }
        });

        // 合計金額を追加
        outputMessage.push(`\n💰Total Cost: $${totalCost.toFixed(2)} USD`);

        // コンソールに出力
        console.log(outputMessage.join('\n'));

        // LINE Notify に送信するメッセージを整形
        const sendParams = new URLSearchParams({
            message: outputMessage.join('\n'),
        });

        // LINE Notify に通知を送信するための設定
        const config = {
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                Authorization: `Bearer ${LINE_TOKEN}`,
            },
        };

        // LINE Notify に通知を送信
        const res = await axios.post(BASE_URL, sendParams.toString(), config);
        console.log(res.status);

        return {
            statusCode: 200,
            body: JSON.stringify({
                message: 'Cost data retrieved successfully',
                data: data.ResultsByTime,
            }),
        };
    } catch (error) {
        console.error('Error fetching cost data:', error);
        return {
            statusCode: 500,
            body: JSON.stringify({
                message: 'Error fetching cost data',
                error: error.message,
            }),
        };
    }
};


Lambda関数デプロイ用にzip圧縮する。以下はコマンドの例です。

# linux/mac
zip -r function_name.zip .

# windows command prompt
powershell Compress-Archive -Path * -DestinationPath function_name.zip

# windows powershell
Compress-Archive -Path * -DestinationPath function_name.zip


Lambda関数を作成し、デプロイする

Lambda関数を作成する。
・ランタイム:Node.js 20.x



環境変数を設定する。
・キー:LINE_TOKEN
・値 :トークン値


Testを実行してLINEに出力されたら成功です。

以下の記事などを使用して定期的に実行可能です。
チュートリアル: EventBridge を使用した AWS Lambda 関数のスケジュール

参考資料

nodejs-send-aws-cost