Finish almost all codes about ignore, sample and analytic trace mechanism. Left analytic trace only for collector.

This commit is contained in:
wusheng 2017-06-15 22:13:13 +08:00
parent c88cf2aff8
commit 112547b515
3 changed files with 79 additions and 21 deletions

View File

@ -2,12 +2,14 @@ package org.skywalking.apm.agent.core.context;
import java.util.LinkedList;
import java.util.List;
import org.skywalking.apm.agent.core.boot.ServiceManager;
import org.skywalking.apm.agent.core.conf.Config;
import org.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.skywalking.apm.agent.core.context.trace.LeafSpan;
import org.skywalking.apm.agent.core.context.trace.Span;
import org.skywalking.apm.agent.core.context.trace.TraceSegment;
import org.skywalking.apm.agent.core.context.trace.TraceSegmentRef;
import org.skywalking.apm.agent.core.sampling.SamplingService;
/**
* {@link TracerContext} maintains the context.
@ -73,17 +75,42 @@ public final class TracerContext implements AbstractTracerContext {
span = new Span(spanIdGenerator++, operationName, startTime);
}
push(span);
} else if (parentSpan.isLeaf()) {
span = parentSpan;
LeafSpan leafSpan = (LeafSpan)span;
leafSpan.push();
} else {
if (isLeaf) {
span = new LeafSpan(spanIdGenerator++, parentSpan, operationName, startTime);
} else {
span = new Span(spanIdGenerator++, parentSpan, operationName, startTime);
/**
* Don't have ref yet, means this isn't part of distributed trace.
* Use sampling mechanism
* Only check this on the second span,
* because the {@link #extract(ContextCarrier)} invoke before create the second span.
*/
if (spanIdGenerator == 1) {
SamplingService samplingService = ServiceManager.INSTANCE.findService(SamplingService.class);
if (segment.hasRef()) {
samplingService.forceSampled();
} else {
if (!samplingService.trySampling()) {
/**
* Don't sample this trace.
* Now, switch this trace as an {@link IgnoredTracerContext},
* further more, we will provide an analytic tracer context for all metrics in this trace.
*/
ContextManager.ContextSwitcher.INSTANCE.toNew(new IgnoredTracerContext(2));
return ContextManager.activeSpan();
}
}
}
if (parentSpan.isLeaf()) {
span = parentSpan;
LeafSpan leafSpan = (LeafSpan)span;
leafSpan.push();
} else {
if (isLeaf) {
span = new LeafSpan(spanIdGenerator++, parentSpan, operationName, startTime);
} else {
span = new Span(spanIdGenerator++, parentSpan, operationName, startTime);
}
push(span);
}
push(span);
}
return span;
}

View File

@ -178,6 +178,10 @@ public class TraceSegment {
return Collections.unmodifiableList(refs);
}
public boolean hasRef() {
return !(refs == null || refs.size() == 0);
}
public List<DistributedTraceId> getRelatedGlobalTraces() {
return relatedGlobalTraces.getRelatedGlobalTraces();
}

View File

@ -1,8 +1,11 @@
package org.skywalking.apm.agent.core.sampling;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.skywalking.apm.agent.core.boot.BootService;
import org.skywalking.apm.agent.core.conf.Config;
import org.skywalking.apm.agent.core.context.ContextCarrier;
import org.skywalking.apm.agent.core.context.trace.TraceSegment;
import org.skywalking.apm.logging.ILog;
import org.skywalking.apm.logging.LogManager;
@ -20,29 +23,53 @@ public class SamplingService implements BootService {
private static final ILog logger = LogManager.getLogger(SamplingService.class);
private volatile boolean on = false;
private volatile int rollingSeed = 1;
private volatile AtomicInteger samplingFactorHolder;
@Override
public void bootUp() throws Throwable {
if (Config.Agent.SAMPLE_N_PER_10_SECS > 0) {
on = true;
this.resetSamplingFactor();
ScheduledExecutorService service = Executors
.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
resetSamplingFactor();
}
}, 1, 1, TimeUnit.SECONDS);
logger.debug("Agent sampling mechanism started. Sample {} traces in 10 seconds.", Config.Agent.SAMPLE_N_PER_10_SECS);
}
}
public void trySampling(TraceSegment segment) {
/**
* @return true, if sampling mechanism is on, and get the sampling factor successfully.
*/
public boolean trySampling() {
if (on) {
int factor = samplingFactorHolder.get();
if (factor < Config.Agent.SAMPLE_N_PER_10_SECS) {
return samplingFactorHolder.compareAndSet(factor, factor + 1);
} else {
return false;
}
}
return true;
}
/**
* Set the {@link TraceSegment} to sampled, when {@link ContextCarrier} contains "isSampled" flag.
* <p>
* A -> B, if TraceSegment is sampled in A, then the related TraceSegment in B must be sampled, no matter you
* sampling rate. And reset the {@link #rollingSeed}, in case of too many {@link TraceSegment}s, which started in
* this JVM, are sampled.
*
* @param segment the current TraceSegment.
* @param carrier
* Increase the sampling factor by force,
* to avoid sampling too many traces.
* If many distributed traces require sampled,
* the trace beginning at local, has less chance to be sampled.
*/
public void setSampleWhenExtract(TraceSegment segment, ContextCarrier carrier) {
public void forceSampled() {
if (on) {
samplingFactorHolder.incrementAndGet();
}
}
private void resetSamplingFactor() {
samplingFactorHolder = new AtomicInteger(0);
}
}