2727import  io .temporal .common .interceptors .WorkflowOutboundCallsInterceptor ;
2828import  io .temporal .common .interceptors .WorkflowOutboundCallsInterceptorBase ;
2929import  io .temporal .opentracing .OpenTracingOptions ;
30+ import  io .temporal .workflow .Functions ;
31+ import  io .temporal .workflow .Promise ;
3032import  io .temporal .workflow .Workflow ;
3133import  io .temporal .workflow .WorkflowInfo ;
3234import  io .temporal .workflow .unsafe .WorkflowUnsafe ;
35+ import  java .util .concurrent .Executor ;
36+ import  java .util .concurrent .TimeUnit ;
37+ import  java .util .concurrent .TimeoutException ;
3338
3439public  class  OpenTracingWorkflowOutboundCallsInterceptor 
3540    extends  WorkflowOutboundCallsInterceptorBase  {
3641  private  final  SpanFactory  spanFactory ;
3742  private  final  Tracer  tracer ;
3843  private  final  ContextAccessor  contextAccessor ;
3944
45+   private  class  SpanTransferringExecutor  implements  Executor  {
46+     private  final  Executor  passthrough ;
47+     private  final  Span  capturedSpan ;
48+ 
49+     public  SpanTransferringExecutor (Executor  passthrough ) {
50+       this .passthrough  = passthrough ;
51+       capturedSpan  = tracer .scopeManager ().activeSpan ();
52+     }
53+ 
54+     public  void  execute (Runnable  r ) {
55+       Span  activeSpan  = tracer .scopeManager ().activeSpan ();
56+ 
57+       if  (activeSpan  == null  && capturedSpan  != null ) {
58+         // if there is no activeSpan AND we captured a span during construction, 
59+         // we should transfer it to the calling context as the new active span 
60+         try  (Scope  ignored  = tracer .scopeManager ().activate (capturedSpan )) {
61+           passthrough .execute (r );
62+         }
63+       } else  {
64+         passthrough .execute (r );
65+       }
66+     }
67+   }
68+ 
69+   private  class  PromiseWrapper <R > implements  Promise <R > {
70+     private  final  Span  capturedSpan ;
71+     private  final  Promise <R > delegate ;
72+ 
73+     PromiseWrapper (Span  capturedSpan , Promise <R > delegate ) {
74+       this .capturedSpan  = capturedSpan ;
75+       this .delegate  = delegate ;
76+     }
77+ 
78+     @ Override 
79+     public  boolean  isCompleted () {
80+       return  delegate .isCompleted ();
81+     }
82+ 
83+     @ Override 
84+     public  R  get () {
85+       return  delegate .get ();
86+     }
87+ 
88+     @ Override 
89+     public  R  cancellableGet () {
90+       return  delegate .cancellableGet ();
91+     }
92+ 
93+     @ Override 
94+     public  R  get (long  timeout , TimeUnit  unit ) throws  TimeoutException  {
95+       return  delegate .get (timeout , unit );
96+     }
97+ 
98+     @ Override 
99+     public  R  cancellableGet (long  timeout , TimeUnit  unit ) throws  TimeoutException  {
100+       return  delegate .cancellableGet (timeout , unit );
101+     }
102+ 
103+     @ Override 
104+     public  RuntimeException  getFailure () {
105+       return  delegate .getFailure ();
106+     }
107+ 
108+     @ Override 
109+     public  <U > Promise <U > thenApply (Functions .Func1 <? super  R , ? extends  U > fn ) {
110+       return  delegate .thenApply (
111+           (r ) -> {
112+             if  (capturedSpan  != null ) {
113+               try  (Scope  ignored  = tracer .scopeManager ().activate (capturedSpan )) {
114+                 return  fn .apply (r );
115+               }
116+             } else  {
117+               return  fn .apply (r );
118+             }
119+           });
120+     }
121+ 
122+     @ Override 
123+     public  <U > Promise <U > handle (Functions .Func2 <? super  R , RuntimeException , ? extends  U > fn ) {
124+       return  delegate .handle (
125+           (r , e ) -> {
126+             if  (capturedSpan  != null ) {
127+               try  (Scope  ignored  = tracer .scopeManager ().activate (capturedSpan )) {
128+                 return  fn .apply (r , e );
129+               }
130+             } else  {
131+               return  fn .apply (r , e );
132+             }
133+           });
134+     }
135+ 
136+     @ Override 
137+     public  <U > Promise <U > thenCompose (Functions .Func1 <? super  R , ? extends  Promise <U >> fn ) {
138+       return  delegate .thenCompose (
139+           (R  r ) -> {
140+             if  (capturedSpan  != null ) {
141+               try  (Scope  ignored  = tracer .scopeManager ().activate (capturedSpan )) {
142+                 return  fn .apply (r );
143+               }
144+             } else  {
145+               return  fn .apply (r );
146+             }
147+           });
148+     }
149+ 
150+     @ Override 
151+     public  Promise <R > exceptionally (Functions .Func1 <Throwable , ? extends  R > fn ) {
152+       return  delegate .exceptionally (
153+           (Throwable  t ) -> {
154+             if  (capturedSpan  != null ) {
155+               try  (Scope  ignored  = tracer .scopeManager ().activate (capturedSpan )) {
156+                 return  fn .apply (t );
157+               }
158+             } else  {
159+               return  fn .apply (t );
160+             }
161+           });
162+     }
163+   }
164+ 
40165  public  OpenTracingWorkflowOutboundCallsInterceptor (
41166      WorkflowOutboundCallsInterceptor  next ,
42167      OpenTracingOptions  options ,
@@ -51,13 +176,16 @@ public OpenTracingWorkflowOutboundCallsInterceptor(
51176  @ Override 
52177  public  <R > ActivityOutput <R > executeActivity (ActivityInput <R > input ) {
53178    if  (!WorkflowUnsafe .isReplaying ()) {
179+       Span  capturedSpan  = tracer .scopeManager ().activeSpan ();
54180      Span  activityStartSpan  =
55181          contextAccessor .writeSpanContextToHeader (
56182              () -> createActivityStartSpanBuilder (input .getActivityName ()).start (),
57183              input .getHeader (),
58184              tracer );
59185      try  (Scope  ignored  = tracer .scopeManager ().activate (activityStartSpan )) {
60-         return  super .executeActivity (input );
186+         ActivityOutput <R > output  = super .executeActivity (input );
187+         return  new  ActivityOutput <>(
188+             output .getActivityId (), new  PromiseWrapper <>(capturedSpan , output .getResult ()));
61189      } finally  {
62190        activityStartSpan .finish ();
63191      }
@@ -69,13 +197,15 @@ public <R> ActivityOutput<R> executeActivity(ActivityInput<R> input) {
69197  @ Override 
70198  public  <R > LocalActivityOutput <R > executeLocalActivity (LocalActivityInput <R > input ) {
71199    if  (!WorkflowUnsafe .isReplaying ()) {
200+       Span  capturedSpan  = tracer .scopeManager ().activeSpan ();
72201      Span  activityStartSpan  =
73202          contextAccessor .writeSpanContextToHeader (
74203              () -> createActivityStartSpanBuilder (input .getActivityName ()).start (),
75204              input .getHeader (),
76205              tracer );
77206      try  (Scope  ignored  = tracer .scopeManager ().activate (activityStartSpan )) {
78-         return  super .executeLocalActivity (input );
207+         LocalActivityOutput <R > output  = super .executeLocalActivity (input );
208+         return  new  LocalActivityOutput <>(new  PromiseWrapper <>(capturedSpan , output .getResult ()));
79209      } finally  {
80210        activityStartSpan .finish ();
81211      }
@@ -87,11 +217,14 @@ public <R> LocalActivityOutput<R> executeLocalActivity(LocalActivityInput<R> inp
87217  @ Override 
88218  public  <R > ChildWorkflowOutput <R > executeChildWorkflow (ChildWorkflowInput <R > input ) {
89219    if  (!WorkflowUnsafe .isReplaying ()) {
220+       Span  capturedSpan  = tracer .scopeManager ().activeSpan ();
90221      Span  childWorkflowStartSpan  =
91222          contextAccessor .writeSpanContextToHeader (
92223              () -> createChildWorkflowStartSpanBuilder (input ).start (), input .getHeader (), tracer );
93224      try  (Scope  ignored  = tracer .scopeManager ().activate (childWorkflowStartSpan )) {
94-         return  super .executeChildWorkflow (input );
225+         ChildWorkflowOutput <R > output  = super .executeChildWorkflow (input );
226+         return  new  ChildWorkflowOutput <>(
227+             new  PromiseWrapper <>(capturedSpan , output .getResult ()), output .getWorkflowExecution ());
95228      } finally  {
96229        childWorkflowStartSpan .finish ();
97230      }
@@ -104,13 +237,16 @@ public <R> ChildWorkflowOutput<R> executeChildWorkflow(ChildWorkflowInput<R> inp
104237  public  <R > ExecuteNexusOperationOutput <R > executeNexusOperation (
105238      ExecuteNexusOperationInput <R > input ) {
106239    if  (!WorkflowUnsafe .isReplaying ()) {
240+       Span  capturedSpan  = tracer .scopeManager ().activeSpan ();
107241      Span  nexusOperationExecuteSpan  =
108242          contextAccessor .writeSpanContextToHeader (
109243              () -> createStartNexusOperationSpanBuilder (input ).start (),
110244              input .getHeaders (),
111245              tracer );
112246      try  (Scope  ignored  = tracer .scopeManager ().activate (nexusOperationExecuteSpan )) {
113-         return  super .executeNexusOperation (input );
247+         ExecuteNexusOperationOutput <R > output  = super .executeNexusOperation (input );
248+         return  new  ExecuteNexusOperationOutput <>(
249+             new  PromiseWrapper <>(capturedSpan , output .getResult ()), output .getOperationExecution ());
114250      } finally  {
115251        nexusOperationExecuteSpan .finish ();
116252      }
@@ -122,6 +258,7 @@ public <R> ExecuteNexusOperationOutput<R> executeNexusOperation(
122258  @ Override 
123259  public  SignalExternalOutput  signalExternalWorkflow (SignalExternalInput  input ) {
124260    if  (!WorkflowUnsafe .isReplaying ()) {
261+       Span  capturedSpan  = tracer .scopeManager ().activeSpan ();
125262      WorkflowInfo  workflowInfo  = Workflow .getInfo ();
126263      Span  childWorkflowStartSpan  =
127264          contextAccessor .writeSpanContextToHeader (
@@ -136,7 +273,8 @@ public SignalExternalOutput signalExternalWorkflow(SignalExternalInput input) {
136273              input .getHeader (),
137274              tracer );
138275      try  (Scope  ignored  = tracer .scopeManager ().activate (childWorkflowStartSpan )) {
139-         return  super .signalExternalWorkflow (input );
276+         SignalExternalOutput  output  = super .signalExternalWorkflow (input );
277+         return  new  SignalExternalOutput (new  PromiseWrapper <>(capturedSpan , output .getResult ()));
140278      } finally  {
141279        childWorkflowStartSpan .finish ();
142280      }
@@ -178,6 +316,12 @@ public Object newChildThread(Runnable runnable, boolean detached, String name) {
178316    return  super .newChildThread (wrappedRunnable , detached , name );
179317  }
180318
319+   @ Override 
320+   public  Executor  newCallbackExecutor () {
321+     Executor  passthrough  = super .newCallbackExecutor ();
322+     return  new  SpanTransferringExecutor (passthrough );
323+   }
324+ 
181325  private  Tracer .SpanBuilder  createActivityStartSpanBuilder (String  activityName ) {
182326    WorkflowInfo  workflowInfo  = Workflow .getInfo ();
183327    return  spanFactory .createActivityStartSpan (
0 commit comments