
Short answer: You can monitor an RSS feed with Prometheus in two layers. The blackbox exporter probes the feed address and reports whether it answers with a valid status, how long it takes and when the certificate expires. A small script reads the feed and exports the number of items and the date of the newest one, so that an alert can fire when the feed is empty or stale. Together they warn you before readers, search engines and auto-posters notice that new articles have stopped reaching your social channels.
A feed fails quietly. The page that shows your articles still works, visitors see nothing wrong and the server logs look normal, but the XML is empty, malformed or three weeks old. The first person to notice is usually a reader who asks why your account has gone silent. If you already run Prometheus for your servers, you can watch the feed with the tools you know. This guide shows how to probe the address with the blackbox exporter, how to export freshness with a short Python script and the textfile collector, which alert rules to write and how to choose thresholds that match the way you publish. The examples are short and meant to be adapted, and every command can be tried on a test feed before you trust it.
A feed has three kinds of failure. The first is availability: the address does not answer, answers slowly or returns an error. The second is validity: the answer is not an RSS or Atom document, or it is cut off in the middle. The third is freshness: the document is valid, but nothing new has appeared for longer than your normal rhythm. A single check cannot cover all three, so combine them.
| Check | Tool | Metric |
|---|---|---|
| Does the address answer with 200? | Blackbox exporter | probe_success, probe_http_status_code |
| Is it fast enough? | Blackbox exporter | probe_duration_seconds |
| Is the body a feed? | Blackbox exporter | Body match in the module |
| Is the certificate valid? | Blackbox exporter | probe_ssl_earliest_cert_expiry |
| Are there items, and are they recent? | Script and textfile collector | Custom item count and newest date |
The blackbox exporter requests an address from the outside and reports the result as metrics. Define a module for feeds in its configuration file. The module below requires a 200 status and a body that contains the start of an RSS or Atom document.
modules:
http_feed:
prober: http
timeout: 10s
http:
method: GET
valid_status_codes: [200]
fail_if_body_not_matches_regexp:
- "<rss|<feed"
preferred_ip_protocol: ip4
headers:
User-Agent: feed-monitor/1.0A body check catches a common failure in which a server answers 200 with an error page written in HTML. Choose a user agent that your own rules do not block, and leave it recognisable in the logs, so that colleagues know where the requests come from. Then add a scrape job to the Prometheus configuration. The usual relabelling passes the feed address to the exporter as a parameter.
scrape_configs:
- job_name: feed_probe
metrics_path: /probe
params:
module: [http_feed]
static_configs:
- targets:
- https://example.com/feed.xml
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox-exporter:9115List every feed you care about as a separate target, including category feeds, the comment feed if you use it and any feed that an auto-poster reads. A probe from the same network as your server proves less than one from another place, so run the exporter on a small machine outside your hosting if you can. Compare the result with a manual request, as shown in debugging a feed with curl.
The blackbox exporter cannot tell whether the newest article is from today or from last month. For that, a script reads the feed and writes a few metrics to a file that the node exporter publishes through its textfile collector. The script below handles RSS dates; Atom uses an updated element instead, so adapt the lookup if you serve Atom.
#!/usr/bin/env python3
import os, time
import urllib.request
import xml.etree.ElementTree as ET
from email.utils import parsedate_to_datetime
URL = "https://example.com/feed.xml"
OUT = "/var/lib/node_exporter/textfile/rss_feed.prom"
req = urllib.request.Request(URL, headers={"User-Agent": "feed-monitor/1.0"})
with urllib.request.urlopen(req, timeout=10) as r:
root = ET.fromstring(r.read())
stamps = []
for item in root.iter("item"):
date = item.findtext("pubDate")
if date:
stamps.append(parsedate_to_datetime(date).timestamp())
lines = [
'rss_feed_items{url="%s"} %d' % (URL, len(stamps)),
'rss_feed_newest_item_timestamp_seconds{url="%s"} %d' % (URL, max(stamps) if stamps else 0),
'rss_feed_check_timestamp_seconds{url="%s"} %d' % (URL, time.time()),
]
tmp = OUT + ".tmp"
with open(tmp, "w") as f:
f.write("\n".join(lines) + "\n")
os.replace(tmp, OUT)The script writes to a temporary file and renames it, so the collector never reads half a file. If the request fails or the XML is invalid, the script stops with an error and does not update the file. That is deliberate: the third metric, the time of the last successful check, stops moving, and an alert can notice it. Run the script from cron or a systemd timer every few minutes with a user that can write to the collector folder. The date format of the feed matters, and wrong dates make the newest item look old or new, as explained in the guide to RSS date format errors.
Alerts should describe a problem that a person can fix, and each rule should have a waiting period, so that one slow answer does not wake anybody. These examples cover the cases that matter for a feed.
groups:
- name: rss-feed
rules:
- alert: FeedNotAnswering
expr: probe_success{job="feed_probe"} == 0
for: 10m
labels:
severity: page
annotations:
summary: "Feed {{ $labels.instance }} fails its probe"
- alert: FeedSlow
expr: probe_duration_seconds{job="feed_probe"} > 5
for: 30m
labels:
severity: ticket
- alert: FeedCertificateExpiring
expr: probe_ssl_earliest_cert_expiry{job="feed_probe"} - time() < 14 * 86400
labels:
severity: ticket
- alert: FeedEmpty
expr: rss_feed_items == 0
for: 15m
labels:
severity: page
- alert: FeedStale
expr: time() - rss_feed_newest_item_timestamp_seconds > 3 * 86400
for: 1h
labels:
severity: ticket
- alert: FeedMonitorStopped
expr: time() - rss_feed_check_timestamp_seconds > 1800
labels:
severity: ticketRoute the severities in Alertmanager: a page for a feed that is down or empty, a ticket for everything else. The stale rule is the one that needs thought, because it depends on how you publish, and the next section explains how to choose the number.
A blog that publishes every weekday can alert after two days without a new item. A shop that adds one product a week should wait ten days. A news site that publishes every hour may alert after six hours. If you set the limit too tight, holidays and quiet weeks cause false alarms, and people learn to ignore the alert. If you set it too loose, a broken feed can run for weeks unnoticed. A good start is three times your normal gap between items, adjusted after a month of experience. Keep separate rules for feeds with different rhythms, and use a label such as the feed name to carry the threshold in the expression. When a feed is stale because you really had nothing to say, the alert is a useful reminder, not an error.
The reason to monitor a feed is that other tools depend on it. An auto-poster that reads your feed every minute cannot publish what is not there, and a search engine that cannot fetch the sitemap or the feed may visit less often. Name alerts so that a colleague who receives one understands the effect, for example: the feed is empty, so no new articles are being shared on social channels. Add a link to the runbook, which should list the usual causes: an application error, a cache that serves an old copy, a full disk, a changed address, a firewall rule or a certificate that expired. Compare the symptoms with why auto-posted content sometimes lags ir the guide to feed timeouts.
Alerts tell you when something breaks, and a dashboard shows how the feed behaves in normal times. Plot the probe duration, the status code, the number of items and the age of the newest item, which is the current time minus the newest timestamp. A sudden drop in the item count often means that a plugin or a template was changed. A slow rise in duration points at a database that is growing or a cache that stopped working. Keep the dashboard small, with one row for each feed, and look at it after every deployment. It also makes a good report for a client, because it shows in one picture that the feed was available and fresh.
A longer routine is in the feed validation guide.
PostRSS has been publishing RSS and Atom feeds to social networks since 2014. Paste the address of your feed, connect your accounts and choose how each post is built from the title, the description or the page title. PostRSS checks the feed as often as every minute and shares each new entry, with its image and link, to the channels you choose among 66 supported networks, messengers, team chats and blogs, including LinkedIn, X, Bluesky, Mastodon and Telegram. Keyword filters, UTM parameters and posting windows let you tune each channel. See the PostRSS features page and the plan limits on the pricing page. More developer guides are under the Technical Guide tag.
A feed deserves the same attention as any service that other systems depend on. Probe the address from outside with the blackbox exporter, check that the body is a feed and that the certificate is valid, export the item count and the date of the newest item with a short script, alert on a feed that is down, empty or stale and also on a monitor that has stopped, and choose thresholds that match the way you publish. Then connect the feed to an auto-poster, and you will know within minutes if new articles stop reaching your readers.
Yes. The blackbox exporter probes the address and reports status, duration and certificate expiry, and a small script can export the item count and the date of the newest item.
Export the timestamp of the newest item and write a rule that fires when the current time minus that timestamp is larger than your normal gap between items, multiplied by about three.
A server can answer with a 200 status and an HTML error page. A body match makes the probe fail when the document is not an RSS or Atom feed.
Yes, if you want to know about stale content. The exporter proves that the address answers, but it does not read the dates of the items.
Yes. PostRSS reads any valid RSS or Atom address that is reachable without a login. Paste the address, connect your channels and new articles are shared as soon as they appear.
What changed in the networks, what broke, and how to fix it before it costs you reach.
Sukūrė Internet Solutions – PostRSS komanda. Kiekvienas produktas sutaupo laiko savaip.