はじめに
これは KWC Advent Calendar 2022 の記事です。
はじめまして、KWCに新卒で入社して、バックエンドエンジニアをしているユウスケと申します。
テックブログは初めてです!
*紹介*
昨日の記事で運用中のAPIでエラーが出たときどうやって検知してSlackに通知しよう 〜概要編〜 の続きとなりますので、先に概要編を読むことをおすすめします!
目次
概要編をサクッとおさらい
今回やりたいことは、エラー出た際にSlackへログを通知することです。
Slackへのメッセージ送信の機能の実装場所はプログラム内部に組み込むか、外部に実装する方法の2つあります。詳しくは概要編で!
今回は、外部に実装する方法を話していきます!
システムの構成
システム構成図は以下のようになります。
- APIのログはCloudWatch Logsに溜まっていきます
- CloudWatch Logsでは、
Subscription filter
を使い特定の文字が含まれるログを検知します- 今回は
_SLACK_NOTIFY
をトリガーにしています
- 今回は
- 特定の文字があった場合は、そのログがeventとしてLambdaへ送られるようにしています
- Lambdaの中でeventの中身を見て、必要な処理をしてからSlackにメッセージを送信します
いざ実装へ
サブスクリプションフィルターで検知するログの作成
サブスクリプションフィルターで検知する_SLACK_NOTIFY
を含んだログを出力します。
今回は下のようなログを出力します。
2022/12/12 11:12:44 ERROR_SLACK_NOTIFY: エラーメッセージ
サブスクリプションフィルターの設定
Cloud Watchのコンソール画面から、設定したいロググループへ移動して、サブスクリプションフィルターの設定を行います。
Lambda サブスクリプションフィルターを作成
では以下の情報を入力します。
送信先を選択
- 送信したいLambdaを選択します
(作成済みのLambdaが表示されます)
ログ形式とフィルターを設定
項目 | 内容 |
---|---|
ログの形式 | その他 |
フィルターパターン | _SLACK_NOTIFY |
フィルター名 | 任意の名前 |
これでCloud Watch Logsへ_SLACK_NOTIFY
のログが出力された時、サブスクリプションフィルターが起動して、Lambdaが起動します。
Slackへメッセージ送信
メッセージ取り出し
サブスクリプションフィルターから次のようなevent
がLambdaへ渡されます。
{
"owner": "<aws account>",
"logGroup": "XXXXXXXXXXXXXXXX",
"logStream": "XXXXXXXXXXXXXXX",
"subscriptionFilters": [
"設定したフィルター名"
],
"messageType": "DATA_MESSAGE",
"logEvents": [
{
"id": "3720074778603986400000000000000",
"timestamp": 1668139223818,
"message": "ERROR_SLACK_NOTIFY: エラーメッセージ"
}
]
}
次のコードはevent
からログを取り出している例です。
func HandleRequest(ctx context.Context, event events.CloudwatchLogsEvent) (string, error) {
e, _ := event.AWSLogs.Parse() // サブスクリプションフィルターから渡されたeventをパース
message := e.LogEvents[0].Message
fmt.Println(message)
return "", nil
}
全体のコード(APIのログを取り出す例)
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
func HandleRequest(ctx context.Context, event events.CloudwatchLogsEvent) (string, error) {
e, _ := event.AWSLogs.Parse()
message := e.LogEvents[0].Message
fmt.Println(message)
return "", nil
}
func main() {
lambda.Start(HandleRequest)
}
Slackへメッセージを送る関数作成
SlackのSDKを使い、Slackへメッセージを送信します。
func SendMessage(message string) {
c := slack.New(os.Getenv("SLACK_TOKEN"))
_, _, err := c.PostMessage(os.Getenv("POST_CHANNEL"), slack.MsgOptionBlocks(
&slack.SectionBlock{
Type: slack.MBTSection,
Text: &slack.TextBlockObject{
Type: "mrkdwn",
Text: message,
},
},
))
if err != nil {
panic(err)
}
}
この関数の引数に、イベントから取得したログを渡してSlackへ通知することができます。
完成したコード
package main
import (
"context"
"os"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/slack-go/slack"
)
func SendMessage(message string) {
c := slack.New(os.Getenv("SLACK_TOKEN"))
_, _, err := c.PostMessage(os.Getenv("POST_CHANNEL"), slack.MsgOptionBlocks(
&slack.SectionBlock{
Type: slack.MBTSection,
Text: &slack.TextBlockObject{
Type: "mrkdwn",
Text: message,
},
},
))
if err != nil {
panic(err)
}
}
func HandleRequest(ctx context.Context, event events.CloudwatchLogsEvent) (string, error) {
e, _ := event.AWSLogs.Parse()
message := e.LogEvents[0].Message
SendMessage(message)
return "", nil
}
func main() {
lambda.Start(HandleRequest)
}
まとめ
アプリが出した特定のログを検知してSlackへ通知する方法を紹介しました。
これは一例なので環境にあった実装を試してみてください!
宣伝
KWC Advent Calendar 2022はまだまだ、続きますので良ければ他の記事もご覧ください!!