Mailgunを使い始めました。すでにDatadogを利用しています。
Mailgunのメトリクスを眺めてると、これどうにかDatadogに流し込んで、監視できねーかなと。もやっと眺めてたら、このあたり接続したら、いい感じになりそうです。
- Mailgunは、 StatsというAPIから、HTTP GETで、最小1時間刻みの件数を取得できます
- Datadogは、独自のメトリクスをAPIからHTTP POSTで投入できます
- Datadogは、メトリクスがいつもと違う動きをした時に通知してくれるような監視を構築できます
- AWS Lambdaは、CloudWatch Eventで、cron式などでスケジュール実行することができます
情報収集
- Mailgunのドメイン名。
- 情報収集したいドメイン名。Stats APIは、ドメイン単位で集計されてるので。
- MailgunのAPIキー。
- Stats APIから情報収集するのに使います。
- https://mailgun.com/app/dashboard にドーンと出てる、プライベートAPIキー。
- DatadogのAPIキー
- Datadogにメトリクスをpostするために使います。
- https://app.datadoghq.com/account/settings#api からAPIキーを。
Lambdaファンクション
- ランタイムはPython3.x
- 環境変数3個。さきほど収集した情報を、以下の環境変数にそれぞれ設定します。
- MAILGUN_DOMAIN
- MAILGUN_API_KEY
- DATADOG_API_KEY
- 実行時間は1分あれば大丈夫。実績13秒前後。
- メモリは128MBで大丈夫。実績25MB程度。
- 起動トリガーはCloudWathc Eventの
rate(1 hour)
ファンクションのコードは以下。Lambdaのインライン編集で管理したいので、標準ライブラリ縛りで書いてます。
import os
import urllib.request
import urllib.parse
import base64
import json
import time
now = time.time()
MAILGUN_DOMAIN=os.environ["MAILGUN_DOMAIN"]
MAILGUN_API_KEY=os.environ["MAILGUN_API_KEY"]
DATADOG_API_KEY=os.environ["DATADOG_API_KEY"]
def get_mailgun_stats():
# https://documentation.mailgun.com/en/latest/api-stats.html
url = "https://api.mailgun.net/v3/" + MAILGUN_DOMAIN + "/stats/total?event=accepted&event=delivered&event=failed&duration=1h"
# MailgunのAPIはBasic認証がかかっている。APIキーがBasic認証キー。
basic_auth_parm = 'api:' + MAILGUN_API_KEY
basic_user_and_pasword = base64.b64encode(basic_auth_parm.encode('utf-8'))
request = urllib.request.Request(url, method="GET", headers={"Authorization": "Basic " + basic_user_and_pasword.decode('utf-8')})
with urllib.request.urlopen(request) as response:
return json.loads(response.read().decode('utf-8'))
def post_datadog_metrics(name, value):
# https://docs.datadoghq.com/ja/api/?lang=console#metrics-post
url = "https://api.datadoghq.com/api/v1/series?api_key=" + DATADOG_API_KEY
method = "POST"
headers = {"Content-Type" : "application/json"}
obj = {
"series": [
{
"metric":name,
"points":[
[now, value]
],
"type":"gauge",
"tags":"[mailgun-domain:" + MAILGUN_DOMAIN + "]"
}
]
}
json_data = json.dumps(obj).encode('utf-8')
request = urllib.request.Request(url, data=json_data, headers=headers, method="POST")
with urllib.request.urlopen(request) as response:
return response.read().decode("utf-8")
def lambda_handler(event, context):
mailgun_stats_full = get_mailgun_stats()
# failedが他と異なり階層が深くなってるためにこんな面倒に
mailgun_stats = {}
mailgun_stats['accepted'] = mailgun_stats_full['stats'][0]['accepted']
mailgun_stats['delivered'] = mailgun_stats_full['stats'][0]['delivered']
mailgun_stats['failed-permanent'] = mailgun_stats_full['stats'][0]['failed']['permanent']
mailgun_stats['failed-temporary'] = mailgun_stats_full['stats'][0]['failed']['temporary']
# ループ二階層は辞めたいけど動くから良いことにする
for metrics_category_name, metrics_kv in mailgun_stats.items():
for metrics_name, metrics_value in metrics_kv.items():
metrics_full_name = 'mailgun-' + metrics_category_name + '-' + metrics_name
post_datadog_metrics(metrics_full_name, metrics_value)
print('%s : %d' %(metrics_full_name, metrics_value))
Datadogダッシュボード
Datadogに以下の名前でメトリクスを投げます。ついでに mailgun-domain: ......
というタグも付けているので、必要ならご活用を。
- mailgun-accepted-incoming
- mailgun-accepted-outgoing
- mailgun-accepted-total
- mailgun-delivered-smtp
- mailgun-delivered-http
- mailgun-delivered-total
- mailgun-failed-permanent-suppress-bounce
- mailgun-failed-permanent-suppress-unsubscribe
- mailgun-failed-permanent-suppress-complaint
- mailgun-failed-permanent-bounce
- mailgun-failed-permanent-delayed-bounce
- mailgun-failed-permanent-total
- mailgun-failed-temporary-espblock
- mailgun-failed-temporary-total
Datadogのダッシュボードは、こんなグラフにして見えるようにしてます。
{
"requests": [
{
"q": "avg:mailgun_accepted_incoming{*}, avg:mailgun_accepted_outgoing{*}, avg:mailgun_delivered_http{*}, avg:mailgun_delivered_smtp{*}, avg:mailgun_failed_permanent_bounce{*}, avg:mailgun_failed_permanent_delayed_bounce{*}, avg:mailgun_failed_permanent_suppress_bounce{*}, avg:mailgun_failed_permanent_suppress_complaint{*}, avg:mailgun_failed_permanent_suppress_unsubscribe{*}, avg:mailgun_failed_temporary_total{*}",
"type": "bars",
"style": {
"palette": "dog_classic",
"type": "solid",
"width": "normal"
},
"conditional_formats": [],
"aggregator": "avg"
}
],
"viz": "timeseries",
"autoscale": true,
"status": "done"
}
Datadogで監視
メトリクスが来ているので、あとはいつもどおりに監視設定して、通知を受けられるようにするだけです。