Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring Boot metrics: bound tag values instead of tracking each receipt

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

A Micrometer meter identity includes its name and tags, so a new tag value can create another series rather than another sample in the same series.

Download Spring source kit

The downloadable Spring source kit pins Java 21 and Spring Boot 4.0.8 with its managed dependencies. Run mvn test to check the named fixture.

Model a finite outcome set

The import metric has two outcomes: ACCEPTED and REJECTED. BoundedImportMetrics receives that enum rather than arbitrary strings. Recording one hundred accepted records and one rejected record creates exactly two local meters, with the accepted counter at one hundred.

The test uses SimpleMeterRegistry so the identity count is visible without a remote backend. Adding receipt IDs, email addresses or request paths containing identifiers would change both retained state and exported series count. Such values also risk placing sensitive data in telemetry.

Local meter count is not backend cost

A remote monitoring system may retain older time series after an application stops exporting them. Multiplying finite tag dimensions can still create many combinations: tenant, region and outcome counts must be budgeted together. A bounded enum only constrains the dimension it owns.

Use logs or traces with an explicit retention and privacy policy when investigating a specific record. Do not solve cardinality by silently dropping a business metric without checking what operations needs to answer. Health probes tell a different story from import counters.

Checked source

Java
package in.aitrove.contracts;
import io.micrometer.core.instrument.MeterRegistry;
public class BoundedImportMetrics {
    public enum Outcome { ACCEPTED, REJECTED }
    private final MeterRegistry registry;
    public BoundedImportMetrics(MeterRegistry registry) { this.registry=registry; }
    public void record(Outcome outcome) {
        registry.counter("receipt.import.records", "outcome",outcome.name()).increment();
    }
}

Test the boundary

FrameworkBoundaryTest.enumOutcomeBoundsMeterIdentities checks this contract in the source kit. Excerpts belong to the named classes; use the downloadable files for imports, configuration and assertions.

Costs and boundaries

The fixture retains two counter identities and increments in constant application work. Real exporter buffering, scraping and backend retention add costs not measured by this test. No remote metrics endpoint, dashboard or production alert threshold is supplied.

Common Mistakes

  • Do not use receipt IDs as metric tags.
  • Bound the product of tag dimensions, not only one dimension.
  • Do not infer backend retention cost from a local registry test.

Read next

Spring Boot Actuator health: public liveness without public diagnostics, Spring cache keys: separate tenants and test the loader count, Spring task executors: capacity, rejection and lost context, Java LongAdder: striped counters and the limits of sum snapshots.

Compare the Python boundary

Python logging: include bounded context without printing sensitive payloads.

Continue with scheduled relay checks

Continue with Spring relay metrics: measure backlog without event-ID labels.

spring
spring-boot
metric-cardinality
Storage details