11package 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+
37import datadog .trace .api .Pair ;
48import datadog .trace .bootstrap .CallDepthThreadLocalMap ;
59import datadog .trace .bootstrap .ContextStore ;
610import datadog .trace .bootstrap .instrumentation .api .AgentSpan ;
711import datadog .trace .bootstrap .instrumentation .api .AgentTracer ;
12+ import datadog .trace .core .DDSpanContext ;
813import java .util .Map ;
914import java .util .Optional ;
1015import java .util .function .Supplier ;
1924import org .mule .runtime .tracer .api .span .info .InitialSpanInfo ;
2025import 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+ */
2231public 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 ()) {
0 commit comments