Make netty 4.0 attributes definition compatible with Apache Atlas 1.1.0
The issue we are trying to fix here seems to be a result of two concurrent issues.
Cassandra driver's used by atlas 1.1.0 brings in a old version of netty < 4.0.23.
In version 4.0.25 netty raised exception in `UniqueName` class for duplicate name
```
if (map.putIfAbsent(name, Boolean.TRUE) != null) {
throw new IllegalArgumentException(String.format("'%s' is already in use", name));
}
```
This changed in 4.0.26 where exception was not thrown, instead the duplicate key was just ignored.
```
protected UniqueName(String name) {
this.name = checkNotNull(name, "name");
id = nextId.incrementAndGet();
}
```
Now this alone would not be enough. The only way I was able to reproduce is if two different class loaders tries to load the
same class `AttributeKeys` twice.
I tried to look into Atlas source code (which is huge) and I could not find a clear path of how this would be possible.
Further more, looking at some build scripts that a user experiencing this issue provided,
it looks like they are doing everything correctly and there is nothing they should change.
In conclusion, I believe that even if this is not a very clean approach,
we should be resilient to this use case, when a customer using netty <4.0.25 in an
older version of Apache Atlas (or with some sort of class loader behavior).
This commit is contained in:
parent
3884cc088e
commit
fac3a93445
|
|
@ -7,13 +7,42 @@ import io.netty.util.AttributeKey;
|
||||||
import io.opentracing.Span;
|
import io.opentracing.Span;
|
||||||
|
|
||||||
public class AttributeKeys {
|
public class AttributeKeys {
|
||||||
|
|
||||||
public static final AttributeKey<TraceScope.Continuation>
|
public static final AttributeKey<TraceScope.Continuation>
|
||||||
PARENT_CONNECT_CONTINUATION_ATTRIBUTE_KEY =
|
PARENT_CONNECT_CONTINUATION_ATTRIBUTE_KEY =
|
||||||
new AttributeKey<>("datadog.trace.instrumentation.netty40.parent.connect.continuation");
|
new AttributeKey<>(
|
||||||
|
buildContextSpecificKey(
|
||||||
|
"datadog.trace.instrumentation.netty40.parent.connect.continuation"));
|
||||||
|
|
||||||
public static final AttributeKey<Span> SERVER_ATTRIBUTE_KEY =
|
public static final AttributeKey<Span> SERVER_ATTRIBUTE_KEY =
|
||||||
new AttributeKey<>(HttpServerTracingHandler.class.getName() + ".span");
|
new AttributeKey<>(
|
||||||
|
buildContextSpecificKey(HttpServerTracingHandler.class.getName() + ".span"));
|
||||||
|
|
||||||
public static final AttributeKey<Span> CLIENT_ATTRIBUTE_KEY =
|
public static final AttributeKey<Span> CLIENT_ATTRIBUTE_KEY =
|
||||||
new AttributeKey<>(HttpClientTracingHandler.class.getName() + ".span");
|
new AttributeKey<>(
|
||||||
|
buildContextSpecificKey(HttpClientTracingHandler.class.getName() + ".span"));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Netty 4.0 before 4.0.26 handled differently how unique attributes where handled, with 4.0.26+
|
||||||
|
* being more lenient with duplicates. We found a use case in Apache Atlas 1.1.0 where for some
|
||||||
|
* reason, this class gets loaded by multiple class loaders generating an error in 4.0.25- before
|
||||||
|
* an exception was thrown if that attribute was already defined.
|
||||||
|
*
|
||||||
|
* @param simpleKey The logical key assigned.
|
||||||
|
* @return A key scoped to the current class loader in use, if not null.
|
||||||
|
*/
|
||||||
|
private static String buildContextSpecificKey(final String simpleKey) {
|
||||||
|
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
String key = simpleKey;
|
||||||
|
if (contextClassLoader != null) {
|
||||||
|
key =
|
||||||
|
"ClassLoader."
|
||||||
|
+ contextClassLoader.getClass().getName()
|
||||||
|
+ "."
|
||||||
|
+ contextClassLoader.hashCode()
|
||||||
|
+ "."
|
||||||
|
+ key;
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
import datadog.trace.instrumentation.netty40.AttributeKeys
|
||||||
|
import spock.lang.Specification
|
||||||
|
|
||||||
|
class ApacheAtlas1_1_0CompatibilityTest extends Specification {
|
||||||
|
|
||||||
|
def "Netty 4.0 Attributes can be loaded by multiple class loaders in different threads as in Apache Atlas 1.1.0"() {
|
||||||
|
|
||||||
|
expect:
|
||||||
|
AttributeKeys.PARENT_CONNECT_CONTINUATION_ATTRIBUTE_KEY.name().matches(/ClassLoader\..*.datadog\.trace\.instrumentation\.netty40\.parent\.connect\.continuation/)
|
||||||
|
AttributeKeys.SERVER_ATTRIBUTE_KEY.name().matches(/ClassLoader\..*\.datadog\.trace\.instrumentation\.netty40\.server\.HttpServerTracingHandler\.span/)
|
||||||
|
AttributeKeys.CLIENT_ATTRIBUTE_KEY.name().matches(/ClassLoader\..*\.datadog\.trace\.instrumentation\.netty40\.client\.HttpClientTracingHandler\.span/)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue