1
1

serverless frameworkを使って毎日AWSのコストをSlackに飛ばすlambda関数を作ってみる(実用コードの記載)

Last updated at Posted at 2024-09-02

概要

serverless frameworkを使って毎日AWSのコストをSlackに飛ばすlambda関数のコードを実際に動作するコードに書き換える。
今まではコスト取得期間がハードコーディングされていたが、今回から動的に情報を取得しSlackに通知を投げる部分も作成する。

前提

下記の内容が完了していること。

方法

  • 下記の内容を参考にSlackAppを作ってWebhook URLを発行し、メモする

  • 下記をプロジェクトディレクトリで実行してaxiosをインストール

    npm install axios
    
  • aws-cost-notify/handler.jsを下記のように書き換える

    aws-cost-notify/handler.js
    const AWS = require('aws-sdk');
    const costExplorer = new AWS.CostExplorer({ region: 'us-east-1' });
    const axios = require('axios');
    
    exports.notify = async (event, context) => {
      try {
        console.log('コスト通知イベントを受信しました:', JSON.stringify(event));
    
        const todayDate = new Date(); // lambdaのタイムゾーンはUTC
        const todayYear = String(todayDate.getFullYear());
        // padStartを使って1桁の場合0埋め
        const todayMonth = String(todayDate.getMonth() + 1).padStart(2, '0'); // 月は1月が0で返るので+1
        const todayDay = String(todayDate.getDate()).padStart(2, '0');
        const todayString = todayYear + '-' + todayMonth + '-' + todayDay;
        const firstDayOfMonthString = todayYear + '-' + todayMonth + '-01';
    
        const isFirstDayOfMonth = firstDayOfMonthString === todayString;
        const defaultDayOfMonthAWSCost = 0; // マジックナンバーを避けるためにあえて定数を定義
        let monthlyAWSCost = defaultDayOfMonthAWSCost;
    
        if (!isFirstDayOfMonth) {
          const params = {
            TimePeriod: {
              Start: firstDayOfMonthString, // 取得開始日
              End: todayString, // 取得終了日
            },
            Granularity: 'MONTHLY',
            Metrics: ['UnblendedCost']
          };
          const costExplorerData = await costExplorer.getCostAndUsage(params).promise();
          monthlyAWSCost = costExplorerData.ResultsByTime[0].Total.UnblendedCost.Amount;
        }
        const slackMessageText = '今月のAWS使用量は' + monthlyAWSCost + ' ドルです';
    
        await sendSlackMessage(slackMessageText);
    
        message = 'コスト通知が正常に処理されました';
        return ok(message);
      } catch (error) {
        console.error('エラーが発生しました:', error);
        return internalServerError();
      }
    };
    
    // Slackにメッセージを送信
    async function sendSlackMessage(slackMessageText) {
      const webhookURL = '皆さんのSlack AppのWebhook URL';
      const slackMessage = {
        text: slackMessageText,
      };
    
      try {
        const response = await axios.post(webhookURL, slackMessage);
        console.log('Slack通知のレスポンス:', response.data);
      } catch (error) {
        console.error('Slack通知のエラー:', error);
      }
    }
    
    // 200を返す
    function ok(message = 'OK') {
      return {
        statusCode: 200,
        body: JSON.stringify({ message: message })
      };
    }
    
    // 500を返す
    function internalServerError(message = 'Internal Server Error') {
      return {
        statusCode: 500,
        body: JSON.stringify({ message: message })
      };
    }
    
  • 下記をプロジェクトディレクトリで実行

    serverless invoke local --function notify --data '{"source":"aws.cost","detail-type":"AWS Cost and Usage Report","detail":{"key1":"value1"}}'
    
  • 下記のように指定したSlackチャンネルに料金が投稿されたら一旦完了

    CleanShot 2024-09-03 at 00.11.28@2x.png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1