This is a simple statsd module for Play Framework 2. It pulls in configuration from conf/application.conf and provides a singleton object Statsd with methods for counter and timing calls to statsd. It provides both a Scala and Java interface. Similar to the Play 2 convention, the Scala interface is called play.modules.statsd.api.Statsd, and the Java interface is play.modules.statsd.Statsd.
To install, add "com.typesafe.play.plugins" %% "play-statsd" % "2.3.0" to your dependencies, for example:
val appDendencies = Seq(@"com.typesafe.play.plugins" %% "play-statsd" % "2.3.0")The following are configuration flags that belong in conf/application.conf:
statsd.enabled: Should betrueto use this module. Can befalsefor testing.statsd.stat.prefix: The prefix for all stats sent by this app. They will appear in a folder of the same name on graphite.statsd.routes.prefix: The prefix to be attached to all routes logged by the StatsdFilter. By default this is “routes”. This prefix is in addition to the main prefix (so if that’s foo, then the default will be foo.routes).statsd.routes.pathSeparator: The separator character that’s used to replace “/” in routes logged by the StatsdFilter. By default this is “.”.statsd.routes.combined.prefix: The prefix to be attached to combined http request logging. By default this is “routes.combined”.statsd.host: The hostname of the statsd server.statsd.port: The port for the statsd server.
If there are any configuration problems (missing or unparseable settings), there will be a warning the first time the module is used but will not cause an error in your app.
To use this module, first add this import:
import play.modules.statsd.api.Statsd
Now you can call it like this:
Statsd.increment("my.stat") // Increment my.stat by 1
Statsd.increment("my.bigger.stat", value = 100) // Increment my.bigger.stat by 100
Statsd.increment("my.frequent.stat", samplingRate = 0.1) // Increment my.frequent.stat 10% of the time
Statsd.timing("my.operation", 100) // my.operation took 100 ms
Statsd.timing("my.frequent.operation", 10, 0.5) // my operation took 50 ms. Send this stat 50% of the time
Statsd.time("my.operation.i.dont.want.to.time.myself") {
// do some stuff...
} // This will get timed automatically.
Statsd.gauge("my.value", 42) // Record 42 for my.value
Statsd.gauge("my.value", 10, true) // Increment my.value by 10
Statsd.gauge("my.value", -10, true) // Decrement my.value by 10Any errors will be logged, but will not cause the app to fail.
To use this module, first add this import:
import play.modules.statsd.Statsd;
Now you can call it like this:
Statsd.increment("my.stat"); // Increment my.stat by 1
Statsd.increment("my.bigger.stat", 100); // Increment my.bigger.stat by 100
Statsd.increment("my.frequent.stat", 0.1); // Increment my.frequent.stat 10% of the time
Statsd.timing("my.operation", 100); // my.operation took 100 ms
Statsd.timing("my.frequent.operation", 10, 0.5); // my operation took 50 ms. Send this stat 50% of the time
String result = Statsd.time("my.operation.i.dont.want.to.time.myself", new F.Function0<String>() {
public String apply() {
return "some result";
}}); // This will get timed automatically.
Statsd.gauge("my.value", 42L) // Record 42 for my.value
Statsd.gauge("my.value", 10L, true) // Increment my.value by 10
Statsd.gauge("my.value", -10L, true) // Decrement my.value by 10Any errors will be logged, but will not cause the app to fail.
This module comes with an optional filter that can be used to log request counts and time requests. It maps requests according to their configured path and method to a statsd key, using the following rules:
GET /foo/bar -> routes.foo.bar.get GET /foo/:param -> routes.foo.param.get GET /foo/*path -> routes.foo.path.get POST /foo/$id<[0-9]+> -> routes.foo.id.post GET / -> routes.get # @statsd.key some.custom.key GET /foo/bar -> routes.some.custom.keyIn addition, the following stats overall stats are recorded:@routes.combined.200@ - The count of each response by status code. @routes.combined.success@ - The count of each successful response. This includes 4xx status codes, since the server still handled them successfully. @routes.combined.error@ - The count of error responses. This is any response with a 5xx status code. @routes.combined.time@ - The time for all requests. @routes.combined.handlerNotFound@ - The count and time of all requests for which no handler was found to handle them.Note that the time a request takes is defined as the amount of time from when the request headers are first received, through to when the response header is generated. It includes the time it takes to receive the body of the request, but does not include the time it takes to send the body of the response.Websocket requests are not reported.
The easiest way to use the filter in Scala applications is to use the WithFilters helper in your Global object, like this:
object Global extends WithFilters(new play.modules.statsd.api.StatsdFilter()) {
…
}
Just return the StatsdFilter class from the filters method of your Global object:
public class Global extends GlobalSettings {
public Class[] filters() {
return new Class[] {play.modules.statsd.StatsdFilter.class};
}
}