miso_soup3 Blog

主に ASP.NET 関連について書いています。

Lambda(SAM) に Datadog を導入したときのメモ

f:id:miso_soup3:20201126120602p:plain
Trace Serverless Functions より

全ては Datadog の公式ドキュメントに記載されている通りですが、引っかかったところをメモします。

導入

サーバーレスモニタリングのインストール の通りに行いました。

1. AWS インテグレーションをインストール
  • 「自動:CloudFormation」 にて、CloudFormation で作成するときは、
    • 作成先のリージョンが意図したリージョンであるか確認します(任意)。
    • 作成ページの最後のチェックボックス「The following resource(s) require capabilities: [AWS::CloudFormation::Stack]」にチェックするのを忘れないようにします。

Update the Datadog AWS インテグレーション タイルを、CloudFormation のスタック作成に使用した IAM ロール名とアカウント ID で更新します。

このとき、ロール名などの入力が正しいかどうかに注意します。また、Datadog の UI の関係により、キーの入力途中のタイミングで検証が行われる可能性があります。上手くいかない時はコピーアンドペーストを利用して、良いタイミングで検証してもらえるよう頑張ります。失敗したときは、作成した CloudFormation から丸ごと削除します。AWS External ID が一致しないときは編集もしてみたのですが、なんだかんだで 4,5回やり直しました😅

2. Datadog Forwarder のインストール

Note: Skip this step if you already have the Forwarder function installed as part of the AWS integration CloudFormation Stack. https://docs.datadoghq.com/serverless/installation/

と書いてあるように、1 の手順の CloudFormation でインストールされているのでここはスキップします。

1 の手順の CloudFormation を確認すると、ネストされた子の CloudFormation があり、Role を作るものと Datadog Forwarder を作るものが確認できました。その作成されたリソースを見ると「Forwarder」という名前の AWS::Lambda::Function が確認できます。これが Datadog Forwarder であり、CloudWatch Logs などのログを Datadog に送信しているものと思われます。

3. アプリケーションのインスツルメンテーション

Lambda に Datadog を設定するステップです。

Lambda は SAM で作っているので、「AWS SAM」の方法でトライしました。そしてエラーが解決できなかったので結局は「Custom」にある Lambda Layer を使う方法で導入しました。お手軽だったので今後も Lambda Layer の方法にすると思います。

AWS SAM」でつまづいた部分は以下の通り↓

Error message: ‘logGroupNamePrefix’ failed to satisfy constraint… Datadog Serverless Macro

とあるように「logGroupNamePrefix」というエラーが発生しました。ドキュメントには対応策が記載されていますが、それでも解決できませんでした。

Lambda Layer の方法で気をつけるのは以下の通りです。

The minor version of the datadog-lambda package always matches the layer version. E.g., datadog-lambda v0.5.0 matches the content of layer version 5.

The available RUNTIME options are Python27, Python36, Python37, and Python38. For VERSION, see the latest release. For example: Instrumenting Python Applications

とあるように、pip install する datadog-lambda のバージョン0.5.05と、arn:aws:lambda:<AWS_REGION>:464622532012:layer:Datadog-<RUNTIME>:<VERSION> の VERSION の数字は同じにします。

また、

Optionally add a service and env tag with appropriate values to your function.

とある部分は、環境変数ではなく Lambda のタグを指しています。

Lambda をデプロイするユーザーに lambda:GetLayerVersion の権限を追加します。でないと以下のようにエラーが発生します。

hogehoge is not authorized to perform:lambda:GetLayerVersion on resource:arn:aws:lambda:ap-northeast-1:464622532012:layer:Datadog-Python**:** (Service: AWSLambdaInternal;Status Code: 403; Error Code: AccessDeniedException;Request ID: xxx; Proxy: null) 

ログとトレースの接続

Connecting Python Logs and Traces この方法に沿って、ログとトレースの接続を行いました。

このとき、出力された CloudWatch Logs のメッセージを確認すると、dd.env dd.version の部分が出力されていませんでした。Lambda の環境変数DD_SERVICE DD_VERSION DD_ENV を追加することで、出力されるようになり、結果 Datadog 上でログとトレースの接続が行えるようになりました。Lambda のタグと内容が重複しますが、どちらかのみの定義で済むかどうかは分かっていません。

最終的な template.yaml は以下の通りとなりました。

  MyLambda:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: 省略
      Handler: datadog_lambda.handler.handler
      ...省略
      Environment:
        Variables:
          DD_LAMBDA_HANDLER: hogehoge.lambda_handler
          DD_TRACE_ENABLED: true
          DD_FLUSH_TO_LOG: true
          DD_SERVICE: Datadog APM のためのサービス名
          DD_VERSION: 1
          DD_ENV: dev
      Layers:
        - arn:aws:lambda:<AWS_REGION>:464622532012:layer:Datadog-<RUNTIME>:<VERSION> ←書き換える
      Tags:
        env: dev
        service: Datadog APM のためのサービス名

カスタムメトリクスの送信

カスタムメトリクス

の通りに行いました。

Datadog Lambda ライブラリ を使用して送信する場合、カスタムメトリクスにタグを付ける必要があります。 カスタムメトリクス

↑これは、下↓の操作の部分のことを示しています。(タグという名前だけだとどのタグのことか紛らわしい…)

Datadog のページにアクセスし、Distributions の通りにメトリクス収集の定義を行いました。p99の値と環境ごとでみたいので、p99 env のタグを設定しました。このタグの数は、後述する課金に影響します。(なので無駄なタグは設定しない方がいいかな)

お値段を把握する

以上のように、Lambda に Datadog APM の導入と カスタムメトリクスの送信に成功しました。ところで、お値段はどれくらいになるんでしょう? 結論としては、月額$5で、あとは使用量次第で増えていきます。

最初、以下の表記をみて「えっ $31/月 もかかるの?」と勘違いしました。

STARTING AT $ 31 Per host, per month* 料金プラン | Datadog

Lambda 1つは1つのホストとみられてしまうから$31/月かかる…?と思いましたがそうではありませんでした。

Pro および Enterprise プランには、請求対象の関数ごとに 150,000 件の Indexed Span と 5 個のカスタムメトリクスが含まれます。サーバーレス APM の請求は、Datadog APM サービスに送信された Indexed Span のうち、バンドルされた数量を超過した総数に基づき、月末に課金されます。サーバーレス使用時は、請求可能な APM ホストはありません。 Datadog

というように、「サーバーレス使用時は、請求可能な APM ホストはありません。」との記載があるので、「STARTING AT $ 31 Per host, per month*」は適用されません。

また、以下のようにサーバーレスの場合の料金が記載されています。

ケース 6: Lambda 関数と Indexed Span Lambda 関数を 1 か月間毎時間継続して呼び出し、2,000 万件の Indexed Span を送信。 f:id:miso_soup3:20201126120346p:plain APM 料金

この「月額5ドル」というのは、以下の Serverless の料金ページの部分から。

STARTING AT $ 5 Per function, per month* 料金プラン | Datadog

つまり、1つの Lambda で Datadog APM を使う場合は以下のような費用となると認識しました。

分散型トレーシング

複数の Lambda を運用していますが、それらを一貫してトレースで見られるようにしたいと思いました。ここで使えるのが、分散型トレーシング です。

最初自分は何も考えずに Datadog APM だけを選択していましたが、しかしそれでは不十分なようで、AWS のリソースを挟む場合は、AWS X-Ray と Datadog APM の両方が必要なようです。料金も増える模様💸(まあそうですよね。Datadog APM だけで何か頑張っているのかと勘違いしてました)

Datadog のサポデから以下の回答をもらいました。3つのドキュメントが参考になりそうです。

S3, SQS and Dynamo would need to be traced with AWS X-Ray, and the Lambdas with Datadog's APM. These can then be combined to produce the full trace.

Here are some more details on that: https://docs.datadoghq.com/tracing/setup_overview/serverless_functions/?tab=nodejs#augment-aws-x-ray-tracing-with-datadog-apm

Specifically this portion may be of interest: https://docs.datadoghq.com/tracing/setup_overview/serverless_functions/?tab=nodejs#tracing-in-a-serverless-first-environment

For more details on X-Ray tracing with Datadog: https://docs.datadoghq.com/tracing/guide/serverless_enable_aws_xray/?tab=nodejs

問題の沼から抜け出す方法

コードを書いていてハマることはよくあるのですが、とある方法を行うようにしてから、問題解決までの時間が短くなったと感じました。その方法を書きます。とはいっても、どれもよく言われることだと思います。

すぐに試せる環境を用意しておく

疑問に思ったときのために、1分以内にコードを書いて動かせる環境を立ち上げられるようにします。「〜 Playground」でググると言語毎にたくさんのツールを見つけられます。なるべく早く、自分が億劫と思わずに済む簡単な方法を見つけます。

例えば、自分は RxJS を試すために stackblitz.com のサイトをブックマークしています。RxJS の他に Angular、TypeScript も試せます。

f:id:miso_soup3:20200619171714p:plain

この方法を身につけるまでは、既存のプロジェクト(たとえば業務のプロジェクト)の中でコードを書いてデバッグしていたり、空のプロジェクトを動かしていたりしていました。それですと複数の要因があるので、本当に知りたい挙動を確かめられないことがあります。また、実行するまでの時間が遅いです。しかし、Playground のサイトでは瞬時に実行できますし、書いたコードの共有も簡単です。「次にこうするとどうなるんだろう?」という次の疑問もすぐに解決できます。書いたコードの URL をメモしておけば、いつか思い出したときに探し出すのも簡単です。他人に共有すれば、「それってこういうときどうなる?」という会話も生まれてさらに深堀できます。そして実行した後でようやく、公式ドキュメントの内容をちゃんと理解できます。

思い返せば、すごいエンジニアは「これってどうなりますか?」と話しかけた後、ものの数秒でコード例を提示していた気がします。

重要なのは、疑問に思ってから実行できるまでの時間を短くし、億劫にならないことだと思います。

作業ログの書き方を見直す

もし何か問題にハマってしまったときは、作業ログの書き方を変えます。試したこと、成功したこと、失敗したことを、全て書くようにします。

自分がハマっていたときの作業ログを思い出すと、単語だけを書いていたり、次にやること・調べたサイトのリンクを貼っていただけでした。解決できないのでテックリードに相談すると、「やったことは全て書いた方がいい」「条件を洗い出し、成功と失敗も全て書く」という旨のアドバイスをもらいました。このとき自分は「成功したことも書くのか」と思いました。その後、作業ログを Slack の自分宛ての DM から、Google Documents に変えました。成功したこと、考えたこと、疑問に思ったこと、書いたコードをストーリー仕立てで文章化しました。このときの気分はまるで、ゲームによくある日記を書く博士のようで、楽しい時間でした。やってからものの数十分で、成功する状態から失敗する状態の境界線を見つけられました。これは所謂ラバーダッキングの手法かと思います。それまでは、自分の作業ログの形が変だとは気付けませんでした。

作業ログについては、ひげぽんさんの 第9回 ログのすすめ:継続は力なり―大器晩成エンジニアを目指して|gihyo.jp … 技術評論社 の記事が好きです。

ミニマムプロジェクトを作成する

自分が触っているフレームワークのミニマムなプロジェクトはすぐに作成できるようにしておきます。Docker, docker-compose, Angular, .NET Core などなどいろいろなフレームワークがありますが、そのミニマムな環境を用意することに躊躇しないことです。クロスプラットフォームであれば、Mac, Windows, Linux のどの環境でも作成します。思えば自分は、開発マシン以外の環境でミニマムプロジェクトを作成するのを避けていて、Google 上で解決方法を探していたのですが、すごいエンジニアは数分でミニマムプロジェクトを用意して解決していました。