Skip to content

Commit

Permalink
Add a forceIgnoring mechanism to the agent kernel (#689)
Browse files Browse the repository at this point in the history
IgnoredTracerContext can propagate the unsampled flag into the following tracing context through the invalid snapshot.
  • Loading branch information
gzlicanyi authored May 17, 2024
1 parent 4dfc1e8 commit b608d74
Show file tree
Hide file tree
Showing 16 changed files with 202 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Release Notes.
* Fix typos in `URLParser`.
* Add support for `Derby`/`Sybase`/`SQLite`/`DB2`/`OceanBase` jdbc url format in `URLParser`.
* Optimize spring-plugins:scheduled-annotation-plugin compatibility about Spring 6.1.x support.
* Add a forceIgnoring mechanism in a CROSS_THREAD scenario.

All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,10 @@ public interface AbstractTracerContext {
* Get current primary endpoint name
*/
String getPrimaryEndpointName();

/**
* Change the current context to be in ignoring status.
*/
AbstractTracerContext forceIgnoring();

}
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,14 @@ public static void continued(ContextSnapshot snapshot) {
throw new IllegalArgumentException("ContextSnapshot can't be null.");
}
if (!snapshot.isFromCurrent()) {
get().continued(snapshot);
// Invalid snapshot is only created by {@link IgnoredTracerContext#capture()}.
// When the snapshot is not valid, need to force ignoring the current tracing context.
if (snapshot.isValid()) {
get().continued(snapshot);
} else {
AbstractTracerContext context = get().forceIgnoring();
CONTEXT.set(context);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ public IgnoredTracerContext() {
this.profileStatusContext = ProfileStatusContext.createWithNone();
}

public IgnoredTracerContext(int stackDepth) {
this.stackDepth = stackDepth;
this.correlationContext = new CorrelationContext();
this.extensionContext = new ExtensionContext();
this.profileStatusContext = ProfileStatusContext.createWithNone();
}

@Override
public void inject(ContextCarrier carrier) {
this.correlationContext.inject(carrier);
Expand Down Expand Up @@ -134,6 +141,11 @@ public String getPrimaryEndpointName() {
return null;
}

@Override
public AbstractTracerContext forceIgnoring() {
return this;
}

public static class ListenerManager {
private static List<IgnoreTracerContextListener> LISTENERS = new LinkedList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,14 @@ public String getPrimaryEndpointName() {
return primaryEndpoint.getName();
}

@Override
public AbstractTracerContext forceIgnoring() {
for (AbstractSpan span: activeSpanStack) {
span.forceIgnoring();
}
return new IgnoredTracerContext(activeSpanStack.size());
}

/**
* Re-check current trace need profiling, encase third part plugin change the operation name.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,9 @@ public interface AbstractSpan extends AsyncSpan {
* Should skip analysis in the backend.
*/
void skipAnalysis();

/**
* Set to ignored status.
*/
void forceIgnoring();
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ public abstract class AbstractTracingSpan implements AbstractSpan {
private volatile boolean isAsyncStopped = false;

/**
* The context to which the span belongs
* The context to which the span belongs.
* This should not be called when {@link #ignored} is true.
*/
protected final TracingContext owner;

Expand Down Expand Up @@ -99,6 +100,11 @@ public abstract class AbstractTracingSpan implements AbstractSpan {
*/
protected boolean skipAnalysis;

/**
* The ignore flag of this span.
*/
protected boolean ignored;

protected AbstractTracingSpan(int spanId, int parentSpanId, String operationName, TracingContext owner) {
this.operationName = operationName;
this.spanId = spanId;
Expand Down Expand Up @@ -318,7 +324,9 @@ public AbstractSpan prepareForAsync() {
if (isInAsyncMode) {
throw new RuntimeException("Prepare for async repeatedly. Span is already in async mode.");
}
ContextManager.awaitFinishAsync(this);
if (!ignored) {
ContextManager.awaitFinishAsync(this);
}
isInAsyncMode = true;
return this;
}
Expand All @@ -332,18 +340,28 @@ public AbstractSpan asyncFinish() {
throw new RuntimeException("Can not do async finish for the span repeatedly.");
}
this.endTime = System.currentTimeMillis();
owner.asyncStop(this);
if (!ignored) {
owner.asyncStop(this);
}
isAsyncStopped = true;
return this;
}

@Override
public boolean isProfiling() {
if (ignored) {
return false;
}
return this.owner.profileStatus().isProfiling();
}

@Override
public void skipAnalysis() {
this.skipAnalysis = true;
}

@Override
public void forceIgnoring() {
this.ignored = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@ public String getPeer() {

@Override
public ExitSpan inject(final ContextCarrier carrier) {
this.owner.inject(this, carrier);
if (!ignored) {
this.owner.inject(this, carrier);
}
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ public boolean isProfiling() {
public void skipAnalysis() {
}

@Override
public void forceIgnoring() {
}

@Override
public AbstractSpan prepareForAsync() {
return this;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.skywalking.apm.agent.core.context;

import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
import org.apache.skywalking.apm.agent.core.conf.Config;
import org.apache.skywalking.apm.agent.core.context.ids.NewDistributedTraceId;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.context.trace.LocalSpan;
import org.apache.skywalking.apm.agent.core.context.trace.NoopSpan;
import org.apache.skywalking.apm.agent.core.profile.ProfileStatusContext;
import org.apache.skywalking.apm.agent.core.test.tools.AgentServiceRule;
import org.apache.skywalking.apm.agent.core.test.tools.SegmentStorage;
import org.apache.skywalking.apm.agent.core.test.tools.SegmentStoragePoint;
import org.apache.skywalking.apm.agent.core.test.tools.TracingSegmentRunner;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.Assert;

@RunWith(TracingSegmentRunner.class)
public class ContinuedContextTest {

@SegmentStoragePoint
private SegmentStorage tracingData;

@Rule
public AgentServiceRule agentServiceRule = new AgentServiceRule();

@BeforeClass
public static void beforeClass() {
Config.Agent.KEEP_TRACING = true;
}

@AfterClass
public static void afterClass() {
Config.Agent.KEEP_TRACING = false;
ServiceManager.INSTANCE.shutdown();
}

@Test
public void testContinued() {

NewDistributedTraceId distributedTraceId = new NewDistributedTraceId();
ContextSnapshot snapshot = new ContextSnapshot(
"1, 2, 3",
1,
distributedTraceId,
"/for-test-continued",
new CorrelationContext(),
new ExtensionContext(),
ProfileStatusContext.createWithNone()
);

AbstractSpan span = ContextManager.createLocalSpan("test-span");
ContextManager.continued(snapshot);

Assert.assertEquals(distributedTraceId.getId(), ContextManager.getGlobalTraceId());
ContextManager.stopSpan();
}

@Test
public void testContinuedWithIgnoredSnapshot() {

ContextSnapshot snapshot =
new ContextSnapshot(null, -1, null, null, new CorrelationContext(), new ExtensionContext(), ProfileStatusContext.createWithNone());

AbstractSpan span = ContextManager.createLocalSpan("test-span");
ContextManager.continued(snapshot);

Assert.assertTrue(span instanceof LocalSpan);

AbstractSpan span2 = ContextManager.createLocalSpan("test-span2");
Assert.assertTrue(span2 instanceof NoopSpan);

ContextManager.stopSpan();
ContextManager.stopSpan();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import static org.mockito.Mockito.when;
import java.util.List;
import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
import org.apache.skywalking.apm.agent.core.context.MockContextSnapshot;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
Expand Down Expand Up @@ -55,7 +56,6 @@ public class OnExceptionInterceptorTest {
@Rule
public MockitoRule rule = MockitoJUnit.rule();

@Mock
private ContextSnapshot contextSnapshot;
private SendCallBackEnhanceInfo enhanceInfo;

Expand All @@ -65,6 +65,7 @@ public class OnExceptionInterceptorTest {
@Before
public void setUp() {
exceptionInterceptor = new OnExceptionInterceptor();
contextSnapshot = MockContextSnapshot.INSTANCE.mockContextSnapshot();

enhanceInfo = new SendCallBackEnhanceInfo("test", contextSnapshot);
when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn(enhanceInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import static org.mockito.Mockito.when;
import java.util.List;
import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
import org.apache.skywalking.apm.agent.core.context.MockContextSnapshot;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
Expand Down Expand Up @@ -57,7 +58,6 @@ public class OnSuccessInterceptorTest {
@Rule
public MockitoRule rule = MockitoJUnit.rule();

@Mock
private ContextSnapshot contextSnapshot;
@Mock
private SendResult sendResult;
Expand All @@ -70,6 +70,7 @@ public class OnSuccessInterceptorTest {
@Before
public void setUp() {
successInterceptor = new OnSuccessInterceptor();
contextSnapshot = MockContextSnapshot.INSTANCE.mockContextSnapshot();

enhanceInfo = new SendCallBackEnhanceInfo("test", contextSnapshot);
when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn(enhanceInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import static org.mockito.Mockito.when;
import java.util.List;
import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
import org.apache.skywalking.apm.agent.core.context.MockContextSnapshot;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
Expand Down Expand Up @@ -55,7 +56,6 @@ public class OnExceptionInterceptorTest {
@Rule
public MockitoRule rule = MockitoJUnit.rule();

@Mock
private ContextSnapshot contextSnapshot;
private SendCallBackEnhanceInfo enhanceInfo;

Expand All @@ -69,6 +69,7 @@ public void setUp() {

@Test
public void testOnException() throws Throwable {
contextSnapshot = MockContextSnapshot.INSTANCE.mockContextSnapshot();
enhanceInfo = new SendCallBackEnhanceInfo("test", contextSnapshot);
when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn(enhanceInfo);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
import org.apache.skywalking.apm.agent.core.context.MockContextSnapshot;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
Expand Down Expand Up @@ -57,7 +58,6 @@ public class OnSuccessInterceptorTest {
@Rule
public MockitoRule rule = MockitoJUnit.rule();

@Mock
private ContextSnapshot contextSnapshot;
@Mock
private SendResult sendResult;
Expand All @@ -70,6 +70,7 @@ public class OnSuccessInterceptorTest {
@Before
public void setUp() {
successInterceptor = new OnSuccessInterceptor();
contextSnapshot = MockContextSnapshot.INSTANCE.mockContextSnapshot();

enhanceInfo = new SendCallBackEnhanceInfo("test", contextSnapshot);
when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn(enhanceInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public enum MockContextSnapshot {

private ContextSnapshot contextSnapshot;

private ContextSnapshot ignoreContextSnapshot;

MockContextSnapshot() {
contextSnapshot = new ContextSnapshot(
"1, 2, 3",
Expand All @@ -36,9 +38,21 @@ public enum MockContextSnapshot {
new ExtensionContext(),
ProfileStatusContext.createWithNone()
);
ignoreContextSnapshot = new ContextSnapshot(
null,
-1,
null,
null,
new CorrelationContext(),
new ExtensionContext(),
ProfileStatusContext.createWithNone());
}

public ContextSnapshot mockContextSnapshot() {
return contextSnapshot;
}

public ContextSnapshot mockIgnoreContextSnapshot() {
return ignoreContextSnapshot;
}
}
Loading

0 comments on commit b608d74

Please sign in to comment.