Skip to content

Commit

Permalink
NumberFormatter: use ThreadLocal for thread safety
Browse files Browse the repository at this point in the history
  • Loading branch information
truthbk committed Mar 12, 2020
1 parent 376c944 commit d5cd46b
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 11 deletions.
33 changes: 26 additions & 7 deletions src/main/java/com/timgroup/statsd/NonBlockingStatsDClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,23 @@ public class NonBlockingStatsDClient implements StatsDClient {
* The NumberFormat instances are not threadsafe but are only ever called from
* the sender thread.
*/
private static final NumberFormat NUMBER_FORMATTER = newFormatter();
private static final NumberFormat SAMPLE_RATE_FORMATTER = newFormatter();
private static final ThreadLocal<NumberFormat> NUMBER_FORMATTER = new ThreadLocal<NumberFormat>() {
@Override
protected NumberFormat initialValue() {
return newFormatter(false);
}
};
private static final ThreadLocal<NumberFormat> SAMPLE_RATE_FORMATTER = new ThreadLocal<NumberFormat>() {
@Override
protected NumberFormat initialValue() {
return newFormatter(true);
}
};

static {
NUMBER_FORMATTER.setMaximumFractionDigits(6);
SAMPLE_RATE_FORMATTER.setMinimumFractionDigits(6);
}

private static NumberFormat newFormatter() {
private static NumberFormat newFormatter(boolean sampler) {
// Always create the formatter for the US locale in order to avoid this bug:
// https://github.com/indeedeng/java-dogstatsd-client/issues/3
NumberFormat numberFormatter = NumberFormat.getInstance(Locale.US);
Expand All @@ -96,9 +104,20 @@ private static NumberFormat newFormatter() {
symbols.setNaN("NaN");
decimalFormat.setDecimalFormatSymbols(symbols);
}

if (sampler) {
numberFormatter.setMinimumFractionDigits(6);
} else {
numberFormatter.setMaximumFractionDigits(6);
}

return numberFormatter;
}

private static String format(ThreadLocal<NumberFormat> formatter, double value) {
return formatter.get().format(value);
}

private final String prefix;
private final DatagramChannel clientChannel;
private final StatsDClientErrorHandler handler;
Expand Down Expand Up @@ -326,7 +345,7 @@ public final void writeTo(StringBuilder builder) {
writeValue(builder);
builder.append('|').append(type);
if (!Double.isNaN(sampleRate)) {
builder.append('|').append('@').append(SAMPLE_RATE_FORMATTER.format(sampleRate));
builder.append('|').append('@').append(format(SAMPLE_RATE_FORMATTER, sampleRate));
}
tagString(tags, builder);
}
Expand All @@ -340,7 +359,7 @@ private void send(String aspect, final double value, String type, double sampleR

statsDProcessor.send(new StatsDMessage(aspect, type, sampleRate, tags) {
@Override protected void writeValue(StringBuilder builder) {
builder.append(NUMBER_FORMATTER.format(value));
builder.append(format(NUMBER_FORMATTER, value));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ public void run() {
}

final Message message = messages.poll(WAIT_SLEEP_MS, TimeUnit.MILLISECONDS);
// TODO: revisit this logic - cleanup, remove duplicate code.
if (message != null) {

builder.setLength(0);
Expand Down Expand Up @@ -66,7 +65,6 @@ public void run() {
writeBuilderToSendBuffer(sendBuffer);
}

// TODO: revisit this logic
if (null == messages.peek()) {
outboundQueue.put(sendBuffer);
sendBuffer = bufferPool.borrow();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public void run() {
return;
}
final Message message = messages.poll();
// TODO: revisit this logic - cleanup, remove duplicate code.
if (message != null) {

qsize.decrementAndGet();
Expand Down Expand Up @@ -72,7 +71,6 @@ public void run() {
writeBuilderToSendBuffer(sendBuffer);
}

// TODO: revisit this logic
if (null == messages.peek()) {
outboundQueue.put(sendBuffer);
sendBuffer = bufferPool.borrow();
Expand Down

0 comments on commit d5cd46b

Please sign in to comment.