Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit 63662d2

Browse files
author
Dan Richelson
committed
Add event sampling. Name threads.
1 parent b7d87be commit 63662d2

File tree

3 files changed

+43
-22
lines changed

3 files changed

+43
-22
lines changed

src/main/java/com/launchdarkly/client/EventProcessor.java

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.launchdarkly.client;
22

3+
import com.google.common.util.concurrent.ThreadFactoryBuilder;
34
import com.google.gson.Gson;
45
import org.apache.http.HttpStatus;
56
import org.apache.http.client.methods.CloseableHttpResponse;
@@ -14,22 +15,34 @@
1415
import java.io.IOException;
1516
import java.util.ArrayList;
1617
import java.util.List;
18+
import java.util.Random;
1719
import java.util.concurrent.*;
1820

1921
class EventProcessor implements Closeable {
20-
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory());
22+
ThreadFactory threadFactory = new ThreadFactoryBuilder()
23+
.setDaemon(true)
24+
.setNameFormat("LaunchDarkly-EventProcessor-%d")
25+
.build();
26+
private final ScheduledExecutorService scheduler =
27+
Executors.newSingleThreadScheduledExecutor(threadFactory);
28+
private final Random random = new Random();
2129
private final BlockingQueue<Event> queue;
2230
private final String apiKey;
31+
private final LDConfig config;
2332
private final Consumer consumer;
2433

2534
EventProcessor(String apiKey, LDConfig config) {
2635
this.apiKey = apiKey;
2736
this.queue = new ArrayBlockingQueue<>(config.capacity);
2837
this.consumer = new Consumer(config);
38+
this.config = config;
2939
this.scheduler.scheduleAtFixedRate(consumer, 0, config.flushInterval, TimeUnit.SECONDS);
3040
}
3141

3242
boolean sendEvent(Event e) {
43+
if (config.samplingInterval > 0 && random.nextInt(config.samplingInterval) != 0) {
44+
return true;
45+
}
3346
return queue.offer(e);
3447
}
3548

@@ -43,18 +56,8 @@ public void flush() {
4356
this.consumer.flush();
4457
}
4558

46-
static class DaemonThreadFactory implements ThreadFactory {
47-
public Thread newThread(Runnable r) {
48-
Thread thread = new Thread(r);
49-
thread.setDaemon(true);
50-
return thread;
51-
}
52-
}
53-
5459
class Consumer implements Runnable {
5560
private final Logger logger = LoggerFactory.getLogger(Consumer.class);
56-
57-
5861
private final CloseableHttpClient client;
5962
private final LDConfig config;
6063

@@ -78,6 +81,7 @@ public void flush() {
7881
}
7982

8083
private void postEvents(List<Event> events) {
84+
logger.debug("Posting " + events.size() + " event(s)..");
8185
CloseableHttpResponse response = null;
8286
Gson gson = new Gson();
8387
String json = gson.toJson(events);
@@ -95,13 +99,11 @@ private void postEvents(List<Event> events) {
9599
if (status >= 300) {
96100
if (status == HttpStatus.SC_UNAUTHORIZED) {
97101
logger.error("Invalid API key");
98-
}
99-
else {
102+
} else {
100103
logger.error("Unexpected status code: " + status);
101104
}
102-
}
103-
else {
104-
logger.debug("Successfully processed events");
105+
} else {
106+
logger.debug("Successfully posted " + events.size() + " event(s).");
105107
}
106108
} catch (IOException e) {
107109
logger.error("Unhandled exception in LaunchDarkly client attempting to connect to URI: " + config.eventsURI, e);
@@ -112,7 +114,6 @@ private void postEvents(List<Event> events) {
112114
logger.error("Unhandled exception in LaunchDarkly client", e);
113115
}
114116
}
115-
116117
}
117118
}
118119
}

src/main/java/com/launchdarkly/client/LDConfig.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public final class LDConfig {
2323
private static final int DEFAULT_FLUSH_INTERVAL = 5;
2424
private static final long DEFAULT_POLLING_INTERVAL_MILLIS = 1000L;
2525
private static final long DEFAULT_START_WAIT_MILLIS = 0L;
26+
private static final int DEFAULT_SAMPLING_INTERVAL = 0;
2627
private static final Logger logger = LoggerFactory.getLogger(LDConfig.class);
2728

2829
protected static final LDConfig DEFAULT = new Builder().build();
@@ -42,6 +43,7 @@ public final class LDConfig {
4243
final boolean offline;
4344
final long pollingIntervalMillis;
4445
final long startWaitMillis;
46+
final int samplingInterval;
4547

4648
protected LDConfig(Builder builder) {
4749
this.baseURI = builder.baseURI;
@@ -63,6 +65,7 @@ protected LDConfig(Builder builder) {
6365
this.pollingIntervalMillis = builder.pollingIntervalMillis;
6466
}
6567
this.startWaitMillis = builder.startWaitMillis;
68+
this.samplingInterval = builder.samplingInterval;
6669
}
6770

6871
/**
@@ -94,6 +97,7 @@ public static class Builder {
9497
private long pollingIntervalMillis = DEFAULT_POLLING_INTERVAL_MILLIS;
9598
private FeatureStore featureStore = new InMemoryFeatureStore();
9699
public long startWaitMillis = DEFAULT_START_WAIT_MILLIS;
100+
public int samplingInterval = DEFAULT_SAMPLING_INTERVAL;
97101

98102
/**
99103
* Creates a builder with all configuration parameters set to the default
@@ -335,6 +339,21 @@ public Builder startWaitMillis(long startWaitMillis) {
335339
return this;
336340
}
337341

342+
/**
343+
* Enable event sampling. When set to the default of zero, sampling is disabled and all events
344+
* are sent back to LaunchDarkly. When set to greater than zero, there is a 1 in
345+
* <code>samplingInterval</code> chance events will be will be sent.
346+
*
347+
* <p>Example: if you want 5% sampling rate, set <code>samplingInterval</code> to 20.
348+
*
349+
* @param samplingInterval the sampling interval.
350+
* @return the builder
351+
*/
352+
public Builder samplingInterval(int samplingInterval) {
353+
this.samplingInterval = samplingInterval;
354+
return this;
355+
}
356+
338357
HttpHost proxyHost() {
339358
if (this.proxyHost == null && this.proxyPort == -1 && this.proxyScheme == null) {
340359
return null;

src/main/java/com/launchdarkly/client/PollingProcessor.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package com.launchdarkly.client;
22

3+
import com.google.common.util.concurrent.ThreadFactoryBuilder;
34
import org.slf4j.Logger;
45
import org.slf4j.LoggerFactory;
56

67
import java.io.IOException;
7-
import java.util.concurrent.Executors;
8-
import java.util.concurrent.Future;
9-
import java.util.concurrent.ScheduledExecutorService;
10-
import java.util.concurrent.TimeUnit;
8+
import java.util.concurrent.*;
119
import java.util.concurrent.atomic.AtomicBoolean;
1210

1311
public class PollingProcessor implements UpdateProcessor {
@@ -40,7 +38,10 @@ public Future<Void> start() {
4038
logger.info("Starting LaunchDarkly polling client with interval: "
4139
+ config.pollingIntervalMillis + " milliseconds");
4240
final VeryBasicFuture initFuture = new VeryBasicFuture();
43-
scheduler = Executors.newScheduledThreadPool(1);
41+
ThreadFactory threadFactory = new ThreadFactoryBuilder()
42+
.setNameFormat("LaunchDarkly-PollingProcessor-%d")
43+
.build();
44+
scheduler = Executors.newScheduledThreadPool(1, threadFactory);
4445

4546
scheduler.scheduleAtFixedRate(new Runnable() {
4647
@Override

0 commit comments

Comments
 (0)