Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion dd-java-agent/agent-bootstrap/agent-bootstrap.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies {
compile project(':dd-java-agent:agent-logging')
compile project(':dd-trace-api')
compile project(':internal-api')
implementation project(':internal-api:internal-api-8')
compile deps.slf4j
// ^ Generally a bad idea for libraries, but we're shadowing.

Expand All @@ -31,7 +32,7 @@ compileMain_java11Java.options.forkOptions.javaHome = file(System.env.JAVA_11_HO
compileMain_java11Java.sourceCompatibility = JavaVersion.VERSION_1_8
compileMain_java11Java.targetCompatibility = JavaVersion.VERSION_1_8
dependencies {
main_java11CompileOnly project(':internal-api')
main_java11CompileOnly project(':internal-api:internal-api-8')
main_java11CompileOnly "org.projectlombok:lombok:${project.lombok.version}" transitive false
main_java11AnnotationProcessor "org.projectlombok:lombok:${project.lombok.version}" transitive false
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
package datadog.trace.bootstrap.instrumentation.exceptions;

import datadog.trace.api.Config;
import datadog.trace.api.sampling.AdaptiveSampler;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import jdk.jfr.EventType;

final class ExceptionSampler {
/*
* Fixed 0.5 second sampling window.
* Logic in StreamingSampler relies on sampling window being small compared to (in our case) recording duration:
* Logic in AdaptiveSampler relies on sampling window being small compared to (in our case) recording duration:
* sampler may overshoot on one given window but should average to samplesPerWindow in the long run.
*/
private static final Duration SAMPLING_WINDOW = Duration.of(500, ChronoUnit.MILLIS);

private final StreamingSampler sampler;
private final AdaptiveSampler sampler;
private final EventType exceptionSampleType;

ExceptionSampler(final Config config) {
this(SAMPLING_WINDOW, getSamplesPerWindow(config), samplingWindowsPerRecording(config));
}

ExceptionSampler(final Duration windowDuration, final int samplesPerWindow, final int lookback) {
sampler = new StreamingSampler(windowDuration, samplesPerWindow, lookback);
sampler = new AdaptiveSampler(windowDuration, samplesPerWindow, lookback);
exceptionSampleType = EventType.getEventType(ExceptionSampleEvent.class);
}

Expand Down
1 change: 1 addition & 0 deletions dd-java-agent/instrumentation/instrumentation.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ shadowJar {
exclude(project(':dd-java-agent:agent-logging'))
exclude(project(':dd-trace-api'))
exclude(project(':internal-api'))
exclude(project(':internal-api:internal-api-8'))
exclude(dependency('org.slf4j::'))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,23 @@ class AgentTestRunnerTest extends AgentTestRunner {
if (!jfrSupported && info.getName().startsWith("datadog.trace.bootstrap.instrumentation.exceptions.")) {
continue; // skip exception-profiling classes - they won't load if JFR is not available
}
Class<?> bootstrapClass = Class.forName(info.getName())
if (bootstrapClass.getClassLoader() != BOOTSTRAP_CLASSLOADER) {
bootstrapClassesIncorrectlyLoaded.add(bootstrapClass)
try {
Class<?> bootstrapClass = Class.forName(info.getName())
if (bootstrapClass.getClassLoader() != BOOTSTRAP_CLASSLOADER) {
bootstrapClassesIncorrectlyLoaded.add(bootstrapClass)
}
break
} catch (UnsupportedClassVersionError e) {
// A dirty hack to allow passing this test on Java 7
if (info.getName().startsWith("datadog.trace.api.sampling.")) {
// The rate limiting sampler support is consciously compiled to Java 8 bytecode
// The sampler will not be used unless JFR is available -> running on Java 8+
// Simply ignore the error as the class will not be even attempted to get loaded on Java 7
break
}
// rethrow the exception otherwise
throw e
}
break
}
}
}
Expand Down
22 changes: 22 additions & 0 deletions internal-api/internal-api-8/internal-api-8.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
ext {
enableJunitPlatform = true
minJavaVersionForTests = JavaVersion.VERSION_1_8
}

apply from: "$rootDir/gradle/java.gradle"

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8

minimumBranchCoverage = 0.8

dependencies {
compile project(':internal-api')

testCompile deps.junit5
testCompile deps.jmc
testCompile deps.commonsMath
testCompile deps.mockito
testCompile deps.slf4j
testCompile project(":utils:test-utils")
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package datadog.trace.bootstrap.instrumentation.exceptions;
package datadog.trace.api.sampling;

import datadog.trace.util.AgentTaskScheduler;
import datadog.trace.util.AgentTaskScheduler.Task;
Expand All @@ -10,7 +10,7 @@
import java.util.concurrent.atomic.LongAdder;

/**
* A streaming (non-remembering) sampler.
* An adaptive streaming (non-remembering) sampler.
*
* <p>The sampler attempts to generate at most N samples per fixed time window in randomized
* fashion. For this it divides the timeline into 'sampling windows' of constant duration. Each
Expand All @@ -31,7 +31,7 @@
* compensate for too rapid changes in the incoming events rate and maintain the target average
* number of samples per window.
*/
class StreamingSampler {
public final class AdaptiveSampler {

/*
* Number of windows to look back when computing carried over budget.
Expand Down Expand Up @@ -86,7 +86,7 @@ boolean addSample(final long limit) {
* @param lookback the number of windows to consider in averaging the sampling rate
* @param taskScheduler agent task scheduler to use for periodic rolls
*/
StreamingSampler(
public AdaptiveSampler(
final Duration windowDuration,
final int samplesPerWindow,
final int lookback,
Expand All @@ -113,7 +113,8 @@ boolean addSample(final long limit) {
* @param samplesPerWindow the maximum number of samples in the sampling window
* @param lookback the number of windows to consider in averaging the sampling rate
*/
StreamingSampler(final Duration windowDuration, final int samplesPerWindow, final int lookback) {
public AdaptiveSampler(
final Duration windowDuration, final int samplesPerWindow, final int lookback) {
this(windowDuration, samplesPerWindow, lookback, AgentTaskScheduler.INSTANCE);
}

Expand All @@ -122,7 +123,7 @@ boolean addSample(final long limit) {
*
* @return {@literal true} if the event should be sampled
*/
final boolean sample() {
public final boolean sample() {
final Counts counts = countsRef.get();
counts.addTest();
if (ThreadLocalRandom.current().nextDouble() < probability) {
Expand Down Expand Up @@ -173,12 +174,12 @@ private static double computeIntervalAlpha(final int lookback) {
/*
* Important to use explicit class to avoid implicit hard references to StreamingSampler from within scheduler
*/
private static class RollWindowTask implements Task<StreamingSampler> {
private static class RollWindowTask implements Task<AdaptiveSampler> {

static final RollWindowTask INSTANCE = new RollWindowTask();

@Override
public void run(final StreamingSampler target) {
public void run(final AdaptiveSampler target) {
target.rollWindow();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package datadog.trace.bootstrap.instrumentation.exceptions;
package datadog.trace.api.sampling;

import static java.lang.Math.abs;
import static java.lang.Math.round;
Expand Down Expand Up @@ -37,10 +37,9 @@
* can be run multiple times - the number of iteration is passed in in {@literal
* com.datadog.profiling.exceptions.test-iterations} system property.
*/
@ExtendWith(MockitoExtension.class)
@Slf4j
class StreamingSamplerTest {

@ExtendWith(MockitoExtension.class)
class AdaptiveSamplerTest {
private static final Duration WINDOW_DURATION = Duration.ofSeconds(1);

/** Generates windows with numbers of events according to Poisson distribution */
Expand Down Expand Up @@ -177,8 +176,8 @@ private static class WindowSamplingResult {
private static final int LOOKBACK = 30;

@Mock AgentTaskScheduler taskScheduler;
@Captor ArgumentCaptor<Task<StreamingSampler>> rollWindowTaskCaptor;
@Captor ArgumentCaptor<StreamingSampler> rollWindowTargetCaptor;
@Captor ArgumentCaptor<Task<AdaptiveSampler>> rollWindowTaskCaptor;
@Captor ArgumentCaptor<AdaptiveSampler> rollWindowTargetCaptor;

@BeforeEach
public void setup() {
Expand Down Expand Up @@ -272,8 +271,8 @@ private void testSamplerInline(
log.info(
"> mode: {}, windows: {}, SAMPLES_PER_WINDOW: {}, LOOKBACK: {}, max error: {}%",
windowEventsSupplier, WINDOWS, SAMPLES_PER_WINDOW, LOOKBACK, maxErrorPercent);
final StreamingSampler sampler =
new StreamingSampler(WINDOW_DURATION, SAMPLES_PER_WINDOW, LOOKBACK, taskScheduler);
final AdaptiveSampler sampler =
new AdaptiveSampler(WINDOW_DURATION, SAMPLES_PER_WINDOW, LOOKBACK, taskScheduler);

// simulate event generation and sampling for the given number of sampling windows
final long expectedSamples = WINDOWS * SAMPLES_PER_WINDOW;
Expand Down Expand Up @@ -356,7 +355,7 @@ private void reportSampleIndexSkew(double[] sampleIndexSkewPerWindow) {
* samples and the sample index skew
*/
private WindowSamplingResult generateWindowEventsAndSample(
IntSupplier windowEventsSupplier, StreamingSampler sampler, Mean mean) {
IntSupplier windowEventsSupplier, AdaptiveSampler sampler, Mean mean) {
int samples = 0;
int events = windowEventsSupplier.getAsInt();
mean.clear();
Expand Down Expand Up @@ -427,8 +426,8 @@ private void testSamplerConcurrently(
final AtomicLong allSamples = new AtomicLong(0);
final AtomicLong receivedEvents = new AtomicLong(0);

final StreamingSampler sampler =
new StreamingSampler(WINDOW_DURATION, SAMPLES_PER_WINDOW, LOOKBACK, taskScheduler);
final AdaptiveSampler sampler =
new AdaptiveSampler(WINDOW_DURATION, SAMPLES_PER_WINDOW, LOOKBACK, taskScheduler);
final CyclicBarrier startBarrier = new CyclicBarrier(threadCount);
final CyclicBarrier endBarrier = new CyclicBarrier(threadCount, this::rollWindow);
final Mean[] means = new Mean[threadCount];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mock-maker-inline
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ include ':dd-trace-ot'

// agent projects
include ':internal-api'
include ':internal-api:internal-api-8'
include ':dd-trace-core'
include ':dd-trace-core:jfr-openjdk'
include ':dd-java-agent'
Expand Down