Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,32 @@
public final class RemoteHostnameAdder extends TagsPostProcessor {
private final Supplier<String> hostnameSupplier;

private TagMap.Entry cachedHostEntry = null;

public RemoteHostnameAdder(Supplier<String> hostnameSupplier) {
this.hostnameSupplier = hostnameSupplier;
}

@Override
public void processTags(
TagMap unsafeTags, DDSpanContext spanContext, AppendableSpanLinks spanLinks) {
if (spanContext.getSpanId() == spanContext.getRootSpanId()) {
unsafeTags.put(DDTags.TRACER_HOST, hostnameSupplier.get());
if (spanContext.getSpanId() != spanContext.getRootSpanId()) {
return;
}

String hostname = hostnameSupplier.get();
if (hostname == null) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is subtle change in behavior from before.
TagMap.put would have failed with an exception when given null.

I've decided to just ignore hostnameSupplier.get returning null instead.

return;
}

TagMap.Entry cachedHostEntry = this.cachedHostEntry;
if (cachedHostEntry != null && hostname.equals(cachedHostEntry.objectValue())) {
unsafeTags.set(cachedHostEntry);
return;
}
Comment on lines +30 to +34
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Out of curiosity, is it better to check to cache before checking if hostname is null? Wonder which case would happen more frequently and is the one that we should optimize for.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That's a good point. My interpretation of the code is that a null return from hostNameSupplier isn't really expected, so checking the cache first probably does make sense.

Copy link
Copy Markdown
Contributor Author

@dougqh dougqh Apr 1, 2026

Choose a reason for hiding this comment

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

Ah, I see now. I was being conservative in my approach.

I wasn't assuming that hostnameSupplier.get() always produces the same value, so I have to call it anyway to check if the cached value matches the current value.
And because I didn't want to assume that it wasn't null, I'd have to call Object.equals which would incur a null check anyway.

I suppose as written, I could let a null hostName flow into cachedHostEntry.objectValue().equals.
But arguably, I'd be better reversing that equal check to take advantage of the more detailed type information on hostname (being String rather than Object).

That would allow for static devirtualization rather than profiled based devirtualization, but I have to keep the null check first.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the explanation, makes sense to me!


TagMap.Entry newEntry = TagMap.Entry.create(DDTags.TRACER_HOST, hostname);
unsafeTags.set(newEntry);
this.cachedHostEntry = newEntry;
}
}
Loading