概要
serverless frameworkを使って毎日AWSのコストをSlackに飛ばすlambda関数のコードを実際に動作するコードに書き換える。
今まではコスト取得期間がハードコーディングされていたが、今回から動的に情報を取得しSlackに通知を投げる部分も作成する。
前提
下記の内容が完了していること。
方法
- 下記の内容を参考にSlackAppを作ってWebhook URLを発行し、メモする
-
下記をプロジェクトディレクトリで実行してaxiosをインストール
npm install axios
-
aws-cost-notify/handler.jsを下記のように書き換える
aws-cost-notify/handler.jsconst 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チャンネルに料金が投稿されたら一旦完了