The way you have it, it will alert if you have new errors every time it evaluates (default=1m) for 10 minutes and then trigger an alert. There is also a property in alertmanager called group_wait (default=30s) which after the first triggered alert waits and groups all triggered alerts in the past time into 1 notification. You can remove the for: 10m and set group_wait=10m if you want to send notification even if you have 1 error but just don't want to have 1000 notifications for every single error

Answer from Petar Nikolov on Stack Overflow
🌐
Prometheus
discuss.prometheus.io › promql
Alert on increase in slow increasing prometheus counter not working due to resetarts - PromQL - Prometheus Monitoring System
August 4, 2023 - We have a counter for some operation, say some_counter. This counter is increased each time the operation is performed for each customer (customer_id is the label). And the operation is usually performed once per day. F…
Discussions

Alerting on prometheus counter increments without false alarms from query timeouts?

I just use 'Keep last state", then rely on a separate check to ensure Grafana and prometheus are working.

More on reddit.com
🌐 r/grafana
1
5
October 27, 2024
grafana - Alert on increase in slow increasing prometheus counter not working due to resetarts - Stack Overflow
We have a counter for some operation, say some_counter. This counter is increased each time the operation is performed for each customer (customer_id is the label). And the operation is usually per... More on stackoverflow.com
🌐 stackoverflow.com
Prometheus alerts first counter value - Stack Overflow
Is there a way to find that first ... value increasing(from 0 to 1)? I need to fire the alert only on the first count of that metric. ... Short answer: No. Long answer: No, but you may get around this limitation by initializing your metrics with a value of 0 the moment you declare the respective metric in your code. Maybe there are other solutions as well I cannot think of right now. The reason is that your metric app_error only starts to "exist" in Prometheus once it gets ... More on stackoverflow.com
🌐 stackoverflow.com
Prometheus alerting rule not detecting first time metric increase - Stack Overflow
Now the issue is, when there is ... by this alert expression and it did not trigger. Then when the counter increases to 2. Alert triggered. The following example would be easy to understand. Time 0: Prometheus: error_in_execution --> No Metric Exsist.... More on stackoverflow.com
🌐 stackoverflow.com
August 3, 2021
Top answer
1 of 2
4

I had a similar issue with planetlabs/draino:
I wanted to be able to detect when it drained a node.
(Unfortunately, they carry over their minimalist logging policy, which makes sense for logging, over to metrics where it doesn't make sense...)
The draino_pod_ip:10002/metrics endpoint's webpage is completely empty... does not exist until the first drain occurs...
My needs were slightly more difficult to detect, I had to deal with metric does not exist when value = 0 (aka on pod reboot).
I had to detect the transition from does not exist -> 1, and from n -> n+1.
This is what I came up with, note the metric I was detecting is an integer, I'm not sure how this will worth with decimals, even if it needs tweaking for your needs I think it may help point you in the right direction:


(absent(draino_cordoned_nodes_total offset 1m) == 1 and count(draino_cordoned_nodes_total) > -1)

^ creates a blip of 1 when the metric switches from does not exist to exists

((draino_cordoned_nodes_total - draino_cordoned_nodes_total offset 1m) > 0)

^ creates a blip of 1 when it increases from n -> n+1


Combining the 2:

(absent(draino_cordoned_nodes_total offset 1m) == 1 and count(draino_cordoned_nodes_total) > -1) or ((draino_cordoned_nodes_total - draino_cordoned_nodes_total offset 1m) > 0)

^ or'ing them both together allowed me to detect changes as a single blip of 1 on a grafana graph, I think that's what you're after.

2 of 2
1

@neokyle has a great solution depending on the metrics you're using.

In my case I needed to solve a similar problem. The issue was that I also have labels that need to be included in the alert. And it was not feasible to use absent as that would mean generating an alert for every label. (I'm using Jsonnet so this is feasible, but still quite annoying!)

The key in my case was to use unless which is the complement operator. I wrote something that looks like this:

(my_metric unless my_metric offset 15m) > 0

This will result in a series after a metric goes from absent to non-absent, while also keeping all labels. The series will last for as long as offset is, so this would create a 15m blip. It's not super intuitive, but my understanding is that it's true when the series themselves are different. So this won't trigger when the value changes, for instance.

You could move on to adding or for (increase / delta) > 0 depending on what you're working with. This is a bit messy but to give an example:

(
  my_metric
  unless my_metric offset 15m
) > 0
or
(
  delta(
    my_metric[15m]
  )
) > 0
🌐
Compoundent
compoundent.com › FSj › prometheus-alert-on-counter-increase
prometheus alert on counter increase
For a list of trademarks of The Linux Foundation, please see our Trademark Usage page. increase(app_errors_unrecoverable_total[15m]) takes the value of if increased by 1. Prometheus Alertmanager and This feature is useful if you wish to configure prometheus-am-executor to dispatch to multiple ...
🌐
Reddit
reddit.com › r/grafana › alerting on prometheus counter increments without false alarms from query timeouts?
r/grafana on Reddit: Alerting on prometheus counter increments without false alarms from query timeouts?
October 27, 2024 -

I've noticed that transient errors executing alert rule queries cause engineers to get confusing alert notification that're false alarms. They're caused by thing like queries timing out when grafana cloud has blips in availability.

This usually happens because the engineers want an alert notification whenever a counter increments, so they set pending period to None. The default configuration for Alert state if execution error or timeout then causes the failed queries to immediately fire the alert

Suppressing all query errors is of course an option but then we risk suppressing alerts for real issues, like query logic/syntax errors and long-lasting grafana outages

Curious how others are handling this? I've found a solution that seems a bit complicated, which makes me suspicious that we're thinking about counter alerting in an unusual way.

The approach i've been suggesting is:

  • If you want to be alerted within 10 minutes of a counter increment, set the query evaluation interval to 5m and the pending period to 5m

  • Set Alert state if execution error or timeout to "Alerting"

  • Set the query range to >2x the pending period, so `increase(some_counter[610s])`. Not sure if setting it to exactly 2x (10m) risks missing an increment that happens around the time of query execution

That way there has to be two query failures in a row for the alert to fire which so far has been rare

Top answer
1 of 2
7

I think I found a workaround for this.

For counters that existed before t, increase(_metric_[t]) is equivalent to _metric_ - _metric_ offset t. (it's not, but that is a different issue).
For counters that did not exist before t, the increase is simply the metrics value _metric_ - 0 = _metric_.

We can find out whether a metric existed at point t by querying it _metric_ offset t. And we can use that as a WHERE NOT EXISTS filter using the unless operator.

Putting it together, we get following query:

( _metric_ unless _metric offset 1d ) or ( _metric_ - _metric_ offset 1d )
^-----------new counters------------^    ^--------existing counters------^

Example

One event happens each timeframe, we want to measure the increase over 2 timeframes.
Expected:
- none for each query frame before the first occurrence
- one for the query frame on first occurrence
- 2 for each query frame beyond the first occurrence

                               t0  t1  t2  t3  t4  t5
_metric_                       -   -   1   2   3   4
_metric offset 2t              -   -   -   -   1   2
__ unless __ offset 2t         -   -   1   2   -   -
__ <minus> __ offset 2t        -   -   -   -   2   2
=====================================================
() or ()                       -   -   1   2   2   2

Grafana example graph
total is the raw counter value, increase is the result of the query. It is still split in two series because the metric name is dropped on the - operation, but not on unless. But summing them up again works well, and is something you will probably do anyways.
Grafana graph with sum

It's really a shame prometheus makes it so hard for everyone who does not use it to display cpu temperature. This is one of the instances where my pride to have found a solution is only surpassed by my exasperation that it was necessary in the first place.

2 of 2
1

This is a "normal" behaviour. If the metric does not exist before and is then initialized with the value 1, this is not considered in functions like increase() or rate().

To catch the very first error, you need to make sure, that the metric exists from the beginning when your application starts having the initial value 0, then the first incrementatation will trigger your alert.

Find elsewhere
🌐
Stack Overflow
stackoverflow.com › questions › 76508127 › prometheus-alert-when-count-increases-steadily
promql - Prometheus - Alert when count increases steadily - Stack Overflow
June 19, 2023 - B. Metric name is flight_api_calls_to_mq_total, of type counter and the label used status real time metric looks like this - flight_api_calls_to_mq_total{status="",region="EMEA"} 40.0 or flight_api_calls_to_mq_total{status="arrived",region="US"} 10.0 · Alert when status is transit for an hour. Unsure what function can be used for this scenario, does increase() helps here ?
🌐
Robust Perception
robustperception.io › avoid-irate-in-alerts
Avoid irate() in alerts – Robust Perception | Prometheus Monitoring Experts
August 28, 2017 - Say that you have a alert with an expression of irate(my_counter[1m]) > 10 and a for: 5m, which is to say that the per-second rate is over 10 for 5 minutes. If the rate increases to 15 per second you'd expect this to fire in 5 minutes or so. However things aren't so simple. Rarely is it the case that are metrics perfectly steady, especially when things are in an abnormal state. Sure the average might be 15 per second, but it might be 9.5 one instant and 18.7 a moment later.
🌐
Prometheus
prometheus.io › docs › tutorials › alerting_based_on_metrics
Alerting based on metrics | Prometheus
Next run the instrumented ping ... To see the status of the alert visit http://localhost:9090/alerts . Once the condition ping_request_count > 5 is true for more than 10s the state will become FIRING....
🌐
Prometheus
prometheus.io › docs › prometheus › latest › configuration › alerting_rules
Alerting rules | Prometheus
This can be used to prevent situations such as flapping alerts, false resolutions due to lack of data loss, etc. Alerting rules without the keep_firing_for clause will deactivate on the first evaluation where the condition is not met (assuming any optional for duration described above has been ...
🌐
GitHub
github.com › prometheus › prometheus › issues › 11433
Prometheus does not detect counter resets (using increase() or resets()) · Issue #11433 · prometheus/prometheus
October 7, 2022 - ### Prometheus configuration file ```yaml global: evaluation_interval: 30s scrape_interval: 30s external_labels: prometheus: prometheus rule_files: - /etc/prometheus/rules/*.yaml scrape_configs: - job_name: shelly-exporter honor_labels: false metrics_path: /prometheus scheme: http scrape_timeout: 20s static_configs: - targets: - shelly-exporter:8080 · ### Alertmanager version _No response_ ### Alertmanager configuration file _No response_ ### Logs _No response_
Author: prometheus
🌐
Medium
medium.com › @suchitasharma1106 › writing-alerts-in-promql-a-guide-to-prometheus-query-language-and-alert-definitions-e430b53180a9
Writing Alerts in PromQL: A Guide to Prometheus Query Language and Alert Definitions | by Suchita Sharma | Medium
October 7, 2024 - increase(): Shows the total increase in a counter over a specific time range. ... This query shows the increase in HTTP requests in the last hour. avg_over_time(): Returns the average value over a range.
🌐
Grafana
community.grafana.com › time series panel
Monitor that Counter increases by exactly 1 for a given time period - Time Series Panel - Grafana Labs Community Forums
January 18, 2022 - Hi everyone! I have an application that provides me with Prometheus metrics that I use Grafana to monitor. One of these metrics is a Prometheus Counter() that increases with 1 every day somewhere between 4PM and 6PM. I…
🌐
Google Groups
groups.google.com › g › prometheus-developers › c › oBRQwL1qhoc
Alerting within specific time periods
Does the answer have something to do with the last successful scrape (scrapes should be successful during the downtime, just the job run counters won't increment)? Feel free to throw in any other advice you want as well as I'm still learning how to use Prometheus. ... Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message ... For the alert, I would suggest increase() for this style of test.
🌐
Stack Overflow
stackoverflow.com › questions › 76836841 › grafana-alert-when-previous-value-increases
prometheus - Grafana alert when previous value increases - Stack Overflow
So if the counter is showing 5 and then it increases to 6, I want an alert that will fire when this event change happens. ... Yes, you are on right track. Generally increase(my_metric_total[1m]) > 0 should do what you want.
🌐
Reddit
reddit.com › r/prometheusmonitoring › prometheus counters very unreliable for many use-cases, what do you use instead?
r/PrometheusMonitoring on Reddit: Prometheus counters very unreliable for many use-cases, what do you use instead?
April 14, 2025 -

My team switched from datadog to prometheus and counters have been the biggest pain-point. Things that just worked without thinking about it in datadog doesn't seem to have good solutions in prometheus. Surely we can't be the only ones hitting our head against the wall with these problems? How are you addressing them?

Specifically for use-cases around low-frequency counters where you want *reasonably* accurate counts. We use Created Timestamp and have dynamic labels on our counters (so pre-initializing counters to zero isn't viable or makes the data a lot less useful). That being said, these common scenarios have been a challenge:

  • Alerting on a counter increase when your counter doesn't start at zero. We use Created Timestamp gives us more confidence but it worries me that a bug/edge-case will cause us to miss an alert. Catching that would be difficult.

  • Calculating the total number of increments in a time period (ex: $__range). Sometimes short-lived series aren't counted towards the total.

  • Viewing the frequency of counter increments over time as a time series. Seems like aligning the rate and step helps but I'm still wary about the accuracy. It seems like for some time ranges it doesn't work correctly.

  • For calculating a success rate or SLI over some period of time. The approach of `sum(rate(success_total[30d])) / `sum(rate(overall_total[30d]))` doesn't always work if there are short-lived series within the query range. I see Grafana SLO feature uses recording rules, which I hope(?) improves this accuracy, but its hard to verify and is a lot of extra steps (i.e. `sum(sum_over_time((grafana_slo_success_rate_5m{})[28d:5m])) / sum(sum_over_time((grafana_slo_total_rate_5m{} )[28d:5m]))`

A lot of teams have started using logs instead of metrics for some of these scenarios. Its ambiguous when its okay to use metrics and when logs are needed, which undermines the credibility of our metrics' accuracy in general.

The frustrating thing is it seems like all the raw data is there to make these use-cases work better? Most of the time you can manually calculate the statistic you want by plotting the raw series. I'm likely over-simplifying things, and I know there's complicated edge-cases around counter-resets, missed scrapes, etc., however promql is more likely to understate the `rate`/`increase` to account for that. If anything, it would be better to overstate the `rate` since its safer to have a false positive than false negative for most monitoring use-cases. I rather have grafana widgets or promql that works for the majority of times you don't hit the complicated edge cases but overstates the rate/increase when that does happen.

I know this comes across as somewhat of a rant so I just want to say I know the prometheus maintainers put a lot of thought into their decisions and I appreciate their responsiveness to helping folks here and on slack.

Top answer
1 of 2
12
You're absolutely correct. Very slow moving counters are a difficult issue with Prometheus. What we do: Reduce the cardinality for important SLO metrics We try not to include "debugging level" labels. Too many teams try and add ever single label dimension they would want in debugging which makes the couting very sparse. Metrics are designed to tell you that there is a problem at X time. It's meant to notify you that you should go look in the logs for the actual errors. If your error metrics have labels, maybe re-think their use. For singleton use timestamp metrics I've seen some teams use counters for cron job like things that should be using job_started_timestamp_seconds or job_completed_timestamp_seconds, etc. Use accumulator exporters For some things we actually end up using push with statsd to a single accumulator that Prometheus scrapes. This is typically for queue dispatched workers. The modern approach would be to use something like OTel cumulative deltas and a single Otel aggregation collector. Personally I wish teams would stop over-leaning on queue dispatched ephemeral workers. It's much more reliabile and efficient to have long-running workers than workers that only last a few seconds or minutes. IMO, the whole "FaaS" thing is a bad fad in the industry. It's cute, but when I put on my SRE hat, it says nope. Long term idea I have a long-term idea to add a new metrics pipeline within Promethus itself. My marketing name for this is "Materialized Metrics". Essentially taking counter scrapes and turning them back into deltas. Then you specify which lables to sum by /without () and turns them back into counters. This way you can do things like drop instance or other labels from the counters and get back a single counter projection that doesn't suffer as much from the extrapolation errors. I'm still working on the design doc, there are a lot of edge cases and things to think about. EDIT to add I think your title statement is a bit clickbait. "very unreliable for many use-cases" is exaggeration / hyperbole. Normal counters are very reliable for almost all use cases. Especially when following Prometheus best practices.
2 of 2
3
How do you write data into prometheus? Scraping? Remote writes? I use Prometheus as a database for fio metrics with 1s update interval, and it works great. If you do scraping, rate of scraping is defining how well your data are represented. There is no proper way to handle situation when metric 'starts' not at the 0. You can emulate it a bit with logic, but it will be flawed. Normal Prometheus use imply, that you either worry about actual value (for gauges) or worry about increments, may be, increments over time. A lot of short-lived metrics is an anti-pattern for Prometheus. Reduce cardinality, remove excessive labeling via rewriting rules. Use of recording rules is more reliable than you think, if you cover your recording rules with a proper unit tests (promtool test rules). Write a good tests, set up few alerts for slow recording rules processing and you can be sure, that they work reliably. Contrary: no tests and no alerts, you get a broken monitoring which checks ...something. One problem with Prometheus: it uses floats, so counts are not 100% accurate, especially, if you do '+1' for large numbers. At some value you can't do +1 anymore (around 1052, I belive, 1052+1 == 1052).