You are currently viewing ワークフローツールn8nで超簡易的死活監視を構築してみました
  • 投稿カテゴリー:-- Web
  • 投稿の最終変更日:2021-07-24

前にオープンソースのワークフローツールであるn8nをDockerで簡単に構築するという記事を書きましたが、今回はその活用法の一つとして、簡易的なWebサイトの死活監視&Slack通知のツールとして使ってみたいと思います。

通常であれば、専用のツール環境を構築したり、小難しいスクリプトを書かなくてはいけませんが、今回の方法ではGUIでポチポチするだけでおおよそ動いてくれます。

下準備

まずは下準備です。大前提としてn8nは構築済みということで…。もしやってみたいけどまだ構築していないという場合は私の記事でも参考にしてもらえると幸いです。

さて、n8nは準備できたので、次にSlackに投稿するためのアクセストークンを取得します。今回は監視結果をSlackに送りたいのでSlackのトークンを取得しますが、メールで送信する場合や別のサービスを利用する場合はそれぞれの方法に合わせたトークンなりを用意しておいてください。

トークン取得は本題ではないのでサラッと行きます。

  1. SlackにログインしつつSlackAPIの管理画面にアクセスする。
  2. 右上の「Your Apps (作成されたアプリ)」→「Create an App (新しいアプリを作成する)」をクリックする。
  3. アプリの名称、ワークスペースを選択して「Create App」をクリックする。
  4. 作成したアプリの設定画面左側の「Basic Information (基本情報)」から「Add features and functionality (特徴と機能の追加)」内の「Permissions (権限)」を選択する。
  5. 「Add an OAuth Scope」のボタンをクリックして chat:writechat:write.customizeの権限を追加する。
  6. 画面左メニューの「App Home」で遷移した後、「Your App’s Presence in Slack (Slack へのログイン状態)」のEditボタンをクリックする。
  7. ボットの名前とユーザ名を入力してAddボタンをクリックする。
  8. 左側メニューの「OAuth & Permissions (OAuth & 権限)」をクリックする。
  9. 「Install App to Workspace」をクリックして、権限内容を確認したのち「許可する」をクリックして有効化する。
  10. アクセストークンが発行される。

上記の手順でアクセストークンを取得することができます。発効後再度確認したくなった場合は、左側メニューの「OAuth & Permissions (OAuth & 権限)」から確認することができます。子のトークンが外部に漏れると自由に投稿されてしまうので注意です。

これで下準備はできたのであとはn8nで設定していくだけです。

ワークフロー作成

準備ができたので、さっそくワークフローを作成していきます。今回の完成図は以下のような形です。

完成図

今回はn8nからHTTPリクエストを飛ばして想定通りのテキストが返ってくるかを確認して、想定通りなら何もしない。想定のデータが返ってこない場合はSlackに通知を飛ばす。というワークフローを作ってみます。

本記事では「右上のプラスボタンからノードを追加して矢印で繋げることでフローを作成する」のような基本的なn8nの操作は省略していきます。前回記事ではちょっと詳しめに書いているので、基本操作を把握していない方はご覧になってください。

1. 定期実行

まずはワークフローの開始地点を設定します。ワークフロー作成時にはデフォルトで「Start」というノードが登録されていますが、こちらは自分で動かしたときに「ここからはじまるよ」というノードです。今回は手動ではなく一定の時間で自動的に動いてほしいので、「Cron」のトリガーノードを追加します。

cron設定画面

今回は1時間に1度実行してみようと思いますので、ノードの設定から「Mode」は「Every Hour」で「Minute」は0で設定します。「Mode」は毎時以外にも毎分, 毎日, 毎週, カスタムもありますのでご自身の環境/要望に合わせて調整しててみてください。

2. HTTPリクエスト

次は監視のメイン部分となるHTTPリクエストです。リクエストするにはその名の通り「HTTP Request」ノードを選択します。設定画面が出てきたら、URL欄に監視したいURLを入力します。あとはレスポンスの形式に合わせて「Response Format」の項目を「JSON」や「String」などに設定します。

リクエスト設定画面

3. リクエスト結果で条件分岐

さてリクエストはできたので、取得した結果をもとに必要があれば通知を送ってみたいと思います。初見だと、ちょっと設定しにくいと思いますが、一回やってみるとかなりシンプルなので初回は頑張ってみてください。

条件分岐には「IF」ノードを使用します (もしTrue/Falseより多くの分岐がしたければ「Switch」ノードが使えます)。この条件分岐ノードで想定内のデータが取れていればOK。取れていなければNGでSlack通知に進むというようにフローを組めば大丈夫です。

実際に条件分岐ノードを設定してみようと思います。今回は2パターンを考えてみます。下記の設定をする前に一度フローを実行しておいてください。実行しておくことで下記の条件設定時に選択肢として各レスポンスデータを選択できるようになります。

Webページ向けレスポンスがHTML形式(String)

まずは単純にWebページに対してリクエストした場合です。この場合ではレスポンスで想定されるテキストが含まれているかで判定するのがいいと思います。今回はレスポンスで返ってくるHTML内に「Hello World」が含まれていれば正常という想定で設定してみます。

IF設定画面 HTML ver

これを設定するには、まず「IF」ノードの設定画面上の「Value1」で、前のノードから取得したHTMLデータを選択します。HTMLデータを選択するには、入力欄右にある歯車マークから「Add Expression」を選択し、そこから「Nodes」→「HTTP Request」→「Output Data」→「JSON」→「Data」を選択します。もし選択肢として出てこない場合は、フローを実行するかフロー自体がつながっているかを確認してみてください。

HTTPRequestの結果対象に指定している様子

「Value1」が選択できたら、「Operation」は「Contains」、「Value2」は調べたい文字列「Hello World」と入力します。

これでレスポンスデータに「Hello World」が含まれているか?の条件分岐ができるようになりました。

API的レスポンスがjson形式(JSON)

もう一つのパターンとしてはAPIへリクエストした場合でjson形式のレスポンスが返ってくる場合の設定方法です。こちらも基本的に想定されるデータと一致しているかで判定を行います。今回はシンプルにレスポンスとして下記のようなjsonが返ってくると想定します。

[
    {
        "Hello": "World"
    }
]

つまり、レスポンスデータ内の「Hello」項目が「World」で返ってくれば正常という判断になります。これをn8nで設定するには、まず「Value1」の項目に「Hello」。「Operation」の項目は「Equal」。そして「Value2」の項目は1つ前のHTTPリクエストの結果、つまり歯車マークから「Add Expression」を選んで「Nodes」→「HTTP Request」→「Output Data」→「JSON」→「Hello」を選択します。

IF設定画面 JSON ver

これで「Hello」項目が「World」で返ってくるか?の条件分岐ができるようになりました。

4. Slack通知

最後にSlack通知部分を作成します。通知を送るにはこれまた名前通りの「Slack」ノードを追加します。追加したノードは上記で作成した条件分岐ノードの「false」側につなげます。もし監視してOKの場合にも通知を贈りたい場合は別途「true」に設置することでOKパターンで通知を送ることもできます。今回は通知しないため「NoOp」ノードをつなげて明示的に何もしないようにしています。

「Slack」ノードを使用する前にAPI設定をしておく必要があります。これはノード設定画面の一番上の「Slack API」の鉛筆マークから設定することができます。

鉛筆マークを押した後の画面

APIの設定画面が表示されたらあとは適当な名前を付けて「Access Token」の項目に本記事初めに取得したSlackのアクセストークンを入力して完了です。ちなみにこの設定はほかのフローでも使いまわすことができ、使用したAPI設定は画面左のメニュー内「Credentials」から見ることができます。

Slack設定画面

APIの設定が終わったら「Slack」ノードの設定をしていきます。「Authentication」では「Access Token」を選択します。あとは投稿先のチャンネルを入力 (例: #notice-alert など)し、「Text」で通知したい内容を入力します。「Text」入力時欄の右側にある歯車マークから、他のノードの情報を持ってくることもできます。今回の例では「HTTP Request」のノードからリクエストを飛ばした「url」の情報をテキスト内に加えて通知しています。

終わりに

今回作成したワークフローをエクスポートしたモノを下に載せておきます。こちらをインポートして、監視対象のURLとSlackトークン指定を修正していただければ動作するはずです。

エクスポートファイル (クリックで展開)
{
  "name": "watch-example.com",
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        10,
        240
      ],
      "disabled": true
    },
    {
      "parameters": {
        "triggerTimes": {
          "item": [
            {
              "mode": "everyHour"
            }
          ]
        }
      },
      "name": "Cron",
      "type": "n8n-nodes-base.cron",
      "typeVersion": 1,
      "position": [
        150,
        240
      ]
    },
    {
      "parameters": {
        "url": "https://example.com",
        "jsonParameters": true,
        "options": {}
      },
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        300,
        240
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "World",
              "value2": "={{$node[\"HTTP Request\"].json[\"Hello\"]}}"
            }
          ]
        }
      },
      "name": "IF",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        450,
        240
      ]
    },
    {
      "parameters": {},
      "name": "NoOp",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        610,
        130
      ]
    },
    {
      "parameters": {
        "channel": "#notice-alert",
        "text": "=NOT WORK!!!\n{{$node[\"HTTP Request\"].parameter[\"url\"]}}\n<!channel>",
        "attachments": [],
        "otherOptions": {},
        "blocksUi": {
          "blocksValues": []
        }
      },
      "name": "Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 1,
      "position": [
        610,
        330
      ],
      "credentials": {
        "slackApi": "HOGEHOGE"
      }
    }
  ],
  "connections": {
    "Cron": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF": {
      "main": [
        [
          {
            "node": "NoOp",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {},
  "id": "1"
}

今回は簡易的な監視システムをn8nで構築してみましたが、今後もn8nの使い道を見つけたら共有していきたいと思います。