未验证 提交 d2f52f28 编写于 作者: wu-sheng's avatar wu-sheng 提交者: GitHub

Make #finish more stable in async APIs (#3115)

* Make finish more stable in async APIs
上级 5b039e97
...@@ -18,14 +18,27 @@ ...@@ -18,14 +18,27 @@
package org.apache.skywalking.apm.agent.core.context; package org.apache.skywalking.apm.agent.core.context;
import java.util.*; import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import org.apache.skywalking.apm.agent.core.boot.ServiceManager; 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.conf.Config;
import org.apache.skywalking.apm.agent.core.context.trace.*; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.dictionary.*; import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
import org.apache.skywalking.apm.agent.core.logging.api.*; import org.apache.skywalking.apm.agent.core.context.trace.EntrySpan;
import org.apache.skywalking.apm.agent.core.context.trace.ExitSpan;
import org.apache.skywalking.apm.agent.core.context.trace.LocalSpan;
import org.apache.skywalking.apm.agent.core.context.trace.NoopExitSpan;
import org.apache.skywalking.apm.agent.core.context.trace.NoopSpan;
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegmentRef;
import org.apache.skywalking.apm.agent.core.context.trace.WithPeerInfo;
import org.apache.skywalking.apm.agent.core.dictionary.DictionaryManager;
import org.apache.skywalking.apm.agent.core.dictionary.DictionaryUtil;
import org.apache.skywalking.apm.agent.core.dictionary.PossibleFound;
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
import org.apache.skywalking.apm.agent.core.sampling.SamplingService; import org.apache.skywalking.apm.agent.core.sampling.SamplingService;
import org.apache.skywalking.apm.util.StringUtil; import org.apache.skywalking.apm.util.StringUtil;
...@@ -76,6 +89,8 @@ public class TracingContext implements AbstractTracerContext { ...@@ -76,6 +89,8 @@ public class TracingContext implements AbstractTracerContext {
private volatile boolean isRunningInAsyncMode; private volatile boolean isRunningInAsyncMode;
private volatile ReentrantLock asyncFinishLock; private volatile ReentrantLock asyncFinishLock;
private volatile boolean running;
/** /**
* Initialize all fields with default value. * Initialize all fields with default value.
*/ */
...@@ -84,6 +99,7 @@ public class TracingContext implements AbstractTracerContext { ...@@ -84,6 +99,7 @@ public class TracingContext implements AbstractTracerContext {
this.spanIdGenerator = 0; this.spanIdGenerator = 0;
samplingService = ServiceManager.INSTANCE.findService(SamplingService.class); samplingService = ServiceManager.INSTANCE.findService(SamplingService.class);
isRunningInAsyncMode = false; isRunningInAsyncMode = false;
running = true;
} }
/** /**
...@@ -402,9 +418,7 @@ public class TracingContext implements AbstractTracerContext { ...@@ -402,9 +418,7 @@ public class TracingContext implements AbstractTracerContext {
throw new IllegalStateException("Stopping the unexpected span = " + span); throw new IllegalStateException("Stopping the unexpected span = " + span);
} }
if (checkFinishConditions()) { finish();
finish();
}
return activeSpanStack.isEmpty(); return activeSpanStack.isEmpty();
} }
...@@ -425,46 +439,40 @@ public class TracingContext implements AbstractTracerContext { ...@@ -425,46 +439,40 @@ public class TracingContext implements AbstractTracerContext {
@Override public void asyncStop(AsyncSpan span) { @Override public void asyncStop(AsyncSpan span) {
asyncSpanCounter.addAndGet(-1); asyncSpanCounter.addAndGet(-1);
finish();
if (checkFinishConditions()) {
finish();
}
} }
private boolean checkFinishConditions() { /**
* Finish this context, and notify all {@link TracingContextListener}s, managed by {@link
* TracingContext.ListenerManager}
*/
private void finish() {
if (isRunningInAsyncMode) { if (isRunningInAsyncMode) {
asyncFinishLock.lock(); asyncFinishLock.lock();
} }
try { try {
if (activeSpanStack.isEmpty() && (!isRunningInAsyncMode || asyncSpanCounter.get() == 0)) { if (activeSpanStack.isEmpty() && running && (!isRunningInAsyncMode || asyncSpanCounter.get() == 0)) {
return true; TraceSegment finishedSegment = segment.finish(isLimitMechanismWorking());
/**
* Recheck the segment if the segment contains only one span.
* Because in the runtime, can't sure this segment is part of distributed trace.
*
* @see {@link #createSpan(String, long, boolean)}
*/
if (!segment.hasRef() && segment.isSingleSpanSegment()) {
if (!samplingService.trySampling()) {
finishedSegment.setIgnore(true);
}
}
TracingContext.ListenerManager.notifyFinish(finishedSegment);
running = false;
} }
} finally { } finally {
if (isRunningInAsyncMode) { if (isRunningInAsyncMode) {
asyncFinishLock.unlock(); asyncFinishLock.unlock();
} }
} }
return false;
}
/**
* Finish this context, and notify all {@link TracingContextListener}s, managed by {@link
* TracingContext.ListenerManager}
*/
private void finish() {
TraceSegment finishedSegment = segment.finish(isLimitMechanismWorking());
/**
* Recheck the segment if the segment contains only one span.
* Because in the runtime, can't sure this segment is part of distributed trace.
*
* @see {@link #createSpan(String, long, boolean)}
*/
if (!segment.hasRef() && segment.isSingleSpanSegment()) {
if (!samplingService.trySampling()) {
finishedSegment.setIgnore(true);
}
}
TracingContext.ListenerManager.notifyFinish(finishedSegment);
} }
/** /**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册