まえがき
この記事はPagerDuty Advent Calendarの14日目になります。
AWS LambdaとPagerDuty APIを組み合わせて、
6ヶ月以上前のインシデントデータを取得する方法について解説します。
PagerDutyは、多くの監視ツールとのインテグレーションに対応しており、様々なインシデントの一括管理が可能なSaaSです。
PagerDutyには、日々のインシデントデータが集約されています。しかし、APIを介してこれらの過去のデータにアクセスしようとすると、特定の制限に直面することがあることが分かりました。
今回この制限に対応し過去のインシデントデータにアクセスするためのアプローチをご紹介したいと思います。
目次
①PagerDuty APIの解説
PagerDuty APIでは、インシデントの作成・更新・などの基本的な操作が可能です。
特に今回は過去のインシデントデータを取得するため、APIドキュメントのList incidentsを参照しました。
PagerDutyのAPIドキュメントの参照画像


上述の画像より、過去のインシデントデータを取得するためのリクエスト送信には、以下情報が必要とわかりました。
ヘッダー情報
・Authorization: APIキー
↳後述の手順内でAPIキーを作成します。
・Accept: application/vnd.pagerduty+json;version=2
・Content-Type: application/json
↳required(必須)と記載があります。
▼インシデントデータ取得の制限について
さらにAPI経由で過去のインシデントデータを参照する制限として、sinceとuntilパラメーターで指定すれば最大6ヶ月間、指定しない場合デフォルトで1ヶ月間が適用されるということが分かりました。

・since
↳ 検索したい日付範囲の開始日。最大範囲は6ヶ月で、デフォルトは1ヶ月です。
・until
↳ 検索したい日付範囲の終了日。最大範囲は6ヶ月、デフォルトは1ヶ月です。
つまりAPIリスクエスト送信時にsinceとuntilパラーメーターを使用することで、過去のインシデントデータを参照することが可能となります。
しかしsinceとuntilパラーメーターを使用しない場合は、過去1ヶ月間しか参照ができない仕様にも見受けられます。
以降のセクションでは、実際に環境構築しsinceとuntilパラーメーターの有無でどんなインシデントデータが取得可能なのか?検証をしていきます。
②環境構築
・Lambdaを作成します。
| 項目 | 値 |
|---|---|
| Lambda名 | pd-list-function(なんでもOK) |
| Runtime | Python3.11 |
| Architecture | x86_64 |
| Layer | 「※1の手順:」で作成して追加 |
※1の手順:
外部のPagerDuty APIにアクセスする必要があるためrequestsライブラリを使えるように、【1】ローカル環境で、zipファイルを作成する。を参照してレイヤーをLambda関数に適用します。
③PagerDuty APIを叩いて最新インシデントデータを取得(since~until未使用)
③-1 PagerDutyに存在する過去のインシデントデータを確認

サンプルのPagerDutyインシデントデータには、2023/12/1に2件。そして2022/4/11に1件ずつ存在していました。
今回は、2023/12/1に2件を取得します。上述で確認したPagerDutyのAPIドキュメント通りだと2022/4/11のデータは取得できないはずです。
よって期待の出力結果は以下になります。
期待値:
・「2023/12/1のインシデントデータ」のみ取得できる。
・「2022/4/11のインシデントデータ」は取得できない。
③-2 Lambda環境変数を更新する。
| 項目 | 値 |
|---|---|
| PAGERDUTY_API_KEY | 「※2の手順:」で作成して追加 |
| PAGERDUTY_ENDPOINT | https://api.pagerduty.com/incidents |
※2の手順:
・PagerDutyにログインし、上部タブ「Integrations」→「API Access Keys」をクリック。(以下の画像を参照)
・「Create New API Key」→「好きなAPIキー名」入力→「Create Key」をクリック。(以下の画像を参照)
・作成された画面にAPIキーの値が表示されるのでコピペして、Lambda環境変数へ貼り付け。



③-3 Lambda関数のコードにコピペして「test」から実行する。
※コードの詳細な解説は省略します。
import os
import json
import requests
import logging
## ロガーの設定
logger = logging.getLogger()
logger.setLevel(logging.INFO)
## 環境変数の設定
PAGERDUTY_API_KEY = os.environ["PAGERDUTY_API_KEY"]
PAGERDUTY_ENDPOINT = os.environ["PAGERDUTY_ENDPOINT"]
def lambda_handler(event, context):
try:
# PagerDutyから特定サービスIDの最近のインシデントを取得
incidents = fetch_recent_incidents()
# インシデント情報を指定された形式で整形
formatted_incidents = format_incidents(incidents)
formatted_output = "\n".join(formatted_incidents)
# 結果をログに出力
logger.info(formatted_output)
return {
"statusCode": 200,
"body": formatted_output,
"headers": {
"Content-Type": "text/plain"
}
}
except Exception as e:
logger.error(f"Error: {e}")
return {
"statusCode": 500,
"body": str(e),
"headers": {
"Content-Type": "text/plain"
}
}
def fetch_recent_incidents():
headers = {
"Authorization": f"Token token={PAGERDUTY_API_KEY}",
"Accept": "application/vnd.pagerduty+json;version=2",
"Content-Type": "application/json"
}
params = {
"statuses[]": ["resolved"],
"limit": 10
}
response = requests.get(PAGERDUTY_ENDPOINT, headers=headers, params=params)
response.raise_for_status()
return response.json().get("incidents", [])
def format_incidents(incidents):
formatted_data = []
for index, incident in enumerate(incidents, start=1):
formatted_data.append(
f"\nNo:{index}\n"
f"Title: {incident['title']}\n"
f"Created At: {incident['created_at']}\n"
f"Status: {incident['status']}\n"
f"Service: {incident['service']['summary']}\n"
f"URL: {incident['html_url']}"
)
return formatted_data
実行結果:
期待どおり「2023/12/1のインシデントデータ」のみ取得できました。
No:1 Title: 2023-12-01_Example Incident-1 Created At: 2023-12-01T11:54:04Z Status: resolved Service: test URL: https://~省略 No:2 Title: 2023-12-01_Example Incident-2 Created At: 2023-12-01T11:54:04Z Status: resolved Service: test URL: https://~省略
④PagerDuty APIを叩いて過去インシデントデータを取得(since~until使用)
次にsince~untilで2022/4/11を参照するように何日後何日前計算機で計算。
2023/12/1から2022/4/11は599日前だったので、Lambda環境変数に渡して実行します。
Pythonコードのしていることはスクショのようなイメージです。
sinceとuntilを代入して特定日付まで遡ってデータ取得しています。

期待の出力結果は以下の通りです。
期待値:
・「2023/12/1のインシデントデータ」は取得できない。
・「2022/4/11のインシデントデータ」のみ取得できる。
④-1 Lambda環境変数を更新する。
| 項目 | 値 |
|---|---|
| PAGERDUTY_API_KEY | 前述手順で作成済 |
| PAGERDUTY_ENDPOINT | https://api.pagerduty.com/incidents |
| SINCE_DAYS_AGO | 600 |
| UNTIL_DAYS_AGO | 598 |
④-2 Lambda関数のコードにコピペして「test」から実行する。
※コードの詳細な解説は省略します。
import os
import json
import requests
import datetime
import logging
## ロガーの設定
logger = logging.getLogger()
logger.setLevel(logging.INFO)
## 環境変数の設定
PAGERDUTY_API_KEY = os.environ["PAGERDUTY_API_KEY"]
PAGERDUTY_ENDPOINT = os.environ["PAGERDUTY_ENDPOINT"]
UNTIL_DAYS_AGO = int(os.environ["UNTIL_DAYS_AGO"])
SINCE_DAYS_AGO = int(os.environ["SINCE_DAYS_AGO"])
def lambda_handler(event, context):
try:
# PagerDutyから特定期間内のインシデントを取得
incidents = fetch_incidents_for_period()
# インシデント情報を指定された形式で整形
formatted_incidents = format_incidents(incidents)
formatted_output = "\n".join(formatted_incidents)
# 結果をログに出力
logger.info(formatted_output)
return {
"statusCode": 200,
"body": formatted_output,
"headers": {
"Content-Type": "text/plain"
}
}
except Exception as e:
logger.error(f"Error: {e}")
return {
"statusCode": 500,
"body": str(e),
"headers": {
"Content-Type": "text/plain"
}
}
def fetch_incidents_for_period():
until_date = datetime.datetime.utcnow() - datetime.timedelta(days=UNTIL_DAYS_AGO)
since_date = until_date - datetime.timedelta(days=SINCE_DAYS_AGO)
# 最大範囲を6ヶ月(約180日)に制限
max_range = datetime.timedelta(days=180)
if since_date < until_date - max_range:
since_date = until_date - max_range
headers = {
"Authorization": f"Token token={PAGERDUTY_API_KEY}",
"Accept": "application/vnd.pagerduty+json;version=2",
"Content-Type": "application/json"
}
params = {
"statuses[]": ["resolved"],
"since": since_date.isoformat(),
"until": until_date.isoformat(),
"limit": 10
}
response = requests.get(PAGERDUTY_ENDPOINT, headers=headers, params=params)
response.raise_for_status()
return response.json().get("incidents", [])
def format_incidents(incidents):
formatted_data = []
for index, incident in enumerate(incidents, start=1):
formatted_data.append(
f"\nNo:{index}\n"
f"Title: {incident['title']}\n"
f"Created At: {incident['created_at']}\n"
f"Status: {incident['status']}\n"
f"Service: {incident['service']['summary']}\n"
f"URL: {incident['html_url']}"
)
return formatted_data
実行結果:
期待どおり「1年以上前のインシデントデータ」のみ取得できました。
No:1 Title: Example Incident Created At: 2022-04-11T03:01:57Z Status: resolved Service: geeks-kohei URL: https://~省略
⑤ まとめ
PagerDutyのAPIを利用し、通常は6ヶ月までの制限がある過去のインシデントデータの取得に成功しました。
sinceとuntilのパラメータを適切に設定することで、通常の制限を超えた期間のデータにもアクセスできることが分かりました。
日々のインシデントをPagerDutyで一括管理していると、6ヶ月以上過去のインシデントデータへを参照する場面は意外と多いのではないでしょうか。
今回まとめた内容がお役に立てば嬉しく感じます。
最後まで閲覧いただきありがとうございました。