Performance & Optimization
Observability
- Three signals: logs (events), metrics (aggregates over time), traces (request paths across services)
- OpenTelemetry is the vendor-neutral standard — instrument once, export anywhere
- Java auto-instrumentation: the OTel Java agent wires HTTP/JDBC/gRPC spans with zero code
- Metrics via Micrometer (Spring's default) → Prometheus/OTLP; alert on symptoms (SLOs), not causes
- Correlate: trace-id in every log line joins the three signals
- JVM-specifics: export GC pause time, heap after-GC, thread states, JFR streams
OCNJ's cloud-native premise: with dozens of service instances appearing and disappearing, attaching a profiler to "the slow box" is over — telemetry must be always on, centrally aggregated, and correlated. A request's story: the trace shows which hop spent the time; that span's attributes and the correlated logs say why; metrics say whether it's one request or all of them. Design dashboards around questions ("why is p99 up?"), not around data you happen to have.
# Zero-code start: the agent instruments common libraries automatically
$ java -javaagent:opentelemetry-javaagent.jar \
-Dotel.service.name=orders \
-Dotel.exporter.otlp.endpoint=http://collector:4317 \
-jar orders.jar
// Custom spans where business logic needs visibility:
Span span = tracer.spanBuilder("price.calculate").startSpan();
try (Scope s = span.makeCurrent()) {
return engine.price(order);
} finally {
span.end();
}JVM signals worth exporting (OCNJ ch. 10–11): GC pause totals and max (the latency suspect #1 — Gc Tuning Logging), heap-after-GC (the leak trend), allocation rate, thread counts by state (a BLOCKED pile-up is a lock story), and JFR event streams (JFR Streaming, Java 14+, feeds live JVM internals to your pipeline). Correlating a p99 spike with a GC pause — or proving the absence of that correlation — is the single most common observability win in Java services.