Fix NPE in APMTracer through RestController (#128314)

Our APMTracer doesn't like nulls - this is a sensible thing, as APM in general does not allow nulls (it only allows a precise set of types).
This PR changes the attribute to a sentinel "" in place of null values. It also makes a small change to APMTracer to give a better error message in case of null values in attributes.
This commit is contained in:
Lorenzo Dematté 2025-05-23 09:32:22 +02:00 committed by GitHub
parent aeafcd26e3
commit 6bf531660c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 11 additions and 3 deletions

View file

@ -0,0 +1,5 @@
pr: 128314
summary: Fix NPE in APMTracer through `RestController`
area: Infra/REST API
type: bug
issues: []

View file

@ -304,6 +304,8 @@ public class APMTracer extends AbstractLifecycleComponent implements org.elastic
spanBuilder.setAttribute(key, (Double) value);
} else if (value instanceof Boolean) {
spanBuilder.setAttribute(key, (Boolean) value);
} else if (value == null) {
throw new IllegalArgumentException("span attributes cannot have a null value");
} else {
throw new IllegalArgumentException(
"span attributes do not support value type of [" + value.getClass().getCanonicalName() + "]"

View file

@ -61,6 +61,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
@ -560,10 +561,10 @@ public class RestController implements HttpServerTransport.Dispatcher {
final Map<String, Object> attributes = Maps.newMapWithExpectedSize(req.getHeaders().size() + 3);
req.getHeaders().forEach((key, values) -> {
final String lowerKey = key.toLowerCase(Locale.ROOT).replace('-', '_');
attributes.put("http.request.headers." + lowerKey, values.size() == 1 ? values.get(0) : String.join("; ", values));
attributes.put("http.request.headers." + lowerKey, values == null ? "" : String.join("; ", values));
});
attributes.put("http.method", method);
attributes.put("http.url", req.uri());
attributes.put("http.method", Objects.requireNonNullElse(method, "<unknown>"));
attributes.put("http.url", Objects.requireNonNullElse(req.uri(), "<unknown>"));
switch (req.getHttpRequest().protocolVersion()) {
case HTTP_1_0 -> attributes.put("http.flavour", "1.0");
case HTTP_1_1 -> attributes.put("http.flavour", "1.1");