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

* Make finish more stable in async APIs
This commit is contained in:
吴晟 Wu Sheng 2019-07-18 23:08:46 +08:00 committed by GitHub
parent 5b039e9747
commit d2f52f28b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 46 additions and 38 deletions

View File

@ -18,14 +18,27 @@
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.locks.ReentrantLock;
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.trace.*;
import org.apache.skywalking.apm.agent.core.dictionary.*;
import org.apache.skywalking.apm.agent.core.logging.api.*;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
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.util.StringUtil;
@ -76,6 +89,8 @@ public class TracingContext implements AbstractTracerContext {
private volatile boolean isRunningInAsyncMode;
private volatile ReentrantLock asyncFinishLock;
private volatile boolean running;
/**
* Initialize all fields with default value.
*/
@ -84,6 +99,7 @@ public class TracingContext implements AbstractTracerContext {
this.spanIdGenerator = 0;
samplingService = ServiceManager.INSTANCE.findService(SamplingService.class);
isRunningInAsyncMode = false;
running = true;
}
/**
@ -402,9 +418,7 @@ public class TracingContext implements AbstractTracerContext {
throw new IllegalStateException("Stopping the unexpected span = " + span);
}
if (checkFinishConditions()) {
finish();
}
finish();
return activeSpanStack.isEmpty();
}
@ -425,26 +439,7 @@ public class TracingContext implements AbstractTracerContext {
@Override public void asyncStop(AsyncSpan span) {
asyncSpanCounter.addAndGet(-1);
if (checkFinishConditions()) {
finish();
}
}
private boolean checkFinishConditions() {
if (isRunningInAsyncMode) {
asyncFinishLock.lock();
}
try {
if (activeSpanStack.isEmpty() && (!isRunningInAsyncMode || asyncSpanCounter.get() == 0)) {
return true;
}
} finally {
if (isRunningInAsyncMode) {
asyncFinishLock.unlock();
}
}
return false;
finish();
}
/**
@ -452,19 +447,32 @@ public class TracingContext implements AbstractTracerContext {
* 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);
if (isRunningInAsyncMode) {
asyncFinishLock.lock();
}
try {
if (activeSpanStack.isEmpty() && running && (!isRunningInAsyncMode || asyncSpanCounter.get() == 0)) {
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 {
if (isRunningInAsyncMode) {
asyncFinishLock.unlock();
}
}
TracingContext.ListenerManager.notifyFinish(finishedSegment);
}
/**