How do you stop certain observations (like actuator/health traffic) from being recorded using ObservationPredicate?
answer
- ObservationPredicate: boolean test(name, context)
- false -> NoopObservation (no metric, no span)
- multiple predicates = AND (all must pass)
- drop /actuator via ServerRequestObservationContext
- Predicate=drop, Filter=mutate tags, Convention=naming
basics
~20 sRegister an ObservationPredicate on the ObservationRegistry. It's a function of (name, context) returning true/false; if it returns false the observation becomes a no-op and nothing (no metric, no span) is recorded. Use it to filter out noise like /actuator paths.
solid answer
~40 sObservationPredicate is a functional interface — boolean test(String name, Observation.Context context) — registered via observationRegistry.observationConfig().observationPredicate(...). Before an observation starts, the registry consults all predicates; if any returns false the observation is turned into a NoopObservation, so no handler runs and neither metrics nor spans are produced. Predicates are combined with AND semantics (all must pass). The classic use is dropping high-volume, low-value traffic — e.g. return false when the name is HTTP server request and the URI/path starts with /actuator. You can inspect the specific context type (e.g. ServerRequestObservationContext) to read the request. Contrast with ObservationFilter, which does not drop observations but mutates the context (add/rename/remove KeyValues) before stop. Predicate = whether to record; Filter = how to tag; Convention = naming.
code
java · 22 linesimport io.micrometer.observation.ObservationPredicate;
import io.micrometer.observation.ObservationRegistry;
import org.springframework.boot.actuate.autoconfigure.observation.ObservationRegistryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.observation.ServerRequestObservationContext;
@Configuration
class ObservationFilterConfig {
@Bean
ObservationRegistryCustomizer<ObservationRegistry> skipActuator() {
ObservationPredicate predicate = (name, context) -> {
if (context instanceof ServerRequestObservationContext req) {
String uri = req.getCarrier().getRequestURI();
return !uri.startsWith("/actuator"); // false => not recorded
}
return true;
};
return registry -> registry.observationConfig().observationPredicate(predicate);
}
}go deeper
Know a predicate can turn off recording for certain operations.
Write a predicate that inspects ServerRequestObservationContext to skip /actuator and know it yields a NoopObservation.
Explain AND-combination, the predicate/filter/convention split, and when supportsContext is the better tool.
Set org-wide policy for noise reduction and cardinality control; balance predicate-based dropping vs sampling at the tracer.
## The problem it solves Some operations are simply not worth observing: health checks, `/actuator` polling from a load balancer, static assets. Recording them wastes metric cardinality and clutters traces. `ObservationPredicate` is the mechanism to **suppress an observation entirely, before it starts**. ## The interface ```java @FunctionalInterface interface ObservationPredicate { boolean test(String name, Observation.Context context); } ``` - `name` — the observation name (e.g. `http.server.requests`). - `context` — the (subtype of) `Observation.Context`; you can `instanceof`-check it to read request-specific data. - Return **true** = keep/record; **false** = suppress. ## Registration and semantics ```java observationRegistry.observationConfig() .observationPredicate((name, context) -> { if (context instanceof ServerRequestObservationContext req) { String uri = req.getCarrier().getRequestURI(); return !uri.startsWith("/actuator"); // drop actuator traffic } return true; // keep everything else }); ``` In Spring Boot you typically register it via an `ObservationRegistryCustomizer<ObservationRegistry>` bean, or by post-processing the registry. Key semantics: - Predicates are evaluated **when the observation is created/started**. If the result is `false`, Micrometer returns a **`NoopObservation`**: `start()`, `stop()`, handler callbacks — all become no-ops. **No metric, no span** for that operation. - If multiple predicates are registered, they are combined with **AND** — *every* predicate must return `true` for the observation to be recorded. A single `false` suppresses it. ## Predicate vs Filter vs Convention (don't mix them up) These three are the common interview trap: - **`ObservationPredicate`** — *whether to record at all* (drop/keep). Returns boolean. - **`ObservationFilter`** — *mutate the context before stop*: add, rename, or remove `KeyValues` (e.g. add a common `region` tag to every observation, or scrub a sensitive tag). It returns a (possibly modified) `Observation.Context`; it does **not** drop observations. - **`ObservationConvention`** — *how to name the observation and derive its tags* from the context. ## Spring Boot's built-in help Boot already filters some noise: for web requests it exposes properties like `management.observations.http.server.requests.name` and, more relevantly, you can configure ignored/uri patterns via metrics/observation properties. But for custom rules (skip a specific path, skip when a header is present, skip internal cron endpoints), a hand-written `ObservationPredicate` is the direct tool. ## Gotchas - A predicate returning `false` kills **both** the metric and the span — you cannot keep the metric but drop the span with a single predicate. If you need selective behavior per sink, use `supportsContext` on individual handlers instead. - Keep predicates cheap and side-effect-free; they run for every candidate observation. - Reading request details requires knowing the concrete context type (e.g. `ServerRequestObservationContext` for Spring MVC) — guard with `instanceof`. ## When to use Use `ObservationPredicate` to cut volume/noise at the source (health/actuator/static). Use `ObservationFilter` to enforce common tags or redact. Use `ObservationConvention` to standardize names/tags.
- If two ObservationPredicates are registered and one returns true while the other returns false, is the observation recorded?No. Predicates are combined with AND — every predicate must return true. A single false makes it a NoopObservation, so nothing is recorded.
- You want to keep the metric but drop the span for actuator calls. Can one ObservationPredicate do that?No — a predicate suppresses the whole observation (both metric and span). For per-sink behavior, make the specific handler's supportsContext return false for those contexts instead.
saying these in an interview costs you the question
- Thinking a false predicate only drops the metric or only the span (it drops the entire observation)
- Confusing ObservationPredicate (drop) with ObservationFilter (mutate tags)
- Assuming predicates are OR-combined (they're AND)
- Putting side effects / heavy logic in a predicate