Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/changelog/128314.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 128314
summary: Fix NPE in APMTracer through `RestController`
area: Infra/REST API
type: bug
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ private void setSpanAttributes(@Nullable Map<String, Object> spanAttributes, Spa
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() + "]"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
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;
Expand Down Expand Up @@ -560,10 +561,10 @@ private void startTrace(ThreadContext threadContext, RestChannel channel, String
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));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did we get a null in the first place? If the header was passed but empty wouldn't it be an empty string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is a possibility for the map to contain a key mapping to a null list; we wrap headers from netty HttpHeaders in Netty4HttpRequest like this:

// Map.get() implementation
public List<String> get(Object key) {
    return key instanceof String ? httpHeaders.getAll((String) key) : null;
}

It's probably remote, but I decided to err on the safe side.

(To be precise, we did not get a null here, the null was in the http.method attribute, but I wanted to be sure this was not possible elsewhere too)

});
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");
Expand Down
Loading