Basics¶
Gauges¶
Gauges measure discrete values at the time they are sampled. These are useful for measuring queue depths and pool sizes.
// scala
import java.util.ArrayBlockingQueue
val aQueue = new ArrayBlockingQueue[Job]()
val queueSize = statsReceiver.addGauge("queue_size") {
aQueue.size
}
// java
import com.twitter.finagle.stats.Gauge;
import java.util.ArrayBlockingQueue;
ArrayBlockingQueue<Job> aQueue =
new ArrayBlockingQueue<Job>();
Gauge queueSize = StatsReceivers.addGauge(
statsReceiver,
new Callable<Float>() {
@Override public Float call() { return aQueue.size(); }
},
"queue_size"
);
Counters¶
Counters are used to, well, count how often something happens. Common examples include the number of requests dispatched and failure counts.
// scala
val numRequests = statsReceiver.counter("num_requests")
numRequests.incr()
// java
import com.twitter.finagle.stats.Counter;
Counter numRequests =
statsReceiver.counter(statsReceiver, "num_requests");
numRequests.incr();
Stats¶
Stats provide a distribution of values that are seen, including percentiles, averages and maximums. Stats are quite useful for measuring the n-th percentiles for latency of requests or capturing the distribution of work batches.
// scala
import com.twitter.finagle.stats.Stat
import java.util.concurrent.TimeUnit
val latency = statsReceiver.stat("latency_ms")
Stat.time(latency, TimeUnit.MILLISECONDS) {
twiddleBits();
}
// java
import com.twitter.finagle.stats.Stat;
import com.twitter.finagle.stats.JStat;
import java.util.concurrent.TimeUnit;
Stat latency = statsReceiver.stat(statsReceiver, "latency_ms");
JStat.time(
latency,
new Callable<Void>() {
@Override public void call() { twiddleBits(); }
},
TimeUnit.MILLISECONDS
);
Verbosity Levels¶
Each metric created via a StatsReceiver has a verbosity level (i.e., “debug” or “default”) attached to it. Distinguishing verbosity levels for metrics is optional and is up to a concrete implementation. Doing this, however, helps to separate debug metrics (only helpful in troubleshooting) from their operationally-required counterparts (provide visibility into a healthy process) thus potentially reducing the observability cost.
Note
Unless an explicit Verbosity
is passed, Verbosity.Default
is used.
// scala
import com.twitter.finagle.stats.Verbosity
val someDebugEvent = statsReceiver.counter(Verbosity.Debug, "some_debug_event")
// java
import java.util.concurrent.Counter;
import java.util.concurrent.Verbosity;
Counter someDebugEvent = statsReceiver.counter(Verbosity.Debug(), "some_debug_event")