diff --git a/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/Sketch.java b/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/Sketch.java index ab9de8b4..7c61f007 100644 --- a/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/Sketch.java +++ b/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/Sketch.java @@ -13,11 +13,10 @@ * Reusable DDSketch builder. Consumes a batch of observations and populates sum, min, max, count * and distribution bins accordingly. * - *
This implementation maintains at most 4096 bins with 64-bit counters. Number of bins is a hard - * limit and is enforced by the intake. + *
This implementation maintains at most 4096 bins with 64-bit counters. * - *
Prioritizes accuracy of higher key bins (higher percentiles) over lower ones when number of - * bins exceeds the limit. + *
Prioritizes accuracy of higher key bins (higher percentiles) over lower ones when the number
+ * of bins exceeds the limit.
*/
public class Sketch {
static final double gamma = 130.0 / 128;
@@ -59,6 +58,12 @@ static short key(double value) {
/** Receives (key, count) pairs from {@link #bins(BinConsumer)}. */
public interface BinConsumer {
+ /**
+ * Process one sketch bin.
+ *
+ * @param key a value that specifies the range of observations counted in this bin.
+ * @param count number of observations in the bin.
+ */
void consumeBin(short key, long count);
}
@@ -69,7 +74,11 @@ public int size() {
return size;
}
- /** Feeds each populated bin to {@code consumer} in order. */
+ /**
+ * Feeds each populated bin to {@code consumer} in order.
+ *
+ * @param consumer a consumer to feed sketch bins to.
+ */
public void bins(BinConsumer consumer) {
int idx = head;
for (int i = 0; i < size; i++) {
@@ -114,11 +123,13 @@ public long count() {
/**
* Builds the sketch from the given values.
*
- * @param observations the observations to include in the sketch
+ * @param observations the observations to include in the sketch.
* @param sampleRate the sampling rate used to collect {@code observations}, in {@code (0, 1]}.
* Each observation is weighted by {@code 1 / sampleRate} when accumulating counts and sums.
* Rates below ~1.08e-19 saturate the per-observation weight; bin counts and the total
* {@code count} field saturate at {@link Long#MAX_VALUE} on overflow.
+ * @throws IllegalArgumentException if {@code sampleRate} is {@code NaN}, not positive, or
+ * greater than 1.
*/
public void build(long[] observations, double sampleRate) {
validateSampleRate(sampleRate);
@@ -136,11 +147,13 @@ public void build(long[] observations, double sampleRate) {
/**
* Builds the sketch from the given values.
*
- * @param observations the observations to include in the sketch
+ * @param observations the observations to include in the sketch.
* @param sampleRate the sampling rate used to collect {@code observations}, in {@code (0, 1]}.
* Each observation is weighted by {@code 1 / sampleRate} when accumulating counts and sums.
* Rates below ~1.08e-19 saturate the per-observation weight; bin counts and the total
* {@code count} field saturate at {@link Long#MAX_VALUE} on overflow.
+ * @throws IllegalArgumentException if {@code sampleRate} is {@code NaN}, not positive, or
+ * greater than 1.
*/
public void build(double[] observations, double sampleRate) {
validateSampleRate(sampleRate);
diff --git a/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/DirectHttpClient.java b/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/DirectHttpClient.java
index e0b8b5d3..7bb83bc5 100644
--- a/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/DirectHttpClient.java
+++ b/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/DirectHttpClient.java
@@ -11,6 +11,7 @@
import com.datadoghq.dogstatsd.http.serializer.PayloadBuilder;
import com.datadoghq.dogstatsd.http.serializer.PayloadConsumer;
import java.net.URI;
+import java.nio.BufferOverflowException;
import java.util.List;
import java.util.Objects;
@@ -35,6 +36,7 @@ public class DirectHttpClient {
*
* @param forwarder the forwarder used to send payloads, required.
* @return a new builder.
+ * @throws NullPointerException if {@code forwarder} is null.
*/
public static Builder builder(final Forwarder forwarder) {
return new Builder(forwarder);
@@ -126,6 +128,7 @@ public DirectHttpClient build() {
* @param value the gauge value.
* @param ts the timestamp of the point in seconds since Unix epoch.
* @param tags the tags to attach to the point.
+ * @throws BufferOverflowException if the encoded metric exceeds the maximum payload size.
*/
public void gauge(String name, double value, long ts, List For compatibility with aggregated dogstatsd counts, assumes aggregation interval of 10s.
+ * For compatibility with aggregated dogstatsd counts, assumes an aggregation interval of
+ * 10s.
*
* @param name the metric name, to which the client prefix is prepended.
* @param value the count accumulated over the interval starting at {@code ts}.
* @param ts the timestamp of the point in seconds since Unix epoch.
* @param tags the tags to attach to the point.
+ * @throws BufferOverflowException if the encoded metric exceeds the maximum payload size.
*/
public void count(String name, double value, long ts, List Only one metric can be encoded at a time.
*
* @param name Name of the metric.
- * @return Builder instance.
+ * @return New builder instance.
+ * @throws BufferOverflowException if finishing the previous metric overflows the payload.
*/
public ScalarMetric count(String name) {
ScalarMetric m = new ScalarMetric(this, 1, name);
@@ -159,12 +160,13 @@ public ScalarMetric count(String name) {
}
/**
- * Begin encoding new rate metric.
+ * Begin encoding a new rate metric.
*
* Only one metric can be encoded at a time.
*
* @param name Name of the metric.
* @return New builder instance.
+ * @throws BufferOverflowException if finishing the previous metric overflows the payload.
*/
public ScalarMetric rate(String name) {
ScalarMetric m = new ScalarMetric(this, 2, name);
@@ -173,12 +175,13 @@ public ScalarMetric rate(String name) {
}
/**
- * Begin encoding new gauge metric.
+ * Begin encoding a new gauge metric.
*
* Only one metric can be encoded at a time.
*
* @param name Name of the metric.
* @return New builder instance.
+ * @throws BufferOverflowException if finishing the previous metric overflows the payload.
*/
public ScalarMetric gauge(String name) {
ScalarMetric m = new ScalarMetric(this, 3, name);
@@ -187,12 +190,13 @@ public ScalarMetric gauge(String name) {
}
/**
- * Begin encoding new sketch metric.
+ * Begin encoding a new sketch metric.
*
* Only one metric can be encoded at a time.
*
* @param name Name of the metric.
* @return New builder instance.
+ * @throws BufferOverflowException if finishing the previous metric overflows the payload.
*/
public SketchMetric sketch(String name) {
SketchMetric m = new SketchMetric(this, 4, name);
@@ -305,7 +309,11 @@ void flushPayload() {
timestampsDelta.clear();
}
- /** Finish any pending data. */
+ /**
+ * Finish any pending data.
+ *
+ * @throws BufferOverflowException if finishing the in-progress metric overflows the payload.
+ */
public void close() {
endMetric();
flushPayload();
diff --git a/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/serializer/PayloadConsumer.java b/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/serializer/PayloadConsumer.java
index 594afb03..64106aad 100644
--- a/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/serializer/PayloadConsumer.java
+++ b/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/serializer/PayloadConsumer.java
@@ -10,7 +10,7 @@
/** Consumes payloads from the PayloadBuilder. */
public interface PayloadConsumer {
/**
- * Called when payload builder finishes another payload.
+ * Called when the payload builder finishes another payload.
*
* @param payload Completed payload.
*/
diff --git a/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/serializer/ScalarMetric.java b/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/serializer/ScalarMetric.java
index 2433b0ca..201bcba2 100644
--- a/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/serializer/ScalarMetric.java
+++ b/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/serializer/ScalarMetric.java
@@ -19,7 +19,7 @@ protected ScalarMetric self() {
}
/**
- * Add new data point to the timeseries.
+ * Add a new data point to the timeseries.
*
* @param timestamp Timestamp of the point in seconds since Unix epoch.
* @param value Metric value at timestamp.
diff --git a/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/serializer/SketchMetric.java b/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/serializer/SketchMetric.java
index 3ace6018..e74afbf9 100644
--- a/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/serializer/SketchMetric.java
+++ b/dogstatsd-http/core/src/main/java/com/datadoghq/dogstatsd/http/serializer/SketchMetric.java
@@ -53,6 +53,9 @@ protected SketchMetric self() {
* @param timestamp Timestamp of the point in seconds since Unix epoch.
* @param sketch Sketch supplying the summary statistics and bin distribution.
* @return This.
+ * @throws BufferOverflowException if the sketch's bin data alone would exceed the maximum
+ * payload size. The metric is no longer valid; call {@link PayloadBuilder#resetMetric()}
+ * before encoding any further metrics.
*/
public SketchMetric addPoint(long timestamp, Sketch sketch) {
// Skip doing the work if just the bin data would exceed payload size limit.
diff --git a/dogstatsd-http/forwarder/src/main/java/com/datadoghq/dogstatsd/http/forwarder/Forwarder.java b/dogstatsd-http/forwarder/src/main/java/com/datadoghq/dogstatsd/http/forwarder/Forwarder.java
index c763e98a..8afd3208 100644
--- a/dogstatsd-http/forwarder/src/main/java/com/datadoghq/dogstatsd/http/forwarder/Forwarder.java
+++ b/dogstatsd-http/forwarder/src/main/java/com/datadoghq/dogstatsd/http/forwarder/Forwarder.java
@@ -76,6 +76,8 @@ public static Builder builder() {
/**
* Captures a snapshot of the forwarder's telemetry counters and queue state, clearing delta
* counters so subsequent snapshots report activity since this call.
+ *
+ * @return a telemetry snapshot.
*/
public Telemetry.Snapshot snapshot() {
return telemetry.snapshot(queue);
@@ -102,14 +104,17 @@ public void run() {
/**
* Enqueues a payload for delivery to the given endpoint.
*
- * If the queue is full, behaviour is determined by the {@link WhenFull} policy set with
+ * If the queue is full, behavior is determined by the {@link WhenFull} policy set with
* {@link Builder#whenFull}.
*
- * @param url the remote HTTP endpoint to POST the payload to
- * @param payload the raw bytes to deliver
+ * @param url the remote HTTP endpoint to POST the payload to.
+ * @param payload the raw bytes to deliver.
* @throws InterruptedException if the calling thread is interrupted while waiting for space
- * ({@link WhenFull#BLOCK} mode only)
- * @throws IllegalStateException if the forwarder has been closed via {@link #close(Duration)}
+ * ({@link WhenFull#BLOCK} mode only).
+ * @throws IllegalStateException if the forwarder has been closed via {@link #close(Duration)}.
+ * @throws IllegalArgumentException if {@code payload} is larger than the queue's {@link
+ * Builder#maxRequestsBytes} limit, in which case it can never be delivered.
+ * @throws NullPointerException if {@code url} or {@code payload} is null.
*/
public void send(URI url, byte[] payload) throws InterruptedException {
Objects.requireNonNull(url, "url");
@@ -213,8 +218,8 @@ void backoff() throws InterruptedException {
* @param timeout maximum time to wait for the backlog to drain. {@code null} means wait
* forever.
* @return {@code true} if the queue drained cleanly with no unsent payloads remaining; {@code
- * false} if the timeout elapsed with data still queued
- * @throws InterruptedException if the calling thread is interrupted while waiting
+ * false} if the timeout elapsed with data still queued.
+ * @throws InterruptedException if the calling thread is interrupted while waiting.
*/
public boolean close(Duration timeout) throws InterruptedException {
queue.close();
@@ -254,6 +259,7 @@ private Builder() {}
*
* @param val the maximum number of buffered bytes; must be positive.
* @return this builder.
+ * @throws IllegalArgumentException if {@code val} is not positive.
*/
public Builder maxRequestsBytes(final long val) {
if (val <= 0) {
@@ -268,6 +274,7 @@ public Builder maxRequestsBytes(final long val) {
*
* @param val the maximum number of attempts; must be at least 1.
* @return this builder.
+ * @throws IllegalArgumentException if {@code val} is less than 1.
*/
public Builder maxTries(final long val) {
if (val < 1) {
@@ -282,6 +289,7 @@ public Builder maxTries(final long val) {
*
* @param val the action to take.
* @return this builder.
+ * @throws NullPointerException if {@code val} is null.
*/
public Builder whenFull(final WhenFull val) {
whenFull = Objects.requireNonNull(val, "whenFull");
@@ -293,6 +301,8 @@ public Builder whenFull(final WhenFull val) {
*
* @param val the connect timeout; must be positive.
* @return this builder.
+ * @throws NullPointerException if {@code val} is null.
+ * @throws IllegalArgumentException if {@code val} is not positive.
*/
public Builder connectTimeout(final Duration val) {
Objects.requireNonNull(val, "connectTimeout");
@@ -310,6 +320,7 @@ public Builder connectTimeout(final Duration val) {
* @param val the request timeout, or {@code null} to disable it; must be positive when
* non-null.
* @return this builder.
+ * @throws IllegalArgumentException if {@code val} is non-null and not positive.
*/
public Builder requestTimeout(final Duration val) {
if (val != null && (val.isNegative() || val.isZero())) {
@@ -326,6 +337,9 @@ public Builder requestTimeout(final Duration val) {
*
* @param context the context to take the values from.
* @return this builder.
+ * @throws NullPointerException if {@code context} is null.
+ * @throws IllegalArgumentException if the context's local or external data contains
+ * characters that are not valid in an HTTP header value.
*/
public Builder context(final ForwarderContext context) {
contextSet = true;
@@ -341,6 +355,8 @@ public Builder context(final ForwarderContext context) {
* started yet.
*
* @return a new forwarder.
+ * @throws IllegalStateException if no context was set with {@link #context} and the default
+ * one cannot be built because {@code DD_DOGSTATSD_HTTP_URL} is not defined.
*/
public Forwarder build() {
if (!contextSet) {
diff --git a/dogstatsd-http/forwarder/src/main/java/com/datadoghq/dogstatsd/http/forwarder/Telemetry.java b/dogstatsd-http/forwarder/src/main/java/com/datadoghq/dogstatsd/http/forwarder/Telemetry.java
index 574cdfa8..820298e2 100644
--- a/dogstatsd-http/forwarder/src/main/java/com/datadoghq/dogstatsd/http/forwarder/Telemetry.java
+++ b/dogstatsd-http/forwarder/src/main/java/com/datadoghq/dogstatsd/http/forwarder/Telemetry.java
@@ -18,7 +18,7 @@ public class Telemetry {
/** HTTP status code used to record transport-level (no-response) errors. */
public static final int TRANSPORT_ERROR_CODE = 0;
- /** Point-in-time view of cumulative counters and queue state. */
+ /** Queue state at snapshot time, plus counters for the interval leading up to it. */
public static final class Snapshot {
/**
* Wall-clock time (Unix epoch milliseconds) at the start of the interval covered by this
@@ -27,17 +27,36 @@ public static final class Snapshot {
*/
public long intervalStartMillis;
+ /** Number of payloads added to the queue in this interval. */
public long enqueuedPayloads;
+
+ /** Number of payloads successfully delivered in this interval. */
public long deliveredPayloads;
+
+ /** Total size in bytes of payloads added to the queue in this interval. */
public long enqueuedBytes;
+
+ /** Total size in bytes of payloads successfully delivered in this interval. */
public long deliveredBytes;
+
+ /** Number of payloads currently in the queue. */
public long queuePayloads;
+
+ /** Total size in bytes of payloads currently in the queue. */
public long queueBytes;
+
+ /** Maximum number of bytes the queue is allowed to store. */
public long queueMaxBytes;
+
+ /** Number of payloads dropped in this interval. */
public long droppedPayloads;
+
+ /** Total size in bytes of payloads dropped in this interval. */
public long droppedBytes;
- /** Nanos elapsed since the oldest queued item was enqueued; {@code 0} if queue is empty. */
+ /**
+ * Nanos elapsed since the oldest queued item was enqueued; {@code 0} if the queue is empty.
+ */
public long oldestEnqueuedAgeNanos;
/** Nanos elapsed since the last successful submission; {@code 0} if none yet. */
@@ -46,7 +65,7 @@ public static final class Snapshot {
/** Totals keyed by HTTP code. */
public Map