3
3
import static datadog .trace .api .ConfigDefaults .DEFAULT_ASYNC_PROPAGATING ;
4
4
import static datadog .trace .bootstrap .instrumentation .api .AgentTracer .noopScope ;
5
5
import static datadog .trace .bootstrap .instrumentation .api .AgentTracer .noopSpan ;
6
+ import static datadog .trace .core .scopemanager .ContinuableScope .CONTEXT ;
6
7
import static datadog .trace .core .scopemanager .ContinuableScope .INSTRUMENTATION ;
7
8
import static datadog .trace .core .scopemanager .ContinuableScope .ITERATION ;
8
9
import static datadog .trace .core .scopemanager .ContinuableScope .MANUAL ;
9
10
import static java .util .concurrent .TimeUnit .MINUTES ;
10
11
import static java .util .concurrent .TimeUnit .NANOSECONDS ;
11
12
import static java .util .concurrent .TimeUnit .SECONDS ;
12
13
14
+ import datadog .context .Context ;
15
+ import datadog .context .ContextManager ;
16
+ import datadog .context .ContextScope ;
13
17
import datadog .trace .api .Config ;
14
18
import datadog .trace .api .Stateful ;
15
19
import datadog .trace .api .scopemanager .ExtendedScopeListener ;
40
44
* from being reported even if all related spans are finished. It also delegates to other
41
45
* ScopeInterceptors to provide additional functionality.
42
46
*/
43
- public final class ContinuableScopeManager implements ScopeStateAware {
47
+ public final class ContinuableScopeManager implements ScopeStateAware , ContextManager {
44
48
45
49
static final Logger log = LoggerFactory .getLogger (ContinuableScopeManager .class );
46
50
static final RatelimitedLogger ratelimitedLog = new RatelimitedLogger (log , 1 , MINUTES );
@@ -83,6 +87,8 @@ public ContinuableScopeManager(
83
87
this .healthMetrics = healthMetrics ;
84
88
this .tlsScopeStack = new ScopeStackThreadLocal (profilingContextIntegration );
85
89
this .profilingContextIntegration = profilingContextIntegration ;
90
+
91
+ ContextManager .register (this );
86
92
}
87
93
88
94
public AgentScope activateSpan (final AgentSpan span ) {
@@ -96,10 +102,12 @@ public AgentScope activateManualSpan(final AgentSpan span) {
96
102
public AgentScope .Continuation captureActiveSpan () {
97
103
ContinuableScope activeScope = scopeStack ().active ();
98
104
if (null != activeScope && activeScope .isAsyncPropagating ()) {
99
- return captureSpan (activeScope .span (), activeScope .source ());
100
- } else {
101
- return AgentTracer .noopContinuation ();
105
+ AgentSpan span = activeScope .span ();
106
+ if (span != null ) {
107
+ return captureSpan (span , activeScope .source ());
108
+ }
102
109
}
110
+ return AgentTracer .noopContinuation ();
103
111
}
104
112
105
113
public AgentScope .Continuation captureSpan (final AgentSpan span ) {
@@ -111,14 +119,14 @@ private AgentScope.Continuation captureSpan(final AgentSpan span, byte source) {
111
119
}
112
120
113
121
private AgentScope activate (
114
- final AgentSpan span ,
122
+ final Context context ,
115
123
final byte source ,
116
124
final boolean overrideAsyncPropagation ,
117
125
final boolean isAsyncPropagating ) {
118
126
ScopeStack scopeStack = scopeStack ();
119
127
120
128
final ContinuableScope top = scopeStack .top ;
121
- if (top != null && top .span .equals (span )) {
129
+ if (top != null && top .context .equals (context )) {
122
130
top .incrementReferences ();
123
131
return top ;
124
132
}
@@ -131,7 +139,7 @@ private AgentScope activate(
131
139
return noopScope ();
132
140
}
133
141
134
- assert span != null ;
142
+ assert context != null ;
135
143
136
144
// Inherit the async propagation from the active scope unless the value is overridden
137
145
boolean asyncPropagation =
@@ -140,7 +148,7 @@ private AgentScope activate(
140
148
: top != null ? top .isAsyncPropagating () : DEFAULT_ASYNC_PROPAGATING ;
141
149
142
150
final ContinuableScope scope =
143
- new ContinuableScope (this , span , source , asyncPropagation , createScopeState (span ));
151
+ new ContinuableScope (this , context , source , asyncPropagation , createScopeState (context ));
144
152
scopeStack .push (scope );
145
153
healthMetrics .onActivateScope ();
146
154
@@ -153,26 +161,26 @@ private AgentScope activate(
153
161
* @param continuation {@code null} if a continuation is re-used
154
162
*/
155
163
ContinuableScope continueSpan (
156
- final ScopeContinuation continuation , final AgentSpan span , final byte source ) {
164
+ final ScopeContinuation continuation , final Context context , final byte source ) {
157
165
ScopeStack scopeStack = scopeStack ();
158
166
159
167
// optimization: if the top scope is already keeping the same span alive
160
168
// then re-use that scope (avoids allocation) and cancel the continuation
161
169
final ContinuableScope top = scopeStack .top ;
162
- if (top != null && top .span .equals (span )) {
170
+ if (top != null && top .context .equals (context )) {
163
171
top .incrementReferences ();
164
172
if (continuation != null ) {
165
173
continuation .cancelFromContinuedScopeClose ();
166
174
}
167
175
return top ;
168
176
}
169
177
170
- Stateful scopeState = createScopeState (span );
178
+ Stateful scopeState = createScopeState (context );
171
179
final ContinuableScope scope ;
172
180
if (continuation != null ) {
173
- scope = new ContinuingScope (this , span , source , true , continuation , scopeState );
181
+ scope = new ContinuingScope (this , context , source , true , continuation , scopeState );
174
182
} else {
175
- scope = new ContinuableScope (this , span , source , true , scopeState );
183
+ scope = new ContinuableScope (this , context , source , true , scopeState );
176
184
}
177
185
scopeStack .push (scope );
178
186
@@ -202,8 +210,9 @@ public void closePrevious(final boolean finishSpan) {
202
210
}
203
211
top .close ();
204
212
scopeStack .cleanup ();
205
- if (finishSpan ) {
206
- top .span .finishWithEndToEnd ();
213
+ AgentSpan span = top .span ();
214
+ if (finishSpan && span != null ) {
215
+ span .finishWithEndToEnd ();
207
216
}
208
217
}
209
218
}
@@ -261,7 +270,7 @@ public void rollbackActiveToCheckpoint() {
261
270
262
271
public AgentSpan activeSpan () {
263
272
final ContinuableScope active = scopeStack ().active ();
264
- return active == null ? null : active .span ;
273
+ return active == null ? null : active .span () ;
265
274
}
266
275
267
276
/** Attach a listener to scope activation events */
@@ -289,11 +298,12 @@ private void addExtendedScopeListener(final ExtendedScopeListener listener) {
289
298
}
290
299
}
291
300
292
- private Stateful createScopeState (AgentSpan span ) {
301
+ private Stateful createScopeState (Context context ) {
293
302
// currently this just manages things the profiler has to do per scope, but could be expanded
294
303
// to encapsulate other scope lifecycle activities
295
304
// FIXME DDSpanContext is always a ProfilerContext anyway...
296
- if (span .context () instanceof ProfilerContext ) {
305
+ AgentSpan span = AgentSpan .fromContext (context );
306
+ if (span != null && span .context () instanceof ProfilerContext ) {
297
307
return profilingContextIntegration .newScopeState ((ProfilerContext ) span .context ());
298
308
}
299
309
return Stateful .DEFAULT ;
@@ -308,6 +318,22 @@ public ScopeState newScopeState() {
308
318
return new ContinuableScopeState ();
309
319
}
310
320
321
+ @ Override
322
+ public Context current () {
323
+ final ContinuableScope active = scopeStack ().active ();
324
+ return active == null ? Context .root () : active .context ;
325
+ }
326
+
327
+ @ Override
328
+ public ContextScope attach (Context context ) {
329
+ return activate (context , CONTEXT , false , true );
330
+ }
331
+
332
+ @ Override
333
+ public Context swap (Context context ) {
334
+ throw new UnsupportedOperationException ("Not yet implemented" );
335
+ }
336
+
311
337
private class ContinuableScopeState implements ScopeState {
312
338
313
339
private ScopeStack localScopeStack = tlsScopeStack .initialValue ();
@@ -383,11 +409,14 @@ public void run(Map<ScopeStack, ContinuableScope> rootIterationScopes) {
383
409
384
410
if (!rootScope .alive ()) { // no need to track this anymore
385
411
itr .remove ();
386
- } else if (NANOSECONDS .toMillis (rootScope .span .getStartTime ()) < cutOff ) {
387
- // mark scope as overdue to allow cleanup and avoid further spans being attached
388
- scopeStack .overdueRootScope = rootScope ;
389
- rootScope .span .finishWithEndToEnd ();
390
- itr .remove ();
412
+ } else {
413
+ AgentSpan span = rootScope .span ();
414
+ if (span != null && NANOSECONDS .toMillis (span .getStartTime ()) < cutOff ) {
415
+ // mark scope as overdue to allow cleanup and avoid further spans being attached
416
+ scopeStack .overdueRootScope = rootScope ;
417
+ span .finishWithEndToEnd ();
418
+ itr .remove ();
419
+ }
391
420
}
392
421
}
393
422
}
0 commit comments