Ask HN: How to do simple heartbeat monitoring?

108 points by benjbrooks ↗ HN
Hey there!

My team is hosting an API that sends open telemetry data to Signoz & manages on-call via PagerDuty. We've configured Signoz to hit Pagerduty when there's a series of 500 errors.

However, our server went down last night and NO opentel data was sent to Signoz. We weren't notified that the server went down as there weren't 500 responses to report. What's the easiest way to have a cron-like query hit our API and integrate with our existing stack? Is this feasible with our existing vendors? Should I have a serverless function running on a timer that uses Pagerduty's API? Should I be migrating to another monitoring service?

Any advice would be appreciated!

85 comments

[ 4.3 ms ] story [ 149 ms ] thread
I can highly recommend Better Stack. We have never been let down by their service.
thanks! this has been recommended by others. I'm not feeling excited about migrating to another monitoring service but it might be the right move.
Seconding this. We've used them for a little over a year now for heartbeats + external status dashboard. Easy platform to set up and maintain. Decent pricing.
Believe you can do this in Signoz: https://signoz.io/docs/monitor-http-endpoints/
ah, this is the answer I was hoping for. thank you!
on second read, this is something that is set up on the service-side. I.e. if our service goes down, we would also stop sending data to Signoz Cloud. We wouldn't be able to run a status check, let alone send it to signoz cloud.
you can add https://github.com/open-telemetry/opentelemetry-collector-co... at signoz's otel-collector which will scrape your service's endpoint periodically. If your service is down, this will give 5xx error and you can set an alert on that.

Another alternative is to use an alert to notify on a metric being absent for sometime. Both of these should work

For my applications, monitored by prometheus + grafana, we have alerts when no data is reported for certain metrics in the past 5 minutes, indicating a malfunction in the subsystem.

With a metric, you can use a monotonic counter to serve as a heartbeat. A timestamp would work. In your monitoring system, when the heartbeat value has not increased in X minutes, you alert.

This basic monitoring primitive is the first thing we started with at Cronitor[1]. I was a software engineer at my day job and needed a way to be alerted when something doesn't happen.

We have a decent free plan that would probably work for you.

[1] https://news.ycombinator.com/item?id=7917587

We have two different external uptime status monitoring services, which has helped
we use updown.io for this and are happy with it.

there's probably functionality built in to your other monitoring tools, or you could write a little serverless function to to it, but for me i really like to have it isolated. i wanted a tool that's not part of the rest of our monitoring stack, not part of our own codebase, and not something we manage.

Seconding Updown. Easy setup, pay-as-you-go, no nonsense.

I wish they had a better way to hit your phone. Currently it supports Slack and SMS but I need a way to make my phone go crazy when things go wrong (you can set Updown as an emergency contact but this has many downsides as well).

(comment deleted)
Healthchecks.io is very simple to use and free for low usage (including 5 free sms per month)
> What's the easiest way to have a cron-like query hit our API and integrate with our existing stack?

Write a cron job that greps the logs and pulls on your api with curl?

With another 20 minutes of work you can remember the log size on each run and grep only what's new on the next run.

To me, this is the biggest problem with OpenTelemetry.

There isn’t a good way to solve this using a PUSH model that isn’t somewhat of a hack or using another external tool

This is one of those things that _seems_ really simple but the details make it pretty complicated.

Not sure about Signoz and PagerDuty, but there are plenty freemium services like UpTimeRobot that work fine for basics.

And then something like AWS CloudWatch has a lot more advanced options about how to treat missing data.

https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitori...

With a lot of knobs to tune around what intervals you need and what counts as 'down', which you'll want to think about pretty carefully given what you need.

https://checklyhq.com

You cannot only do classic heartbeat checks but also high level API (single request and multi request) and Browser checks to make sure your service is behaving as expected.

statuscake & new relic both have generous free tiers
Writing a heartbeat process using UDP for a Fluentd logger is as one of the first things I learned in Elixir! In my case, basically when then there was no heartbeat, the TCP forwarder /w a connection pool would be taken offline. When the heartbeat came back, the forwarder was free to send messages again.

The heartbeat process itself basically just sent pings every second on a UDP port and waited for a reply. If we didn’t get a reply in one second, it’d assume the connection was bad until a ping came again.

You need to implement a deadman switch. For example if using Prometheus you can configure it to access an HTTP endpoint of a deadman switch service every X seconds. When that service detects you have not accessed it in some time it will alert you.

For example: https://blog.ediri.io/how-to-set-up-a-dead-mans-switch-in-pr...

And now you need to monitor the deadman switch service!
Oh, you just run two instances of those and point them at each other.
Even number so that everything is symmetrical.
You want odd numbers (n+1) so you can have a quorum in case of network partition.
I think you're missing the vibe (sarcasm).
And then a third instance in case those both go down at the same time, and a fourth just in case there's a major worldwide outage.... it's monitoring instances all the way down
Typically that's why people use dead man's switch as a service. You don't assume that they'll never go down, but you're paying for someone who's failures are very likely uncorrelated with your own.
I clicked to say something about Instrumentation Amplifiers or interfacing with chest straps ;)

You might want to use a different service for monitoring your stack just to make sure you have some redundancy there. Seems like you got an answer for how to do this with Signoz but if that is down then you won't know.

What did you want to say about instrumentation amplifiers / chest straps? :eyes:
In pre-historic times I (EDIT: designed and) built a battery powered heart rate data logger for livestock. I used an instrumentation amplifier IC and some very simple electrodes and was able to use auto-correlation to detect the heart rate pretty reliably. For humans today I'd pick something like a Garmin chest strap which works with Bluetooth or ANT+. I've no direct experience with ANT or ANT+ but I imagine it's not hard to interface with ;)

That's more or less what I was gonna say...

Same, honestly, though not specifically about chest straps. Extremely primitive but effective heartbeat monitoring can be done with a cheap SpO2 monitor from Amazon and reverse engineering the Bluetooth LE signal. You won't get a true beat, but one that's more of an approximation. I know I have some C++ code lying around somewhere for this.
Even full-blown OEM heartrate monitors seem to be relatively ineffective (at least, in my experience this is true when talking about watches specifically). I can't imagine this would do a great job, would it?
Could be done with a webcam even. It's known that facial skin color is affected subtly by pulses. There are plenty Python codes for that on GitHub.
Yeah, honestly, I'd like a smartwatch type monitor without any smart features; just something that sits on my wrist and displays my heart rate so I can watch it myself. I've looked a bit, but such a thing hasn't been easy to find.
Fitbit Sense 2 is pretty dumb for a smart watch, but Polar H10 should be more accurate.
The polar verity sense is what you're looking for. It connects to your phone via ble so it doesn't need a display. It's not as popular as a chest strap.
The Polar Pacer or Pracer Pro's only smart features are for exercises/etc. and I don't really use them, so it's really what you describe.
(comment deleted)
OnlineOrNot has a cron job/scheduled task monitoring system that integrates with PagerDuty fwiw

edit: on second read, it sounds like regular uptime monitoring for your API would do the trick

I use grafana. Setup an endpoint on the backend that uses things like the database to check if it can still connect. Every 10 sec. If it fails I get a text.
https://heartbeat.sh/

Free and easy. Not affiliated, just a happy user.

I combine it with a service like uptimerobot to get messages if the heartbeat stopped.

Depending on your expected traffic patterns and volume, no responses to report for an extended period of time is its own data point.
In the old days when telemetry was exotic this was the answer.

No 2XX-499 results means the server is borked.

If you wanted to be really fancy you could send heartbeat requests when no live traffic had hit that node for n milliseconds.

I still think the latter is the right answer. Why inflate traffic when you are horizontally scaling? That’s a lot of health checks per second.

healthchecks.io
Agreed, I've used this for a number of years and have been happy with it, very straightforward free service.
I've been using UptimeRobot since 2019 for FastComments, relatively happy. They have a PagerDuty integration, although I just use the built in text/email alerts ATM.
> Should I have a serverless function running on a timer that uses Pagerduty's API?

If you're on AWS, there's already heartbeat monitoring and that can integrate with CloudWatch to notify PagerDuty.

If you want super minimal, something like this might work?

  #!/bin/bash

  # Add this script to cron to run at whatever duration you desire.

  # URL to be checked
  URL="https://example.com/test.php"

  # Email for alerts
  EMAIL="root@example.com"

  # Perform the HTTP request and extract the status code with 10 second timeout.
  STATUS=$(curl -o /dev/null -s -w "%{http_code}\n" --max-time 10 $URL)

  # Check if the status code is not 200
  if [ "$STATUS" -ne 200 ]; then
      # Send email alert
      echo "The URL $URL did not return a 200 status code. Status was $STATUS." | mail -s "URL Check Alert" $EMAIL

      # Instead of email, you could send a Slack/Teams/PagerDuty/Pushover/etc, etc alert, with something like:
      curl -X POST https://events.pagerduty.com/...
  fi
Edit: updated with suggested changes.
As a slight variation, you could send an alert to the PagerDuty API by replacing “Send email alert” with something like:

  # Send PagerDuty alert
  curl -X POST https://events.pagerduty.com/...
Added.

In fact, this is what I'd recommend (though I use Pushover), because then you don't have to be concerned with email setup, not getting caught in spam filters, firewalls, etc. You could also send a Slack/Teams alert with a similar POST.

For some reason, I thought I had read that OP wanted to send an email.

You should include a timeout in the curl to detect if it hangs, or if it gets slower than it should be.
A lot of vendors offer this and call it "synthetic monitoring". They will repeatedly send requests that you configure and record the success rate.

They usually all have pager duty integration as well.

Some examples:

Datadog: https://docs.datadoghq.com/synthetics/ Grafana cloud: https://grafana.com/grafana/plugins/grafana-synthetic-monito...

We do synthetics and heartbeat monitoring for quite some companies (link in bio) but this problem is a bit trickier, or let's say "three sided"

1. Yes, a synthetic check is very useful here to just see if a user facing "thing" is still working.

2. a heartbeat check / deadman's switch can also work here, but it will only be reliable when the monitored event has a predefined cadence, e.g. "every 5 minutes this should happen".

3. The lack / absence of metrics flowing into a system is also sign. This would typically be solved by the Signoz team where they would alert on not seeing some specific event happening for x time. This can be tricky if the event is directly related to a user interaction.

Super big disclaimer: founder at a monitoring company that solve 1 and 2, not 3.