DEV Community

Cover image for DIY downtime monitor with NodeRED
Mangirdas Judeikis
Mangirdas Judeikis

Posted on • Edited on

DIY downtime monitor with NodeRED

"Black box" monitoring is one of the key concepts, when monitoring any application. We will show how to deploy a free DIY downtime monitoring stack, using NodeRed and Synpse.

Similar pattern could be used to do almost any home automation. So go crazy! We use this pattern as its easy to modify, and not does much maintenance.

Synpse is an end-to-end platform to manage your device fleet that can grow to hundreds of thousands of devices, perform OTA software updates, collect metrics, logs, deploy your containerized applications and facilitate tunnel-based SSH access to any of your device. You can find a Quick Start here .

Technologies used

Synpse for hosting and running applications anywhere
NodeRED for instrumenting our monitoring

NodeRED

We will use NodeRED as instrumentation tool to “write code without writing any code” and monitor our web pages availability. If downtime is detected, we will notify administrators via slack or discord message.

First lets deploy NodeRED into Synpse enable IoT device we own. We use simple RPI4 under the desk at home:

name: NodeRed
description: Low-code programming for event-driven applications
type: container
scheduling:
  type: Selector
  # More on selectors https://docs.synpse.net/synpse-core/applications/scheduling
  selectors:
    nodered: master
spec:
  containers:
  - name: nodered
    image: nodered/node-red:latest-minimal
    user: root
    ports:
      - "1880:1880"
    volumes:
      - /data/nodered:/data
      - /etc/localtime:/etc/localtime
      - /root/.ssh:/root/.ssh
Enter fullscreen mode Exit fullscreen mode

Access the remote device via Synpse proxy CLI command to configure it

synpse device proxy <device_name> --port 1880
Enter fullscreen mode Exit fullscreen mode

Open the browser page http://localhost:1880. You should be able to see NodeRed running.

Downtime flow

We use Discord webhook integration to send a messages and alert our developers once page is down. Discord webhook documentation can be found here

Discord webhook

Flow we created is very simple:

  1. Every 5 seconds cloud.synpse.net health url
  2. If response is not 200, go to next phase, else drop
  3. Rate limit to send only 1 message every 5 min
  4. Create a Webhook payload
  5. Send POST request to webhook URL

Flow itself looks like this (we have left if 200 branch too, in case you want to re-use it for other purposes). Full json flow can be found bellow for you to reuse.

NodeRED flow

Press “deploy” and you are done :)

Message

This is very simple way to monitor your applications or construct any other automation flows. In addition you can deploy same application to different agents across the globe, and you have free Region based downtime monitoring!

./wrap_up.sh

If you have any questions or suggestions, feel free to start a new discussion in our forum or drop us a line on Discord

Originally published at Synpse.net blog

Full flow

[
    {
        "id": "90902c5d92f08930",
        "type": "tab",
        "label": "NodeRed on Synpse",
        "disabled": false,
        "info": ""
    },
    {
        "id": "ef34b5db67c67385",
        "type": "http request",
        "z": "90902c5d92f08930",
        "name": "<PAGE_TO_CHECK_NAME>",
        "method": "GET",
        "ret": "txt",
        "paytoqs": "ignore",
        "url": "<PAGE_TO_CHECK_URL>",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "",
        "x": 370,
        "y": 260,
        "wires": [
            [
                "2109536ce55f85cf",
                "1aae7673af94fb6c"
            ]
        ]
    },
    {
        "id": "3c39826c5c2c418b",
        "type": "inject",
        "z": "90902c5d92f08930",
        "name": "ticker 5s",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "5",
        "crontab": "",
        "once": true,
        "onceDelay": "1",
        "topic": "",
        "payload": "{}",
        "payloadType": "json",
        "x": 150,
        "y": 260,
        "wires": [
            [
                "ef34b5db67c67385"
            ]
        ]
    },
    {
        "id": "2109536ce55f85cf",
        "type": "switch",
        "z": "90902c5d92f08930",
        "name": "if not 200",
        "property": "statusCode",
        "propertyType": "msg",
        "rules": [
            {
                "t": "neq",
                "v": "200",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 580,
        "y": 200,
        "wires": [
            [
                "758156729b55665f"
            ]
        ]
    },
    {
        "id": "1aae7673af94fb6c",
        "type": "switch",
        "z": "90902c5d92f08930",
        "name": "if  200",
        "property": "statusCode",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "200",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 570,
        "y": 300,
        "wires": [
            []
        ]
    },
    {
        "id": "758156729b55665f",
        "type": "delay",
        "z": "90902c5d92f08930",
        "name": "",
        "pauseType": "rate",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "5",
        "rateUnits": "minute",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": true,
        "allowrate": false,
        "x": 740,
        "y": 260,
        "wires": [
            [
                "a062d51eb49713f9"
            ]
        ]
    },
    {
        "id": "2452ffaa52e6333f",
        "type": "http request",
        "z": "90902c5d92f08930",
        "name": "discord webhook",
        "method": "POST",
        "ret": "txt",
        "paytoqs": "ignore",
        "url": "<DISCORD_WEBHOOK_URL>",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "",
        "x": 1110,
        "y": 260,
        "wires": [
            []
        ]
    },
    {
        "id": "a062d51eb49713f9",
        "type": "function",
        "z": "90902c5d92f08930",
        "name": "payload",
        "func": "var payload = {\n  \"username\": \"Downtime BOT\",\n  \"avatar_url\": \"https://i.imgur.com/zEGYUVs.jpeg\",\n  \"content\": \"cloud.synpse.net Downtime detected. Next check in 5 min\",\n}\n\nmsg.payload = payload\nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 920,
        "y": 260,
        "wires": [
            [
                "2452ffaa52e6333f"
            ]
        ]
    }
]
Enter fullscreen mode Exit fullscreen mode

Top comments (0)