in thrift/src/main/scala/com/twitter/finatra/thrift/filters/StatsFilter.scala [25:120]
def apply(stats: StatsReceiver): ThriftMethodStats =
ThriftMethodStats(
failuresCounter = stats.counter("failures"),
failuresScope = stats.scope("failures"),
ignoredCounter = stats.counter("ignored"),
ignoredScope = stats.scope("ignored"),
latencyStat = stats.stat("latency_ms"),
successCounter = stats.counter("success"),
successesScope = stats.scope("success"),
requestsCounter = stats.counter("requests")
)
}
/** INTENDED FOR INTERNAL USE ONLY */
case class ThriftMethodStats(
failuresCounter: Counter,
failuresScope: StatsReceiver,
ignoredCounter: Counter,
ignoredScope: StatsReceiver,
latencyStat: Stat,
successCounter: Counter,
successesScope: StatsReceiver,
requestsCounter: Counter)
}
/**
* Tracks "per method" statistics scoped under `per_method_stats/<method>` including:
* - success/failure (with exceptions) counters
* - latency_ms histogram
*
* Example stats for a successful request to a method named `foo`:
*
* {{{
* per_method_stats/foo/failures 0
* per_method_stats/foo/ignored 0
* per_method_stats/foo/requests 1
* per_method_stats/foo/success 1
* per_method_stats/foo/latency_ms 43.000000 [43.0]
* }}}
*
* Example stats, for a failed request to a method named `foo`:
*
* {{{
* exceptions 1
* exceptions/java.lang.Exception 1
* per_method_stats/foo/failures 1
* per_method_stats/foo/failures/java.lang.Exception 1
* per_method_stats/foo/ignored 0
* per_method_stats/foo/requests 1
* per_method_stats/foo/success 0
* per_method_stats/foo/latency_ms 43.000000 [43.0]
* }}}
*
* Example stats, for a failed request to a method named `foo` with a [[ResponseClassifier]] which
* classifies [[java.lang.Exception]] as Ignorable:
*
* {{{
* exceptions 1
* exceptions/java.lang.Exception 1
* per_method_stats/foo/failures 0
* per_method_stats/foo/ignored 1
* per_method_stats/foo/ignored/java.lang.Exception 1
* per_method_stats/foo/requests 1
* per_method_stats/foo/success 0
* per_method_stats/foo/latency_ms 43.000000 [43.0]
* }}}
*
* requests == success + failures + ignored
* The logical success rate for a method can be calculated as `success / (success + failures)`
*
* @note It is expected that this Filter is inserted ABOVE the [[ExceptionMappingFilter]] in a
* given filter chain, e.g., `StatsFilter.andThen(ExceptionMappingFilter)`.
* For the response flow, [[StatsFilter]] would happen AFTER [[ExceptionMappingFilter]] and
* calculate mapped result.
* @param statsReceiver the [[com.twitter.finagle.stats.StatsReceiver]] to which
* to record stats.
* @param responseClassifier a [[ThriftResponseClassifier]] used to determine when a response
* is successful or not.
*/
@Singleton
class StatsFilter @Inject() (
statsReceiver: StatsReceiver,
responseClassifier: ThriftResponseClassifier)
extends Filter.TypeAgnostic {
import StatsFilter._
/* Public */
/**
* Secondary constructor which accepts a [[StatsReceiver]]. The [[ThriftResponseClassifier]]
* is defaulted to [[ThriftResponseClassifier.ThriftExceptionsAsFailures]].
*
* @param statsReceiver the [[com.twitter.finagle.stats.StatsReceiver]] to which
* to record stats.
*/
def this(statsReceiver: StatsReceiver) {