When implementing metrics and telemetry in your application, avoid using dynamic values like path parameters or user IDs directly as metric tags or dimensions. This practice causes cardinality explosion, which leads to excessive memory usage, degraded performance, and can overwhelm your monitoring systems.

Instead:

  1. Use route templates rather than actual paths:
  2. For high-cardinality data like tenant IDs or user identifiers:

Example of proper implementation:

// WRONG: Will cause cardinality explosion
@Path("template/path/{value}")
public class PathTemplateResource {
    @GET
    public String get(@PathParam("value") String value) {
        // Don't do this - adds a high-cardinality tag
        ContextLocals.put("metric-tag", value);
        // ...
    }
}

// CORRECT: Uses route templates instead
@Path("template/path/{value}")
public class PathTemplateResource {
    @GET
    public String get(@PathParam("value") String value) {
        // For tracing/debugging, put in span attributes instead
        Span.current().setAttribute("path.value", value);
        // ...
    }
}

Remember that for each unique tag value, you multiply the number of time series across all other dimensions (methods, status codes, endpoints), which can quickly overwhelm your metrics system.