はじめに

私が開発運用を担当している社内サービスの一つに「MSPの監視業務の一次対応を自動化する」システムがあります。
ある条件に則ったPagerDutyインシデント(以下インシデント)が登録されると事前に設定された一次対応シナリオを実行するというもので、PagerDutyを活用する当社の監視業務の一翼を担っています。

この社内サービスではMSPをはじめとしたインシデントの閲覧者に対する補足情報として PagerDutyのNotes (以下ノート)を利用しています。
サービスの処理内容や処理結果を随時ノートに記録し、あとから参照できるようになっています。

ノートはたいへん便利ですが、より端的な情報を伝えることができるような機能はないかと探したところ「カスタムフィールド」という機能が今年(2023年)リリースされたので調べた内容をまとめます。

カスタムフィールドとは

公式ドキュメントより。

カスタムフィールドを使用すると、インシデントのライフサイクルを通じて、PagerDutyインシデントを重要かつ有用なメタデータで豊かにすることができます。お好みのデータを柔軟に定義し、インシデントが表示する情報を標準化することができます。また、この機能により、複数の既存システムからデータを集約し、インシデント対応時にその情報を入力することができます。

仕様をまとめると以下のとおり。

  • 1つのカスタムフィールド =「フィールド名(name)」と「フィールド値(value)」のペア
  • 追加したフィールドはPagerDutyアカウント単位で共通して利用できる
    • フィールドの追加・編集・削除にはAdminもしくはAccount Owner権限が必要
  • インシデントごとに各フィールドの値を設定できる
    • 値の編集はUser権限でも可能
  • 9種類のフィールドのデータ型が用意されている(後述)

なおカスタムフィールドが利用できる料金プランは Business および Digital Operations です。

●ノートとの違い

ノート (Notes) カスタムフィールド (Custom Fields)
追加できる数 2,000件/1インシデント 15フィールド/1アカウント
1件あたり最大文字数 65,535文字 200文字 (各フィールドごと)
データ型 なし – Text
– Single select
– Multiple select
– Tag
– URL
– Checkbox
– Datetime
– Decimal
– Integer
※詳細はドキュメント参照
表示される場所 – インシデント詳細ページ (右側)
– インシデント詳細 > Timeline
– インシデント詳細ページ
必要な権限 正確な情報は見つけられなかったものの基本的な権限であればUser以上、高度な権限であればResponder以上あれば追加できると思います ・フィールドの追加/編集/削除
 → AdminもしくはAccount Owner
・フィールドの表示・値の編集
 → インシデントの表示・編集できるユーザーであれば可能(おそらくノートと同じ)
編集・削除 追加後に編集・削除できない フィールド値を設定後に編集・削除可能
その他特徴 ノート内のURLはリンクに自動変換される

インシデント対応者に対して追加や補足となる情報を提供するという機能は共通していますが、

ノート
→ インシデント詳細のTimelineタブでも表示できることから「時系列を意識したメモを追加・掲載する場所」
カスタムフィールド
→ 様々なデータ型が用意されていることから「連携する他のシステムから標準化されたデータ(情報)を掲載する場所」

といった特徴があるようです。

API

REST APIが用意されており、大きく「カスタムフィールド自体の追加・編集・削除」と「各インシデントに設定されたカスタムフィールドの値の取得・編集」に分かれます。

●カスタムフィールドの追加・編集・削除

API Reference へのリンクを載せただけですが、、

フィールド本体と、リスト型フィールドのオプションの取得・追加・編集・削除と、一般的なCRUDが用意されています。
また上述のとおり追加や編集するにはAdmin以上の権限を持つユーザーが発行したAPIキーが必要です。
カスタムフィールドの編集や削除は機能の主旨からして頻繁に行われるものではないと思いますし、アカウント全体に影響するため慎重を要します。
可能であればPagerDutyのコンソール画面で確認しながら実施するのが安全かと思います。

●各インシデントに設定されたカスタムフィールドの値の取得・編集

インシデントごとに設定されたフィールド値(value)は取得・編集の2種類が用意されており、カスタムフィールド本体の操作よりもこちらがメインで利用するAPIになると思います。
上記リンク先のリファレンスにあるサンプルコードのとおりに実行すれば簡単に確認できます。

取得は “Get an incident” でも可能

インシデントのデータを取得する “Get an incident” というAPIがあります。
プログラム上では最も利用されるAPIの一つではないかと思いますが、クエリパラメータのオプションを指定することで取得したインシデントデータ内にカスタムフィールドも含めることができます。

# クエリパラメータ `include[]` で "custom_fields" を含める
https://api.pagerduty.com/incidents/?include[]=custom_fields

少し長いですが以下のようなレスポンスが返ってきます(値は適当に変更しています)
下から2番目に "custom_fields" があります。

{
    "incident": {
        "title": "xxxx",
        "incident_number": 9999999,
        "id": "QXXXXXXXXXXXXX",
        "summary": "xxxx",
        "self": "https://api.pagerduty.com/incidents/QXXXXXXXXXXXXX",
        "incidents_responders": [],
        "status": "resolved",
        "escalation_policy": {
            "html_url": "https://mspdev.pagerduty.com/escalation_policies/PXXXXXX",
            "id": "PXBS8UU",
            "self": "https://api.pagerduty.com/escalation_policies/PXXXXXX",
            "summary": "Default",
            "type": "escalation_policy_reference"
        },
        "teams": [],
        "resolved_at": "2023-12-00T00:02:00Z",
        "type": "incident",
        "resolve_reason": null,
        "priority": null,
        "updated_at": "2023-12-00T00:01:00Z",
        "created_at": "2023-12-00T00:00:00Z",
        "html_url": "https://mspdev.pagerduty.com/incidents/QXXXXXXXXXXXXX",
        "impacted_services": [
            {
                "html_url": "https://mspdev.pagerduty.com/service-directory/PZZZZZZ",
                "id": "PPOPWIV",
                "self": "https://api.pagerduty.com/services/PZZZZZZ",
                "summary": "xxxx",
                "type": "service_reference"
            }
        ],
        "basic_alert_grouping": null,
        "assigned_via": "escalation_policy",
        "pending_actions": [],
        "last_status_change_at": "2023-12-00T00:00:00Z",
        "assignments": [],
        "first_trigger_log_entry": {
            "html_url": "https://mspdev.pagerduty.com/incidents/QXXXXXXXXXXXXX/log_entries/RXXXXXXXXXXXXXXXXXXXXXXXXX",
            "id": "RXXXXXXXXXXXXXXXXXXXXXXXXX",
            "self": "https://api.pagerduty.com/log_entries/RXXXXXXXXXXXXXXXXXXXXXXXXX",
            "summary": "Triggered through the website.",
            "type": "trigger_log_entry_reference"
        },
        "responder_requests": [],
        "last_status_change_by": {
            "html_url": "https://mspdev.pagerduty.com/users/PXXXXXX",
            "id": "PXXXXXX",
            "self": "https://api.pagerduty.com/users/PYYYYYY",
            "summary": "XXXXXX",
            "type": "user_reference"
        },
        "urgency": "high",
        "is_mergeable": true,
        "acknowledgements": [],
        "subscriber_requests": [],
        "service": {
            "html_url": "https://mspdev.pagerduty.com/service-directory/PXXXXXX",
            "id": "PXXXXXX",
            "self": "https://api.pagerduty.com/services/PXXXXXX",
            "summary": "xxxx",
            "type": "service_reference"
        },
        "description": "xxxx",
        "incident_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "alert_grouping": null,
        "custom_fields": [
            {
                "data_type": "string",
                "description": "会社の名前",
                "display_name": "会社名",
                "field_type": "single_value",
                "id": "PXXXXXX",
                "name": "name",
                "type": "field_value",
                "value": "iret, inc."
            },
            {
                "data_type": "url",
                "description": null,
                "display_name": "ホームページURL",
                "field_type": "single_value",
                "id": "PXXXXXX",
                "name": "website_url",
                "type": "field_value",
                "value": "https://iret.co.jp"
            }
        ],
        "alert_counts": {
            "all": 0,
            "resolved": 0,
            "triggered": 0
        }
    }
}

このようにしておけば後からカスタムフィールドが必要になってもこのデータから抜き出せるのでリクエストを節約できます。
逆にカスタムフィールドの値しかいらないのに “Get an incident” してしまうと不要なデータもついてくるので控えたほうが良いでしょう。

まとめ

カスタムフィールドを使うとPagerDutyアカウント全体に共通する項目でありつつ、インシデントごとに個別のデータ(値)を載せられるようになることがわかりました。
仕様的には他のサービスから標準化されたデータを掲載することが意識されているようですが、インシデント詳細ページの中央あたりと目立つ場所に表示されるので、他サービスとの連携はなくてもインシデントの対応者に役立つ情報を載せるような活用をしていきたいと思います。