package org.skywalking.apm.agent.core.sampling; 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.logging.ILog; import org.skywalking.apm.logging.LogManager; import org.skywalking.apm.trace.TraceSegment; /** * The <code>SamplingService</code> take charge of how to sample the {@link TraceSegment}. Every {@link TraceSegment}s * have been traced, but, considering CPU cost of serialization/deserialization, and network bandwidth, the agent do NOT * send all of them to collector, if SAMPLING is on. * <p> * By default, SAMPLING is off, and {@link Config.Agent#SAMPLING_CYCLE} == 1. * * @author wusheng */ public class SamplingService implements BootService { private static final ILog logger = LogManager.getLogger(SamplingService.class); private volatile boolean on = false; private volatile int rollingSeed = 1; @Override public void bootUp() throws Throwable { if (Config.Agent.SAMPLING_CYCLE == 1) { this.on = false; return; } if (Config.Agent.SAMPLING_CYCLE < 1) { throw new IllegalSamplingRateException("sampling cycle must greater than 0."); } this.on = true; logger.debug("The trace sampling is on, and the sampling cycle is: {}", Config.Agent.SAMPLING_CYCLE); } public void trySampling(TraceSegment segment) { if (on) { if (rollingSeed % Config.Agent.SAMPLING_CYCLE != 0) { segment.setSampled(false); this.rollingSeed = 1; } rollingSeed++; } } /** * 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 */ public void setSampleWhenExtract(TraceSegment segment, ContextCarrier carrier) { if (on) { if (!segment.isSampled() && carrier.isSampled()) { segment.setSampled(true); this.rollingSeed = 1; } } } }