{"id":1299,"date":"2023-02-17T11:30:04","date_gmt":"2023-02-17T09:30:04","guid":{"rendered":"https:\/\/cln.io\/blog\/?p=1299"},"modified":"2024-09-21T17:16:49","modified_gmt":"2024-09-21T15:16:49","slug":"monitoring-web-services-availability-with-tines","status":"publish","type":"post","link":"https:\/\/cln.io\/blog\/monitoring-web-services-availability-with-tines\/","title":{"rendered":"Monitoring web services availability with Tines"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I&#8217;ve been using UptimeRobot for a while now <a rel=\"noreferrer noopener\" href=\"https:\/\/blog.uptimerobot.com\/december-2022-we-are-introducing-sub-users-and-new-plans\/\" target=\"_blank\">but they have recently removed features &#8216;we&#8217; paid for and are asking extra for it<\/a> &#x1f926;&#x1f3fb;&#x200d;&#x2640;&#xfe0f; UPDATE: seems I was not the only one complaining haha, the post was updated with: &#8216;<em>We\u2019ve decided not to restrict legacy users<\/em>.&#8217;  <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Anyhow, I&#8217;ve been playing and working with Tines recently, its a visual programming automation platform and this made me wonder if I could replace UptimeRobot with Tines<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ve written a small Tines story to exactly achieve this.<br>This can be used to monitor internal services (if you have an Enterprise license with a self-hosted node) or monitor your company&#8217;s website, services, you name it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ve opted to use PushOver, but you can easily switch out the notification block with your Slack block or Twilio block or whatever you want<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The flow goes as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"556\" src=\"https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/image-31-1024x556.png\" alt=\"\" class=\"wp-image-1364\" srcset=\"https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/image-31-1024x556.png 1024w, https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/image-31-300x163.png 300w, https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/image-31-768x417.png 768w, https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/image-31.png 1417w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-right is-layout-flex wp-container-core-buttons-is-layout-89b4c9e9 wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button is-style-fill\"><a class=\"wp-block-button__link has-white-color has-cyan-bluish-gray-background-color has-text-color has-background wp-element-button\" href=\"https:\/\/login.tines.com\/saml_idp\/choose_tenant?intended_path=\/import_seed_story?guid=6411b73dd462c533c282b34be494ca34\" target=\"_blank\" rel=\"noopener\">try it out<\/a><\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">My story has been published in the Tines story library over <a rel=\"noreferrer noopener\" href=\"https:\/\/www.tines.com\/story-library\/1140600\/monitor-web-services-for-availability-via-pushover\" target=\"_blank\">here<\/a> &#x1f973; in case you want to try it out or take a closer look at it <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">My approach was to just give it an array of services I want to check, what method and what the expected reply should be (status codes) if the reply is different than the one I was expecting it will ping me on PushOver to alert me something is up<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">the config is as follows<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[\n  {\n    \"url\": \"https:\/\/cln.io\",\n    \"method\": \"get\",\n    \"timeout\": 5,\n    \"expected_status_code\": 200\n  },\n  {\n    \"url\": \"https:\/\/tines.com\",\n    \"method\": \"get\",\n    \"timeout\": 5,\n    \"expected_status_code\": 200\n  }\n]<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">the end result (you can customize everything about the alert! have fun) <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"270\" src=\"https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/3F7CBFEA-2286-4312-9BB2-D36070B2347C-1024x270.jpeg\" alt=\"\" class=\"wp-image-1369\" srcset=\"https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/3F7CBFEA-2286-4312-9BB2-D36070B2347C-1024x270.jpeg 1024w, https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/3F7CBFEA-2286-4312-9BB2-D36070B2347C-300x79.jpeg 300w, https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/3F7CBFEA-2286-4312-9BB2-D36070B2347C-768x202.jpeg 768w, https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/3F7CBFEA-2286-4312-9BB2-D36070B2347C.jpeg 1284w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The neat thing is that if you schedule your story to check every 10 minutes or so you can do it on their free plan &#x1f643; so you basically get free monitoring with push notifications<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you want the entire story as a copy paste for easier import, here you go:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">{\n    \"standardLibVersion\": \"14\",\n    \"actionRuntimeVersion\": \"3\",\n    \"agents\": [\n        {\n            \"disabled\": false,\n            \"name\": \"URL's to monitor\",\n            \"description\": \"An array containing the URL's to monitor\",\n            \"options\": \"{\\\"mode\\\":\\\"message_only\\\",\\\"loop\\\":false,\\\"payload\\\":[{\\\"url\\\":\\\"https:\/\/google.com\\\",\\\"method\\\":\\\"get\\\",\\\"timeout\\\":5,\\\"expected_status_code\\\":200},{\\\"url\\\":\\\"https:\/\/tines.com\\\",\\\"method\\\":\\\"get\\\",\\\"timeout\\\":5,\\\"expected_status_code\\\":200},{\\\"url\\\":\\\"https:\/\/httpbin.org\/post\\\",\\\"method\\\":\\\"post\\\",\\\"timeout\\\":3,\\\"expected_status_code\\\":200},{\\\"url\\\":\\\"https:\/\/httpbin.org\/post\\\",\\\"method\\\":\\\"get\\\",\\\"timeout\\\":3,\\\"expected_status_code\\\":200},{\\\"url\\\":\\\"https:\/\/this-is-a-non-existing-domain.com\\\",\\\"method\\\":\\\"get\\\",\\\"timeout\\\":3,\\\"expected_status_code\\\":200},{\\\"url\\\":\\\"https:\/\/github.com\\\",\\\"method\\\":\\\"get\\\",\\\"timeout\\\":3,\\\"expected_status_code\\\":200}]}\",\n            \"position\": {\n                \"x\": 705,\n                \"y\": 180\n            },\n            \"schedule\": [\n                {\n                    \"cron\": \"*\/10 * * * *\",\n                    \"timezone\": \"Etc\/UTC\"\n                }\n            ],\n            \"type\": \"eventTransformation\",\n            \"timeSavedUnit\": \"minutes\",\n            \"timeSavedValue\": 0,\n            \"monitorAllEvents\": false,\n            \"monitorFailures\": false,\n            \"monitorNoEventsEmitted\": null,\n            \"form\": null\n        },\n        {\n            \"disabled\": false,\n            \"name\": \"Explode URL Array\",\n            \"description\": \"We explode the array into individual bits and continue the story below 1 by 1\",\n            \"options\": \"{\\\"mode\\\":\\\"explode\\\",\\\"path\\\":\\\"=url_s_to_monitor\\\",\\\"to\\\":\\\"service\\\"}\",\n            \"position\": {\n                \"x\": 705,\n                \"y\": 270\n            },\n            \"type\": \"eventTransformation\",\n            \"timeSavedUnit\": \"minutes\",\n            \"timeSavedValue\": 0,\n            \"monitorAllEvents\": false,\n            \"monitorFailures\": false,\n            \"monitorNoEventsEmitted\": null,\n            \"form\": null\n        },\n        {\n            \"disabled\": false,\n            \"name\": \"Request the URL\",\n            \"description\": \"\",\n            \"options\": \"{\\\"url\\\":\\\"&lt;&lt;explode_url_array.service.url>>\\\",\\\"content_type\\\":\\\"application_json\\\",\\\"method\\\":\\\"&lt;&lt;explode_url_array.service.method>>\\\",\\\"timeout\\\":\\\"&lt;&lt;NUMBER(explode_url_array.service.timeout)>>\\\",\\\"log_error_on_status\\\":[]}\",\n            \"position\": {\n                \"x\": 705,\n                \"y\": 360\n            },\n            \"type\": \"httpRequest\",\n            \"timeSavedUnit\": \"minutes\",\n            \"timeSavedValue\": 0,\n            \"monitorAllEvents\": false,\n            \"monitorFailures\": false,\n            \"monitorNoEventsEmitted\": null,\n            \"form\": null\n        },\n        {\n            \"disabled\": false,\n            \"name\": \"Check for an expected reply\",\n            \"description\": \"\",\n            \"options\": \"{\\\"rules\\\":[{\\\"type\\\":\\\"field!=value\\\",\\\"value\\\":\\\"&lt;&lt;explode_url_array.service.expected_status_code>>\\\",\\\"path\\\":\\\"&lt;&lt;request_the_url.status>>\\\"}]}\",\n            \"position\": {\n                \"x\": 705,\n                \"y\": 435\n            },\n            \"type\": \"trigger\",\n            \"timeSavedUnit\": \"minutes\",\n            \"timeSavedValue\": 0,\n            \"monitorAllEvents\": false,\n            \"monitorFailures\": false,\n            \"monitorNoEventsEmitted\": null,\n            \"form\": null\n        },\n        {\n            \"disabled\": false,\n            \"name\": \"Send notification to Pushover\",\n            \"description\": \"\",\n            \"options\": \"{\\\"url\\\":\\\"https:\/\/api.pushover.net\/1\/messages.json\\\",\\\"content_type\\\":\\\"json\\\",\\\"method\\\":\\\"post\\\",\\\"payload\\\":{\\\"token\\\":\\\"&lt;&lt;CREDENTIAL.pushover_app_token>>\\\",\\\"user\\\":\\\"&lt;&lt;CREDENTIAL.pushover_user_key>>\\\",\\\"message\\\":\\\"=prepare_notification_message.message\\\"},\\\"headers\\\":{}}\",\n            \"position\": {\n                \"x\": 705,\n                \"y\": 585\n            },\n            \"type\": \"httpRequest\",\n            \"timeSavedUnit\": \"minutes\",\n            \"timeSavedValue\": 0,\n            \"monitorAllEvents\": false,\n            \"monitorFailures\": false,\n            \"monitorNoEventsEmitted\": null,\n            \"form\": null\n        },\n        {\n            \"disabled\": false,\n            \"name\": \"prepare notification message\",\n            \"description\": \"\",\n            \"options\": \"{\\\"mode\\\":\\\"message_only\\\",\\\"loop\\\":false,\\\"payload\\\":{\\\"message\\\":\\\"Tines&#x26a0;&#xfe0f; a service you monitor (&lt;&lt;explode_url_array.service.url>>) did not reply as expected\\\\n&lt;%if request_the_url.status = 0%> &lt;&lt;request_the_url.connection_error>>&lt;%else%>) reply was [&lt;&lt;request_the_url.status>>] but we expected [&lt;&lt;explode_url_array.service.expected_status_code>>]&lt;%endif%>\\\"}}\",\n            \"position\": {\n                \"x\": 705,\n                \"y\": 510\n            },\n            \"type\": \"eventTransformation\",\n            \"timeSavedUnit\": \"minutes\",\n            \"timeSavedValue\": 0,\n            \"monitorAllEvents\": false,\n            \"monitorFailures\": false,\n            \"monitorNoEventsEmitted\": null,\n            \"form\": null\n        }\n    ],\n    \"links\": [\n        {\n            \"sourceIdentifier\": 0,\n            \"receiverIdentifier\": 1\n        },\n        {\n            \"sourceIdentifier\": 1,\n            \"receiverIdentifier\": 2\n        },\n        {\n            \"sourceIdentifier\": 2,\n            \"receiverIdentifier\": 3\n        },\n        {\n            \"sourceIdentifier\": 3,\n            \"receiverIdentifier\": 5\n        },\n        {\n            \"sourceIdentifier\": 5,\n            \"receiverIdentifier\": 4\n        }\n    ],\n    \"diagramNotes\": [\n        {\n            \"position\": {\n                \"x\": 960,\n                \"y\": 285\n            },\n            \"content\": \"# Overview\\n\\nMonitor a list of web services for their availability. Configure the maximum time a service should respond by and the normal operating status codes that should be turned.\\n\\nIf the given service matches a failure condition, send a push notification to [Pushover](https:\/\/pushover.net\/).\\n\",\n            \"width\": null\n        },\n        {\n            \"position\": {\n                \"x\": 375,\n                \"y\": 435\n            },\n            \"content\": \"# Requirements:\\n\\n- [ ] A Credential `pushover_app_token` as a [Pushover app token](https:\/\/pushover.net\/apps\/build) \\n- [ ] A Credential `pushover_user_key` as a Pushover user key. Viewable when logged into your [dashboard](https:\/\/pushover.net\/dashboard).\",\n            \"width\": 264\n        },\n        {\n            \"position\": {\n                \"x\": 900,\n                \"y\": 180\n            },\n            \"content\": \"&#x2b05;&#xfe0f; The monitoring schedule is located in here (default is every ten minutes).\",\n            \"width\": null\n        },\n        {\n            \"position\": {\n                \"x\": 345,\n                \"y\": 210\n            },\n            \"content\": \"https:\/\/image-uploads.tines.com\/upload-pushover.png\",\n            \"width\": 332\n        }\n    ]\n}<\/pre>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"589\" src=\"https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/nasa-dCgbRAQmTQA-unsplash-1024x589.jpg\" alt=\"\" class=\"wp-image-1371\" srcset=\"https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/nasa-dCgbRAQmTQA-unsplash-1024x589.jpg 1024w, https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/nasa-dCgbRAQmTQA-unsplash-300x173.jpg 300w, https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/nasa-dCgbRAQmTQA-unsplash-768x442.jpg 768w, https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/nasa-dCgbRAQmTQA-unsplash-1536x884.jpg 1536w, https:\/\/cln.io\/blog\/wp-content\/uploads\/2023\/02\/nasa-dCgbRAQmTQA-unsplash.jpg 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Photo by <a href=\"https:\/\/unsplash.com\/@nasa?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\" target=\"_blank\" rel=\"noreferrer noopener\">NASA<\/a> on <a href=\"https:\/\/unsplash.com\/photos\/dCgbRAQmTQA?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\" target=\"_blank\" rel=\"noreferrer noopener\">Unsplash<\/a><\/figcaption><\/figure>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been using UptimeRobot for a while now but they have recently removed features &#8216;we&#8217; paid for and are asking extra for it &#x1f926;&#x1f3fb;&#x200d;&#x2640;&#xfe0f; UPDATE: seems I was not the only one complaining haha, the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1372,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,26,38,59],"tags":[50,8,55,53,49,51,52,54],"class_list":["post-1299","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-automation","category-it","category-monitoring","category-tines","tag-api","tag-automation","tag-push-notification","tag-pushover","tag-tines","tag-uptimerobot","tag-visual-programming","tag-webhook"],"_links":{"self":[{"href":"https:\/\/cln.io\/blog\/wp-json\/wp\/v2\/posts\/1299","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cln.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cln.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cln.io\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cln.io\/blog\/wp-json\/wp\/v2\/comments?post=1299"}],"version-history":[{"count":8,"href":"https:\/\/cln.io\/blog\/wp-json\/wp\/v2\/posts\/1299\/revisions"}],"predecessor-version":[{"id":1375,"href":"https:\/\/cln.io\/blog\/wp-json\/wp\/v2\/posts\/1299\/revisions\/1375"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cln.io\/blog\/wp-json\/wp\/v2\/media\/1372"}],"wp:attachment":[{"href":"https:\/\/cln.io\/blog\/wp-json\/wp\/v2\/media?parent=1299"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cln.io\/blog\/wp-json\/wp\/v2\/categories?post=1299"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cln.io\/blog\/wp-json\/wp\/v2\/tags?post=1299"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}