LoginSignup
5
2

More than 5 years have passed since last update.

[stripe][AWS] Stripe の Event を CloudWatch custom metrics に記録

Last updated at Posted at 2017-06-13

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 でやりましょう。
ソースはこんな感じです。

handler.js
'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 を用意してやればいいです。

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 もそのまま渡してますが、必要なら暗号化するなりしてください。

environmentSTRIPE_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 のカスタムメトリクスに登録されてるよ!
Screen Shot 2017-06-13 at 17.17.25.png

これで、Stripe からのチャリンチャリンが CloudWatch で確認できるようになりました。
可視化大事ですね。

現場からは以上です。

5
2
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
5
2