What Is a Counter in OpenTelemetry?
A Counter is the simplest and most common metric instrument in OpenTelemetry: a number that only goes up, used to count how many times something has happened. This guide explains it from zero, with analogies, diagrams and real-world patterns.
Look at the odometer in a car. It shows how many kilometers the car has travelled since the day it was built. It never goes backward, even when you reverse down the driveway. When you stop for lunch, the number stays where it is. When you drive again, it keeps climbing. If you want to know how fast you drove yesterday, you do not need a special gadget: you simply read the odometer today, subtract yesterday’s reading, and divide by the time. A Counter in OpenTelemetry works exactly like that odometer. It is a number that only grows, and its power comes from comparing readings over time.
1Why We Need to Count Things
Before learning the tool, understand the question it answers.
Every running application does things over and over: it serves web pages, processes payments, reads from databases, sends emails and retries failed work. The people who run these applications constantly ask simple questions. How many orders did we process today? How many requests failed in the last hour? How many emails were sent? Is the number of errors growing? Are we getting busier than last week?
All of these are counting questions. Answering them by reading log files would be slow and costly, because someone would have to search millions of lines and count by hand. A much better approach is to have the application keep a small running tally for each thing worth counting and to report that tally regularly. That tally is what we call a metric, and the simplest kind of metric tally is the Counter.
Think of the clicker that a security guard at a stadium gate holds in his hand. Every time a visitor walks in, he presses it once. He does not write names or track who came first. He just keeps one growing number, and at the end of the day he knows how many people arrived. That clicker is a Counter.
2A Quick Map of OpenTelemetry Metrics
A short refresher on the surrounding vocabulary makes everything easier.
OpenTelemetry, often called OTel, is an open-source project that defines how software describes its own behavior. It is vendor neutral, which means it does not belong to any one monitoring company. It describes three kinds of data, called signals: traces, metrics and logs. This guide lives in the world of metrics, which are numbers measured over time.
Meter Provider
The factory and manager for all metrics in an application. It is set up once, usually when the application starts.
Meter
A named group of instruments, often one per library or component. Think of it as a labeled drawer that holds related tools.
Instrument
The actual tool that records measurements. A Counter is one kind of instrument.
Reader and Exporter
The parts that collect the current values on a schedule and send them to the place where people look at charts.
Remember the chain: a meter provider hands out meters, a meter hands out instruments, and an instrument records numbers. A Counter is simply the instrument you use when the number should only grow.
3So, What Exactly Is a Counter?
A Counter is a synchronous instrument that records values which only ever increase.
Let us define it carefully. A Counter in OpenTelemetry is a metric instrument used to record a value that accumulates over time and can only go up. You use it by calling an add operation each time something happens, and each call adds a non-negative amount to the running total. Most of the time you add exactly one, such as one more request served. Sometimes you add a bigger number, such as the number of bytes in a response.
The two most important properties are the word monotonic and the word synchronous. Monotonic means the value never decreases. Synchronous means that your own code calls the instrument right at the moment the event happens, as part of the normal flow of work. We will look closely at both ideas.
An event happens
A customer places an order, a request arrives, or an error is caught.
The code adds to the Counter
The application tells the Counter to add one, or another non-negative amount.
The SDK keeps the running total
Inside the application, the OpenTelemetry library stores the growing sum in memory.
The total is exported on a schedule
Every so often, the current total is sent to a backend, where it is stored and charted.
A Counter does not store a list of events. It stores one number. You cannot ask a Counter which order was number five. You can only ask how many orders there have been in total.
4The Golden Rule: It Only Goes Up
The one-way nature of a Counter is not a limitation. It is the whole point.
You might wonder why a Counter refuses to go down. Surely it would be more flexible to allow both directions. The answer is that the one-way promise makes the data far easier to understand and far more reliable when it travels through many systems.
When a value only increases, any tool reading it can make safe assumptions. If the reading today is bigger than the reading yesterday, the difference is exactly the number of events in between. If a reading ever appears smaller than the previous one, the tool knows something special happened, usually that the application restarted and began counting from zero again. Tools can then adjust for the reset instead of drawing a false drop on the chart.
A turnstile at a metro station only turns one way. Because it is one-way, the number on its meter is trustworthy: every click is a person who entered. If it could spin backward, you could never be sure whether a lower number meant people left or the meter was tampered with.
What if I try to add a negative number?
The specification says a Counter should only accept non-negative values. If code tries to add a negative number, the library is expected to ignore it, and it may log a warning. This protects the promise that the total never goes down.
What if I need a number that goes up and down?
Then a Counter is the wrong tool. For things like the number of people currently in a queue, which rise and fall, OpenTelemetry offers a different instrument called the UpDownCounter. We compare them in a later chapter.
5Synchronous vs Asynchronous Counters
OpenTelemetry offers two ways to feed a Counter, depending on who does the counting.
The regular Counter is synchronous. Your code is in charge. Whenever the event happens, your code calls add. This is the natural choice for events your application itself performs, such as handling a request or processing an order.
The second style is the asynchronous Counter, also called an observable Counter. Here, you do not call add on every event. Instead, you register a small function called a callback. Every time the library is about to collect metrics, it calls your function, and your function simply reports the current total. This is useful when the total already lives somewhere else and you merely want to read it, for example a total kept by the operating system, such as the number of bytes a network card has sent since boot.
| Question | Synchronous Counter | Asynchronous Counter |
|---|---|---|
| Who triggers the update? | Your code, at the moment of each event | The library, on each collection cycle |
| What do you report? | The amount to add right now | The current total, already accumulated |
| Best when | Your code performs the events being counted | Another system already keeps the running total |
| Typical example | Requests handled by a web service | Total bytes sent by a network card since boot |
| Cost per event | A tiny operation on every event | No cost per event, one read per cycle |
A synchronous Counter is like writing a tally mark on a wall each time a customer enters your shop. An asynchronous Counter is like glancing at the electricity meter outside your shop once an hour and writing down the reading. The meter was counting all along. You just look at it when needed.
If your program causes the event, use the synchronous Counter. If you are only reporting a total that someone else already maintains, use the asynchronous one.
6What Should You Count?
Good Counters answer questions people actually ask.
A Counter fits anything where you care about the total number of occurrences. The key test is simple: does it only make sense to ask how many so far, and would the number never need to shrink? If yes, it is probably a Counter.
Requests served
Every time a web service answers a call, add one. The growth of this number over time tells you how busy the service is.
Errors encountered
Count failures separately from successes. A sudden jump in the growth of the error count is often the first sign of trouble.
Orders, signups and payments
Business events make excellent Counters. They connect engineering metrics to the things the company cares about most.
Bytes sent or received
Here you add the size of each message instead of adding one. The total shows how much data your service has handled.
Retries and timeouts
Counting retries reveals hidden instability: a service may look healthy while quietly retrying many calls behind the scenes.
Cache hits and misses
Two separate Counters, one for hits and one for misses, let you compute how effective your cache is.
You can add amounts bigger than one. Counting bytes, items in a batch or money processed are all natural uses, as long as the amount is never negative.
7What Should You NOT Count with a Counter?
Knowing the limits prevents the most common beginner mistakes.
Counters are wonderful, but they are not a universal tool. Picking the wrong instrument gives you confusing charts. Here are things that look like Counter candidates but are not.
Problem
Using a Counter for something that goes up and down, such as the number of active users right now or the length of a queue.
Why It’s Harmful
A Counter cannot go down, so the number would show total arrivals, not the current size. The chart would keep climbing even when the queue is empty.
Correct Approach
Use an UpDownCounter or a Gauge for values that rise and fall.
Problem
Using a Counter to track how long operations take, by adding the duration each time.
Why It’s Harmful
You would get the total time spent, but lose the shape of the data. You could not tell whether most requests are fast and a few are very slow.
Correct Approach
Use a Histogram, which records the distribution of values such as latency.
Problem
Using a Counter for a current reading, such as temperature, memory in use or CPU percentage.
Why It’s Harmful
These readings are snapshots, not accumulations. Adding them together over time is meaningless.
Correct Approach
Use a Gauge, which reports the current value at the moment of collection.
Problem
Trying to make a Counter go down by adding negative numbers when something is undone, such as a cancelled order.
Why It’s Harmful
The library will ignore negative additions, so your numbers silently stop matching reality.
Correct Approach
Create a second Counter for cancellations and compare the two, or use an UpDownCounter if a live balance is what you truly want.
8Counter vs Other Instruments
A side-by-side comparison makes the right choice obvious.
OpenTelemetry offers several instruments, each designed for a different shape of question. The easiest way to choose is to ask what the number does over time and what question you want to answer.
| Instrument | What the value does | Question it answers | Everyday example |
|---|---|---|---|
| Counter | Only goes up | How many times has this happened? | Requests served |
| UpDownCounter | Goes up and down by steps | What is the current balance? | Items waiting in a queue |
| Histogram | Records a spread of values | How are the values distributed? | Response times |
| Gauge | Reports the latest reading | What is the value right now? | Room temperature |
flowchart TD
Q1{"Does the value only ever grow?"}
Q1 -->|"Yes, and I want a total of events"| C["Counter"]
Q1 -->|"No, it rises and falls by steps"| U["UpDownCounter"]
Q1 -->|"No, it is a reading at a moment"| G["Gauge"]
Q1 -->|"I care about the spread of values"| H["Histogram"]
Think of four household gadgets. The Counter is the odometer in your car, the UpDownCounter is the number of books currently checked out from your shelf, the Gauge is the thermometer on the wall, and the Histogram is a record of how long each of your phone calls lasted.
9Names, Units and Descriptions
A good Counter introduces itself clearly so that strangers can understand it.
When you create a Counter, you give it a few pieces of descriptive information. These matter more than beginners expect, because the person reading a chart six months later will not remember what you meant.
Name
A short, clear, dotted name such as http.server.requests or orders.placed. It must be unique within a meter and should describe what is being counted.
Unit
What each count means, such as bytes, seconds or a plain curly-braced label like {request}. Units stop confusion between kilobytes and megabytes.
Description
A one-sentence human explanation that appears in tools. It is the label on the jar.
Naming habits that help
Use lowercase words separated by dots to build a clear hierarchy, from general to specific. Do not stuff units or the word total into the name when the unit field already says it, since many backends add such suffixes automatically. Keep names stable, because renaming a Counter breaks charts and alerts that depend on the old name. Follow the OpenTelemetry semantic conventions whenever one exists for what you are counting, so that your numbers line up with those of other teams and tools.
Before inventing a name, check whether the semantic conventions already define one for your case, such as for HTTP requests or database calls. Using the shared name gives you ready-made dashboards for free.
Creating the same Counter again and again inside busy code. A Counter should be created once, when the program starts, and reused. Recreating it for every event wastes effort and can cause confusing warnings.
10Attributes: Slicing One Counter into Many Series
Attributes are labels that let a single Counter answer many questions.
Counting all requests together is useful, but usually not enough. You also want to know how many requests were successful versus failed, how many came to each route, or how many came from each region. Instead of creating a separate Counter for every combination, you attach attributes to each addition. An attribute is a small key and value pair, such as the status of the response or the route that was called.
Behind the scenes, OpenTelemetry keeps a separate running total for every unique combination of attribute values. Each one is called a time series. A backend can then show the total of everything, or break it down by any attribute you recorded.
flowchart LR
A["Counter: http.server.requests"] --> B["Series: route is checkout, status is 200"]
A --> C["Series: route is checkout, status is 500"]
A --> D["Series: route is search, status is 200"]
A --> E["Series: route is search, status is 404"]
Imagine one big bakery sales book. Instead of writing only the total number of loaves sold, the clerk keeps separate tally columns for each kind of bread. The book is still one book, but it now answers questions like how many sourdough loaves were sold compared with baguettes.
A good attribute is small and stable
The best attributes have a small, known set of possible values, such as the HTTP method, the status class, the region or the name of a route pattern. These give tidy, readable breakdowns and cost little to store.
11The Cardinality Trap
The most expensive mistake with Counters is adding labels that have too many possible values.
Because every unique attribute combination creates a new series, the number of series can explode if you choose attributes carelessly. This number of possible combinations is called cardinality. High cardinality means huge memory use in your application, large bills at your monitoring vendor, and slow dashboards.
Suppose you add the customer’s user identifier as an attribute to a request Counter. If you have one million users, you may create a million separate series for one Counter. If you add a request identifier, which is different every single time, you create a brand-new series for every event, and the Counter stops being a summary and becomes a very expensive log.
Safe Attributes
- HTTP method such as get or post
- Status class such as success or server error
- Route pattern such as the template of a path
- Region or environment name
- Service version
Dangerous Attributes
- User identifiers or email addresses
- Request identifiers or trace identifiers
- Full web addresses with changing parts
- Timestamps or random numbers
- Free-text error messages
A single careless attribute can multiply your metrics bill many times over. If a value is unbounded or unique per event, it belongs in a trace or a log, not in a metric attribute.
OpenTelemetry includes a limit on how many series one instrument may create, and it can fold extra combinations into an overflow series. Views, covered next, can also remove attributes you do not want. These help, but choosing good attributes in the first place is the real solution.
12What Happens Inside: From Add to Chart
Let us follow a single increment from your code all the way to a dashboard.
Understanding the journey helps you reason about delays, resets and missing data. Here is what happens when an application serves a request and counts it.
Code adds to the Counter
The application records that one more request was served, along with attributes such as the route and status.
The SDK aggregates in memory
The library finds the series matching those attributes and adds to its running sum. No network call happens yet. This keeps the cost per event tiny.
A reader wakes up on a timer
A metric reader collects the current sums of all series at a regular interval, commonly about once a minute by default.
An exporter sends the snapshot
The exporter packages the sums and sends them to a Collector or backend using a standard protocol.
The backend stores and charts
The backend stores each series over time, computes rates by comparing readings, and draws charts and alerts.
sequenceDiagram
participant App as Application Code
participant SDK as SDK Aggregator
participant R as Metric Reader
participant E as Exporter
participant B as Backend
App->>SDK: Add 1 with attributes
App->>SDK: Add 1 with attributes
App->>SDK: Add 1 with attributes
Note over SDK: Running sum grows in memory
R->>SDK: Collect on timer
SDK-->>R: Current sums
R->>E: Hand over snapshot
E->>B: Send metrics
Notice that a million increments do not cause a million network messages. They are folded into one number per series and sent once per interval. That is why Counters are cheap even in very busy code.
13Aggregation: Why a Counter Becomes a Sum
The raw additions are folded into a summary called a sum.
OpenTelemetry separates the act of recording from the way recorded values are summarized. The act of recording is what your code does with the Counter. The summary is called the aggregation. For a Counter, the default aggregation is a Sum, and because the Counter never decreases, that sum is marked as monotonic. This marker tells backends they may safely compute rates.
Why not send every single addition? Because that would be as heavy as logging every event. By summing inside the application, the system trades individual detail for low cost and high speed, which is exactly the right trade for a metric.
A cashier does not read out every single sale to the manager. At the end of each hour she reports one number: the total collected so far. The manager gets what he needs without hearing about every coin.
Because individual events are summed away, you cannot recover details of a single event from a Counter. If you need to inspect one specific request, use traces or logs alongside your metrics.
14Cumulative vs Delta Temporality
There are two ways to report a growing total, and backends have preferences.
When the Counter’s sum is sent out, it can be described in one of two styles, called temporality. This single concept causes a lot of confusion, but the analogy of a car makes it easy.
Cumulative
Each report says the total since the program started, like the car odometer. The numbers always grow, and a rate is computed by subtracting two readings.
Delta
Each report says only the change since the last report, like the trip meter you reset at every stop. Each number stands alone and shows what happened in that interval.
| Interval | Real events in the interval | Cumulative report | Delta report |
|---|---|---|---|
| Minute 1 | 10 | 10 | 10 |
| Minute 2 | 5 | 15 | 5 |
| Minute 3 | 20 | 35 | 20 |
| Minute 4 | 0 | 35 | 0 |
Which should I choose?
The choice usually depends on the backend. Systems built around scraping and computing rates from growing totals prefer cumulative. Some systems prefer delta because it uses less memory in the application and is naturally robust when a program restarts. OpenTelemetry lets the metric exporter choose the temporality, and the Collector can convert between the two in many cases.
You rarely need to decide this at the Counter level. The exporter or Collector configuration handles it. Just check what your backend expects, and match it.
15Restarts, Resets and Rates
The total on its own is rarely what you chart. The rate is.
A cumulative Counter that says three million requests so far is hard to interpret. Is that a lot? Is it growing? What people really want is the rate: how many requests per second are happening now. Backends compute this by taking two readings, subtracting, and dividing by the elapsed time. That is why the monotonic promise is so valuable.
What happens when the program restarts?
When an application restarts, its in-memory Counter begins again from zero. A naive chart would show a sudden crash to zero. Because the Counter is known to be monotonic, tools detect any drop as a reset and treat the post-restart value as growth from zero. OpenTelemetry also records the start time of each series, which helps backends recognize resets precisely.
flowchart LR
A["Reading at 10:00 is 1000"] --> B["Reading at 10:01 is 1060"]
B --> C["Restart at 10:01:30"]
C --> D["Reading at 10:02 is 40"]
D --> E["Tool detects the drop as a reset and still computes a sensible rate"]
If the odometer in a rented car is replaced with a brand-new one showing 40 kilometers, you do not conclude that the driver reversed a thousand kilometers. You realize the meter was swapped, and you add the new reading to the old total.
Do not chart the raw total of a Counter and expect to read health from it. Always look at its rate or its increase over a time window. The raw total is mostly a reference value for the tools to subtract.
16Views: Reshaping Counters Without Changing Code
Views let operators adjust how a Counter is reported, with no code edits.
Sometimes the people who run the application want to change how a metric is reported without asking developers to modify and redeploy code. OpenTelemetry provides views for this purpose. A view is a rule, set up in the SDK configuration, that selects one or more instruments and changes how they are aggregated or presented.
Drop unwanted attributes
If a library adds a high-cardinality attribute you do not want, a view can remove it so that it never creates extra series.
Rename a metric
A view can present a Counter under a different name so that it matches your company’s naming standards.
Turn a metric off
A view can drop an instrument entirely, which is handy when a third-party library produces metrics you do not need and do not want to pay for.
Views are a cost-control tool. They give platform teams a safety valve against runaway cardinality in code they do not own.
17Counters and the Rest of Observability
Counters work best when they cooperate with traces and logs.
Metrics are the early warning system. They are cheap, fast and great for spotting that something changed. But a Counter tells you only that errors increased, not which request failed or why. For that you need traces and logs. A healthy workflow uses all three together.
Metrics notice
The rate of a failure Counter rises above its normal level and an alert fires.
Traces locate
The engineer opens example failing traces and sees which service and step is responsible.
Logs explain
Logs linked to those traces show the exact error message and context.
A smoke detector tells you that something is burning, which is the metric. The security camera shows which room, which is the trace. The room’s diary tells you exactly what the cook was doing, which is the log. You want all three.
Some backends can attach example traces, called exemplars, to metric points. A spike on a Counter chart can then link straight to a real request that contributed to it.
18Alerting and Dashboards with Counters
The real payoff of counting comes when people and tools act on the numbers.
Counters are the raw material for many of the most important charts and alerts in operations. Because they are cheap and precise, teams build their basic health picture on them.
Request Rate
The growth of a request Counter shows traffic volume. A sudden fall to nearly zero often means an outage upstream.
Error Rate
Divide the growth of the error Counter by the growth of the request Counter. A percentage is easier to judge than a raw number.
Business Throughput
Orders or signups per hour link technical health to company results. A dip may signal a bug before customers complain.
Budget Burn
Teams that promise a reliability target use good-event and bad-event Counters to see how fast they are using their allowed failures.
Alerting on the raw growing total. It will always rise, so such an alert is either always firing or never useful. Alert on rates and ratios over a time window instead.
19Best Practices and Common Mistakes
A short checklist that saves hours of confusion later.
Create Counters Once
Build each instrument at startup and reuse it everywhere, instead of recreating it for every event.
Pick Bounded Attributes
Choose labels with a small, known set of values so series counts stay predictable.
Set a Unit and Description
Future readers will thank you. A unit removes doubt about what one count means.
Follow Semantic Conventions
Shared names and attributes make dashboards portable across teams and tools.
Count Successes and Failures Together
Use one Counter with a status attribute, so ratios are easy and consistent.
Add Unbounded Labels
User identifiers, request identifiers and free text will explode your series count.
Use a Counter for Rising and Falling Values
Reach for an UpDownCounter or Gauge when the value can shrink.
Rename Casually
Changing a name breaks charts and alerts. Plan names carefully and keep them stable.
If a Counter seems to show no data, check three basics: is the meter provider configured, is the exporter reaching the backend, and has enough time passed for at least one collection cycle to run?
20Advantages and Trade-offs
Every design choice has a price, and Counters are no exception.
Advantages
- Extremely cheap to record, even in very busy code
- Simple to understand: it only goes up
- Safe to compute rates, even across restarts
- Perfect for traffic, errors and business throughput
- Small data size compared with logs or traces
- Standard across languages and backends
Disadvantages / Trade-offs
- No detail about individual events
- Cannot represent values that decrease
- Careless attributes cause cardinality explosions
- Metrics appear with a delay equal to the export interval
- Raw totals are hard to read without rate calculations
Balancing detail and cost
Every attribute you add increases the detail you can see, and also the cost you must pay. A Counter with no attributes is nearly free but answers only one question. A Counter with a handful of well-chosen attributes answers many questions at modest cost. A Counter with unbounded attributes answers everything and bankrupts your monitoring budget. The craft lies in choosing the middle path.
21Real-World Examples
Seeing how teams use Counters makes the ideas concrete.
An online retailer on sale day
The retailer counts orders placed, with a payment-method attribute. During the sale, the growth rate of the order Counter shows traffic tripling, and a drop in one payment method’s growth reveals a broken integration within minutes.
A streaming service tracking playback failures
Two Counters, one for playback starts and one for playback errors, give an error ratio per device type. A rising ratio for one device family leads engineers straight to a faulty app version.
A bank counting retried transfers
The bank counts retries separately from first attempts. A slow rise in retries warns about an unstable partner service long before customers see outright failures.
A platform team controlling costs
After noticing a huge bill, the team finds a Counter labeled with user identifiers. A view removes that attribute, series counts fall dramatically, and the bill shrinks with no code change.
A data pipeline measuring throughput
A batch job adds the number of records processed to a Counter after each batch. The growth rate shows records per second and warns when processing slows.
22Frequently Asked Questions
It is a metric instrument that records a running total of how many times something has happened, and that can only ever increase.
Not while the program is running. Negative additions are ignored. A Counter can appear to drop only when the program restarts and begins again from zero, and tools handle that as a reset.
It means the value never decreases. It may stay the same or grow, but it never shrinks.
Use it when the quantity rises and falls by steps, such as items waiting in a queue or connections currently open.
A Counter accumulates events and only grows. A Gauge reports a current reading, such as temperature, which may go up or down freely.
No. Use a Histogram, which keeps the distribution of values. A Counter of total time hides whether most requests are fast and a few are very slow.
It is a Counter whose total is reported through a callback at collection time, used when another system already keeps the running total and you simply read it.
Attributes are labels that split a Counter into separate series. They are risky when they have many possible values, because each unique combination creates a new series and raises memory use and cost.
You are probably charting the raw cumulative total. Chart the rate or the increase over a time window instead, which shows how fast events are happening.
Cumulative reports the total since the start, like a car odometer. Delta reports only the change since the last report, like a resettable trip meter.
On the metric reader’s interval, commonly about once a minute by default. Many additions are folded into one number per series between exports.
Very little. Each addition is a tiny in-memory operation. The heavy work of exporting happens rarely and off the main path.
Yes. Views in the SDK configuration can rename, drop or reshape Counters and remove unwanted attributes.
23Summary and Key Takeaways
We began with the odometer in a car, a number that only climbs and that tells its story when you compare two readings. A Counter in OpenTelemetry is exactly that: a simple, cheap, one-way instrument for counting events such as requests, errors, orders and bytes. Your code adds to it, the SDK folds the additions into a running sum, a reader exports the sum on a schedule, and the backend turns it into rates, charts and alerts. Choose its attributes with care, pick the right instrument when a value can go down or needs a distribution, and the humble Counter will quietly carry a large share of your daily observability work.
Key Takeaways
- A Counter only goes up — it records a running total of events, and negative additions are ignored, which makes the data safe to turn into rates.
- Synchronous or asynchronous — use the regular Counter when your code causes the event, and the observable Counter when you are reading a total that something else maintains.
- Choose the right instrument — use an UpDownCounter for values that rise and fall, a Gauge for current readings, and a Histogram for distributions such as latency.
- Attributes slice one Counter into many series — keep them small and bounded, because every unique combination adds memory and cost.
- Beware cardinality — never use user identifiers, request identifiers or free text as attributes, and use views to remove them when they sneak in.
- The sum is exported periodically — additions are aggregated in memory and sent on an interval, in cumulative or delta style depending on what your backend prefers.
- Chart rates, not raw totals — the growth of a Counter over time is what carries meaning, and resets from restarts are handled automatically by the tools.