Stripe では、各種イベントを Webhook としてぶん投げてくれる仕組みがあります。
以前、その Webhook を Serverless Framework 使って API Gateway + Lambda で処理する記事書きました。
Stripe の Webhook を API Gateway で受け取って Lambda で処理する
それを応用して、Event Type ごとに CloudWatch のカスタムメトリクスに記録しておくとテンションあがるかなーと思って、こんなん書いてみました。
Stripe の Event を CloudWatch custom metrics に記録
Lambda で Webhook 受け取って CloudWatch にカスタムメトリクス登録
Lambda は node.js 6.10 でやりましょう。
ソースはこんな感じです。
'use strict';
module.exports.incoming = (event, context, callback) => {
const stripe = require('stripe')(process.env.STRIPE_API_KEY); // eslint-disable-line
let response = {
statusCode: 200,
body: ''
};
try {
// Parse Stripe Event
const jsonData = JSON.parse(event.body); // https://stripe.com/docs/api#event_object
// Verify the event by fetching it from Stripe
console.log("Stripe Event: %j", jsonData); // eslint-disable-line
stripe.events.retrieve(jsonData.id, (err, stripeEvent) => {
const AWS = require('aws-sdk');
const cloudwatch = new AWS.CloudWatch({apiVersion: '2010-08-01'});
const eventType = stripeEvent.type ? stripeEvent.type : '';
const params = {
Namespace: process.env.NAMESPACE,
MetricData: [
{
MetricName: eventType,
Dimensions: [{
Name: process.env.DIMENSION,
Value: process.env.STAGE
}],
Timestamp: new Date,
Unit: 'Count',
Value: '1'
}
]
};
cloudwatch.putMetricData(params, (err) => {
if (err) {
console.log('PutMetricData Error: %j', err); // eslint-disable-line
}
response.body = JSON.stringify({
message: 'Stripe webhook incoming!',
stage: process.env.STAGE,
eventType: eventType
});
return callback(null,response);
});
});
} catch (err) {
response.statusCode = 501;
response.body = JSON.stringify(err);
callback(err,response);
}
};
stripe.events.retrieve() で、送られてきたデータが本当に Stripe からのデータかどうかをチェックして、問題なければ CloudWatch のカスタムメトリクスに登録してる感じすね。
Serverless framework で API Gateway の endpoint 用意
API GateWay + Lambda の設定は苦行でしたが、Serverless framework を使用することで途端に簡単になりました。
こんな感じの serverless.yml を用意してやればいいです。
service: put-stripe-event-to-custom-metrics
custom:
stage: ${opt:stage, self:provider.stage}
logRetentionInDays:
test: "14" # stage[test]は14日
live: "90" # stage[live]は90日
default: "3" # stageが見つからなかったらこれにfallbackするために設定
stripeAPIKey:
test: "__STRIPE_TEST_API_SECRETKEY_HERE___" # stage[test]用の Stripe API Key
live: "__STRIPE_LIVE_API_SECRETKEY_HERE___" # stage[live]用の Stripe API Key
default: "__STRIPE_TEST_API_SECRETKEY_HERE___" # stageが見つからなかったらこれにfallbackするために設定
provider:
name: aws
runtime: nodejs6.10
stage: test
region: us-east-1
memorySize: 128
timeout: 60
iamRoleStatements:
- Effect: Allow
Action:
- cloudwatch:PutMetricData
Resource: "*"
environment:
STAGE: ${self:custom.stage}
# you can add packaging information here
package:
include:
- node_modules/**
exclude:
- .git/**
- package.json
functions:
incoming:
handler: handler.incoming
events:
- http:
path: stripe/incoming
method: post
environment:
NAMESPACE: "___SERVICENAME__HERE__"
DIMENSION: "Stripe"
STRIPE_API_KEY: ${self:custom.stripeAPIKey.${self:custom.stage}, self:custom.stripeAPIKey.default}
resources:
Resources:
IncomingLogGroup:
Properties:
RetentionInDays: ${self:custom.logRetentionInDays.${self:custom.stage}, self:custom.logRetentionInDays.default}
serverless でのデフォルトに従うと、開発環境の stage は dev
になりますが、ここは Stripe のお作法に従って開発環境は test
、本番環境は live
としましょうか。
environment として、以下の 4つを渡してますので、これを Lambda 内部では process.env.{environment name}
で参照できます。
- STAGE
- NAMESPACE
- DIMENSION
- STRIPE_API_KEY
サンプルなので Stripe API KEY もそのまま渡してますが、必要なら暗号化するなりしてください。
environment
の STRIPE_API_KEY
とか、Resources
のロググループの期限とかは stage によって切り替えています。
この辺は @sawanoboly の以下の記事が参考になります。
Serverless Frameworkで、AWS Lambda function用に作られるCloudWatch Logsの期限を指定する
Deploy !
前準備
deploy したいところですが npm パッケージ stripe
を内部で使用しているので、まずは npm install
で stripe パッケージを取ってきましょう。
$ npm install stripe
いよいよデプロイ
もう、何も恐れる必要はありません。deploy してあげてください。
$ serverless deploy -v
:
Serverless: Stack update finished...
Service Information
service: put-stripe-event-to-custom-metrics
stage: test
region: us-east-1
api keys:
None
endpoints:
POST - https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/test/stripe/incoming
functions:
incoming: put-stripe-event-to-custom-metrics-test-incoming
Stack Outputs
ServiceEndpoint: https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/test
ServerlessDeploymentBucketName: put-stripe-event-to-cust-serverlessdeploymentbuck-xxxxxxxxxxxx
IncomingLambdaFunctionQualifiedArn: arn:aws:lambda:us-east-1:000000000000:function:put-stripe-event-to-custom-metrics-test-incoming:1
endpoint (https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/test/stripe/incoming)
に表示される URL が API Gateway の endpoint です。
これを Stripe の Webhook 登録画面 で登録してあげればオッケーです。
本番環境( live )にデプロイする場合は、以下の感じで
$ serverless deploy -v -s live
やったー、CloudWatch のカスタムメトリクスに登録されてるよ!
これで、Stripe からのチャリンチャリンが CloudWatch で確認できるようになりました。
可視化大事ですね。
現場からは以上です。