Skip to content

Commit 9bcde36

Browse files
committed
wip
1 parent 01633c9 commit 9bcde36

File tree

7 files changed

+139
-49
lines changed

7 files changed

+139
-49
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package datadog.trace.instrumentation.mule4;
2+
3+
import datadog.trace.agent.tooling.InstrumenterModule;
4+
import datadog.trace.api.Pair;
5+
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
6+
import java.util.HashMap;
7+
import java.util.Map;
8+
9+
public abstract class AbstractMuleInstrumentation extends InstrumenterModule.Tracing {
10+
11+
public AbstractMuleInstrumentation() {
12+
super("mule");
13+
}
14+
15+
@Override
16+
public Map<String, String> contextStore() {
17+
final Map<String, String> ret = new HashMap<>();
18+
ret.put("org.mule.runtime.api.event.EventContext", Pair.class.getName());
19+
ret.put("org.mule.runtime.api.profiling.tracing.Span", AgentSpan.class.getName());
20+
return ret;
21+
}
22+
23+
@Override
24+
public String[] helperClassNames() {
25+
return new String[] {
26+
packageName + ".CurrentEventHelper",
27+
packageName + ".MuleDecorator",
28+
packageName + ".DDEventTracer",
29+
};
30+
}
31+
}

dd-java-agent/instrumentation/mule-4/src/main/java/datadog/trace/instrumentation/mule4/CurrentEventHelper.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ public static void attachSpanToEventContext(
2727
}
2828
AgentScope newScope = null;
2929
if (null != eventContext) {
30-
Pair<AgentSpan, Object> pair = contextStore.get(eventContext);
30+
// we do not explicitly draw dependencies on Mule span since it's only available from 4.5.0
31+
// The EventTracerInstrumentation can muzzle but this will continue working
32+
Pair<AgentSpan, ?> pair = contextStore.get(eventContext);
3133
if (null != pair && pair.hasLeft()) {
3234
newScope = activateSpan(pair.getLeft());
3335
}

dd-java-agent/instrumentation/mule-4/src/main/java/datadog/trace/instrumentation/mule4/DDEventTracer.java

Lines changed: 67 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package datadog.trace.instrumentation.mule4;
22

3+
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeSpan;
4+
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.noopSpan;
5+
import static datadog.trace.instrumentation.mule4.MuleDecorator.DECORATE;
6+
37
import datadog.trace.api.Pair;
48
import datadog.trace.bootstrap.CallDepthThreadLocalMap;
59
import datadog.trace.bootstrap.ContextStore;
610
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
711
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
12+
import datadog.trace.core.DDSpanContext;
813
import java.util.Map;
914
import java.util.Optional;
1015
import java.util.function.Supplier;
@@ -19,38 +24,70 @@
1924
import org.mule.runtime.tracer.api.span.info.InitialSpanInfo;
2025
import org.mule.runtime.tracer.api.span.validation.Assertion;
2126

27+
/**
28+
* This class is responsible for translating span reported by mule internal observability into DD
29+
* ones.
30+
*/
2231
public class DDEventTracer implements EventTracer<CoreEvent> {
2332

24-
private final ContextStore<Span, AgentSpan> spanStore;
25-
private final ContextStore<EventContext, Pair> contextStore;
33+
/**
34+
* Holds the link between mule span <-> Pair(currentSpan, parentSpan)
35+
*/
36+
private final ContextStore<Span, Pair> spanStore;
37+
/**
38+
* Holds the link between mule event context <-> Pair(currentSpan, muleSpan)
39+
*/
40+
private final ContextStore<EventContext, Pair> eventContextStore;
2641
private final EventTracer<CoreEvent> delegate;
2742

2843
public DDEventTracer(
29-
ContextStore<Span, AgentSpan> spanStore,
30-
ContextStore<EventContext, Pair> contextStore,
44+
ContextStore<Span, Pair> spanStore,
45+
ContextStore<EventContext, Pair> eventContextStore,
3146
EventTracer<CoreEvent> delegate) {
3247
this.spanStore = spanStore;
33-
this.contextStore = contextStore;
48+
this.eventContextStore = eventContextStore;
3449
this.delegate = delegate;
3550
}
3651

37-
private AgentSpan fromMuleSpan(Span muleSpan, InitialSpanInfo spanInfo) {
38-
final AgentSpan parent =
39-
muleSpan.getParent() != null ? spanStore.get(muleSpan.getParent()) : null;
40-
52+
private AgentSpan fromMuleSpan(Span muleSpan, AgentSpan parentSpan, InitialSpanInfo spanInfo) {
53+
// we stick with the same level of detail of otel exporter.
54+
// if the customer requires this we can think about giving the ability to override it
55+
if (spanInfo.getInitialExportInfo() != null
56+
&& !spanInfo.getInitialExportInfo().isExportable()) {
57+
return noopSpan();
58+
}
4159
final AgentSpan span;
42-
if (parent == null) {
43-
span = AgentTracer.startSpan("mule", muleSpan.getName());
60+
61+
if (parentSpan == null) {
62+
span = AgentTracer.startSpan(muleSpan.getName());
4463
} else {
45-
span = AgentTracer.startSpan("mule", muleSpan.getName(), parent.context());
64+
span = AgentTracer.startSpan(muleSpan.getName(), parentSpan.context());
4665
}
66+
DECORATE.afterStart(span);
4767
spanInfo.forEachAttribute(span::setTag);
4868
return span;
4969
}
5070

71+
private AgentSpan findParentSpan(Span muleSpan) {
72+
final Pair<AgentSpan, AgentSpan> parentPair =
73+
muleSpan.getParent() != null ? spanStore.get(muleSpan.getParent()) : null;
74+
if (parentPair == null) {
75+
return null;
76+
}
77+
// Since we are not opening all the spans we have to make sure we attach the right parent
78+
if (parentPair.hasLeft() && parentPair.getLeft() != AgentTracer.NoopAgentSpan.INSTANCE) {
79+
// we traced that mule span so it can be used as parent
80+
return parentPair.getLeft();
81+
} else if (parentPair.hasRight()) {
82+
// we did not trace the span but we knew the last traced parent.
83+
return parentPair.getRight();
84+
}
85+
return null;
86+
}
87+
5188
private void activateOnContext(EventContext eventContext, AgentSpan span, Span muleSpan) {
52-
contextStore.put(eventContext, Pair.of(span, muleSpan));
53-
CurrentEventHelper.attachSpanToEventContext(eventContext, contextStore);
89+
eventContextStore.put(eventContext, Pair.of(span, muleSpan));
90+
CurrentEventHelper.attachSpanToEventContext(eventContext, eventContextStore);
5491
}
5592

5693
private Optional<Span> handleNewSpan(
@@ -60,8 +97,9 @@ private Optional<Span> handleNewSpan(
6097
}
6198
try {
6299
final Span muleSpan = maybeSpan.get();
63-
final AgentSpan span = fromMuleSpan(muleSpan, spanInfo);
64-
spanStore.put(muleSpan, span);
100+
final AgentSpan parentSpan = findParentSpan(muleSpan);
101+
final AgentSpan span = fromMuleSpan(muleSpan, parentSpan, spanInfo);
102+
spanStore.put(muleSpan, Pair.of(span, parentSpan));
65103
activateOnContext(event.getContext(), span, muleSpan);
66104
} finally {
67105
CallDepthThreadLocalMap.reset(Span.class);
@@ -74,11 +112,13 @@ private void handleEndOfSpan(CoreEvent event) {
74112
return;
75113
}
76114
try {
77-
final Pair<AgentSpan, Span> pair = contextStore.get(event.getContext());
115+
final Pair<AgentSpan, Span> pair = eventContextStore.get(event.getContext());
78116
if (pair != null && pair.hasLeft() && pair.hasRight()) {
79117
final AgentSpan span = pair.getLeft();
80118
final Span muleSpan = pair.getRight();
119+
81120
spanStore.remove(muleSpan);
121+
82122
if (muleSpan.hasErrors()) {
83123
span.setError(true);
84124
for (final SpanError spanError : muleSpan.getErrors()) {
@@ -87,13 +127,11 @@ private void handleEndOfSpan(CoreEvent event) {
87127
}
88128
}
89129
}
90-
span.finish();
91-
final Span muleParent = muleSpan.getParent();
92-
if (muleParent != null) {
93-
final AgentSpan parent = spanStore.get(muleParent);
94-
if (parent != null) {
95-
activateOnContext(event.getContext(), parent, muleParent);
96-
}
130+
if (span.phasedFinish()) {
131+
span.publish();
132+
}
133+
activateOnContext(event.getContext(), findParentSpan(span), muleSpan.getParent());
134+
97135
}
98136
}
99137
} finally {
@@ -126,19 +164,21 @@ public void endCurrentSpan(CoreEvent event, Assertion condition) {
126164
@Override
127165
public void injectDistributedTraceContext(
128166
EventContext eventContext, DistributedTraceContextGetter distributedTraceContextGetter) {
167+
System.err.println("INJEEEEECT " + distributedTraceContextGetter );
129168
delegate.injectDistributedTraceContext(eventContext, distributedTraceContextGetter);
130169
}
131170

132171
@Override
133172
public void recordErrorAtCurrentSpan(
134173
CoreEvent event, Supplier<Error> errorSupplier, boolean isErrorEscapingCurrentSpan) {
174+
// errors will be collected at the end
135175
delegate.recordErrorAtCurrentSpan(event, errorSupplier, isErrorEscapingCurrentSpan);
136176
}
137177

138178
@Override
139179
public void setCurrentSpanName(CoreEvent event, String name) {
140180
delegate.setCurrentSpanName(event, name);
141-
Pair<AgentSpan, Span> pair = contextStore.get(event.getContext());
181+
Pair<AgentSpan, Span> pair = eventContextStore.get(event.getContext());
142182
if (pair != null && pair.hasLeft()) {
143183
pair.getLeft().setOperationName(name);
144184
}
@@ -147,7 +187,7 @@ public void setCurrentSpanName(CoreEvent event, String name) {
147187
@Override
148188
public void addCurrentSpanAttribute(CoreEvent event, String key, String value) {
149189
delegate.addCurrentSpanAttribute(event, key, value);
150-
Pair<AgentSpan, Span> pair = contextStore.get(event.getContext());
190+
Pair<AgentSpan, Span> pair = eventContextStore.get(event.getContext());
151191
if (pair != null && pair.hasLeft()) {
152192
pair.getLeft().setTag(key, value);
153193
}
@@ -156,7 +196,7 @@ public void addCurrentSpanAttribute(CoreEvent event, String key, String value) {
156196
@Override
157197
public void addCurrentSpanAttributes(CoreEvent event, Map<String, String> attributes) {
158198
delegate.addCurrentSpanAttributes(event, attributes);
159-
Pair<AgentSpan, Span> pair = contextStore.get(event.getContext());
199+
Pair<AgentSpan, Span> pair = eventContextStore.get(event.getContext());
160200
if (pair != null && pair.hasLeft()) {
161201
final AgentSpan span = pair.getLeft();
162202
for (Map.Entry<String, String> entry : attributes.entrySet()) {

dd-java-agent/instrumentation/mule-4/src/main/java/datadog/trace/instrumentation/mule4/EventContextInstrumentation.java

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,20 @@
11
package datadog.trace.instrumentation.mule4;
22

3-
import static java.util.Collections.singletonMap;
43
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
54

65
import com.google.auto.service.AutoService;
76
import datadog.trace.agent.tooling.Instrumenter;
87
import datadog.trace.agent.tooling.InstrumenterModule;
9-
import datadog.trace.api.Pair;
10-
11-
import java.util.Map;
128

139
/**
1410
* Events in Mule have an {@code EventContext} attached to them, that travels with the event through
1511
* the system. We attach the active span to the concrete implementation of the {@code EventContext}
1612
* and activate/deactivate the span when mule changes which event it is processing.
1713
*/
1814
@AutoService(InstrumenterModule.class)
19-
public final class EventContextInstrumentation extends InstrumenterModule.Tracing
15+
public final class EventContextInstrumentation extends AbstractMuleInstrumentation
2016
implements Instrumenter.ForKnownTypes {
2117

22-
public EventContextInstrumentation() {
23-
super("mule");
24-
}
25-
26-
@Override
27-
protected boolean defaultEnabled() {
28-
return false;
29-
}
30-
3118
@Override
3219
public String[] knownMatchingTypes() {
3320
return new String[] {
@@ -36,13 +23,6 @@ public String[] knownMatchingTypes() {
3623
};
3724
}
3825

39-
@Override
40-
public Map<String, String> contextStore() {
41-
return singletonMap(
42-
"org.mule.runtime.api.event.EventContext",
43-
Pair.class.getName());
44-
}
45-
4626
@Override
4727
public void methodAdvice(MethodTransformer transformer) {
4828
transformer.applyAdvice(isConstructor(), packageName + ".EventContextCreationAdvice");
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package datadog.trace.instrumentation.mule4;
2+
3+
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
4+
import datadog.trace.bootstrap.instrumentation.api.InternalSpanTypes;
5+
import datadog.trace.bootstrap.instrumentation.api.Tags;
6+
import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString;
7+
import datadog.trace.bootstrap.instrumentation.decorator.BaseDecorator;
8+
9+
public class MuleDecorator extends BaseDecorator {
10+
private static final CharSequence MULE = UTF8BytesString.create("mule");
11+
public static final MuleDecorator DECORATE = new MuleDecorator();
12+
13+
@Override
14+
protected String[] instrumentationNames() {
15+
return new String[] {MULE.toString()};
16+
}
17+
18+
@Override
19+
protected CharSequence spanType() {
20+
return InternalSpanTypes.MULE;
21+
}
22+
23+
@Override
24+
protected CharSequence component() {
25+
return MULE;
26+
}
27+
28+
@Override
29+
public AgentSpan afterStart(final AgentSpan span) {
30+
span.setMeasured(true);
31+
span.setTag(Tags.SPAN_KIND, Tags.SPAN_KIND_INTERNAL);
32+
return super.afterStart(span);
33+
}
34+
}

dd-trace-api/src/main/java/datadog/trace/api/DDSpanTypes.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,6 @@ public class DDSpanTypes {
3434

3535
public static final String VULNERABILITY = "vulnerability";
3636
public static final String PROTOBUF = "protobuf";
37+
38+
public static final String MULE = "mule";
3739
}

internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/InternalSpanTypes.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,5 @@ public class InternalSpanTypes {
4747
public static final UTF8BytesString PROTOBUF = UTF8BytesString.create(DDSpanTypes.PROTOBUF);
4848

4949
public static final UTF8BytesString TIBCO_BW = UTF8BytesString.create("tibco_bw");
50+
public static final UTF8BytesString MULE = UTF8BytesString.create(DDSpanTypes.MULE);
5051
}

0 commit comments

Comments
 (0)