import java.security.SecureRandom;
import java.util.BitSet;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
public class RequestSampler {
private final AtomicInteger counter = new AtomicInteger(0);
private final BitSet sampleDecisions;
private float percentage =0.1f;
private static float percentCount = 10000.0f;
public RequestSampler(float percentage) {
RequestSampler.setPercentCount(1/percentage);
int outOf100 = (int) (percentage * percentCount);
this.sampleDecisions = randomBitSet((int)percentCount, outOf100, new SecureRandom());
this.percentage = percentage;
}
public boolean isSampled() {
if (this.percentage == 0) {
return false;
} else if (this.percentage == percentCount) {
return true;
}
synchronized (this) {
final int i = this.counter.getAndIncrement();
boolean result = this.sampleDecisions.get(i);
if (i == (percentCount-1)) {
this.counter.set(0);
}
return result;
}
}
private BitSet randomBitSet(int size, int cardinality, Random rnd) {
BitSet result = new BitSet(size);
int[] chosen = new int[cardinality];
int i;
for (i = 0; i < cardinality; ++i) {
chosen[i] = i;
result.set(i);
}
for (; i < size; ++i) {
int j = rnd.nextInt(i + 1);
if (j < cardinality) {
result.clear(chosen[j]);
result.set(i);
chosen[j] = i;
}
}
return result;
}
public static float getPercentCount() {
return percentCount;
}
public static void setPercentCount(float percentCount) {
RequestSampler.percentCount = percentCount;
}
}