Class `FieldBackedProvider` uses ByteBuddy to add a field and its respective getters and setters to store the context object.
Assuming that we have a class `A` that implements runnable and that we wrap with a `FieldBackedProvider`
`Runnable` interfaces, if later on we use a cglib's `Enancher` class on `A` then the our mechanism will kick in again and try
to add the methods again. This causes a `java.lang.ClassFormatError: Duplicate method name "get__datadogContext$java$lang$Runnable" with signature "()Ljava.lang.Object;"`
to be thrown because CGLIB already copied over those methods from the original class `A` to the newly created class.
With this commit we now check that method were not previously defined before adding them, and if they were then we avoid adding them
again.
The reason why it wasn't faiing before is that we only checked on context field existence, not methods and cglib do not copy over fields, it copies only methods. E.g.
```
public class Main {
public static class A {
private String name = "hey";
public String getName() {
return this.name;
}
}
public static void main(String[] args) {
System.out.println("----- 'A' declared fields -----");
A s = new A();
for (Field f : s.getClass().getDeclaredFields()) {
System.out.println("field: " + f.getName());
}
for (Method m : s.getClass().getDeclaredMethods()) {
System.out.println("method: " + m.getName());
}
System.out.println("----- Proxy declared fields -----");
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(A.class);
enhancer.setCallback((FixedValue) () -> null);
A proxy = (A) enhancer.create();
for (Field f : proxy.getClass().getDeclaredFields()) {
System.out.println("field: " + f.getName());
}
for (Method m : proxy.getClass().getDeclaredMethods()) {
System.out.println("method: " + m.getName());
}
}
}
```
Results in:
```
----- 'A' declared fields -----
field: name
method: getName
----- Proxy declared fields -----
field: CGLIB$BOUND
field: CGLIB$FACTORY_DATA
field: CGLIB$THREAD_CALLBACKS
field: CGLIB$STATIC_CALLBACKS
field: CGLIB$CALLBACK_0
field: CGLIB$CALLBACK_FILTER
method: equals
method: toString
method: hashCode
method: clone
method: getName
method: newInstance
method: newInstance
method: newInstance
method: setCallbacks
method: CGLIB$SET_STATIC_CALLBACKS
method: CGLIB$SET_THREAD_CALLBACKS
method: getCallback
method: getCallbacks
method: CGLIB$STATICHOOK1
method: CGLIB$BIND_CALLBACKS
method: setCallback
```
Idea complains about duplicates root because we run latest dep tests
and 'later version' tests from the same dir. This is ultimately
TestSetd plugin bug by the looks of it, but we can work around it by
swapping old and new version tests.
Also run both old and new version tests under 'test' task.
Currently helpers will not be injected if instrumentation doesn't
apply. Unfortunately it is possible for some classes to have context
fields added even if instrumentation is not allied (i.g. instrumented
classes are not used). Fix this by always injecting all helpers if we
inject context fields.
This can cause problems if muzzle prevents an integration from loading because the class for the new field being added may not be injected. This results in an error:
```
Caused by: java.lang.NoClassDefFoundError: datadog/trace/bootstrap/instrumentation/context/FieldBackedProvider$ContextAccessor$org$hibernate$Session$datadog$trace$bootstrap$instrumentation$hibernate$SessionState
```
Also add each hibernate instrumentation project as a test dependency to the others. This demonstrates a problem with muzzle and instrumentation context which currently causes the tests to fail.
Looks like AWS SDK doesn't call interceptor when non-sdk exception
occurs. This leads to leaking open spans. Fix that by instrumenting
http client.
Note: currently has no tests.
Serialize payloads as they arrive, send to agent when size exceeds 5MB.
If a flood of traces fills up the RingBuffer, we still count the traces that are discarded for stats reporting.
Do we want to allow configuration of the RingBuffer size?
I notice occasionally some of the instrumentation tests fail due to port
conflicts in TestHttpServer, esp when using the `--parallel` option in
gradle. I think the previous method is subject to a race where two
concurrent workers will both get the same port from `randomOpenPort()`.