Skip to content

Instantly share code, notes, and snippets.

@scullxbones
Created October 2, 2013 01:57
Show Gist options
  • Select an option

  • Save scullxbones/6788038 to your computer and use it in GitHub Desktop.

Select an option

Save scullxbones/6788038 to your computer and use it in GitHub Desktop.
Another take on fine-grained metrics
object SuppliesMetricInformation {
import akka.actor.Actor.Receive
trait MetricInformation[A] {
val clazz: Class[_]
val name: String
val builder: InstrumentedBuilder
def counter: Counter = builder.metrics.counter(MetricBuilder.metricName(clazz, Seq(name)))
def supplyCounter(message: Any)(implicit man: Manifest[A]) = {
if (message.getClass.isAssignableFrom(man.runtimeClass)) Some(counter)
else None
}
}
def wrapReceive(receive: Receive)(withMetrics: Seq[MetricInformation[_]]) = new Receive {
def apply(message: Any) = {
withMetrics.flatMap(i => i.supplyCounter(message)).map( _.inc(1) ) // Increments all matching counters
receive(message)
}
def isDefinedAt(message: Any) = receive.isDefinedAt(message)
}
}
// Protocol
sealed trait Message
case class Get(id: Long) extends Message
case class Put(id: Long, value: String) extends Message
// Domain service
case class Database(store:Map[Long,String] = Map()) {
def get(id: Long) = store.get(id)
def put(id: Long, value: String) = new Database( store + (id -> value) )
}
// Metrics-Scala registry supplier
trait Instrumented extends InstrumentedBuilder {
val metricRegistry = new com.codahale.metrics.MetricRegistry()
}
// Actor w/ domain logic
class DatabaseActor(var db: Database) extends Actor with Instrumented {
def receive() = {
case Get(id) => sender ! db.get(id)
case Put(id, value) => db = db.put(id,value)
}
}
// Counter selector
case class SuppliesMetricInformationForGet(clazz: Class[_], builder: InstrumentedBuilder)
extends SuppliesMetricInformation.MetricInformation[Get] {
val name = "gets"
}
// Counter selector
case class SuppliesMetricInformationForPut(clazz: Class[_], builder: InstrumentedBuilder)
extends SuppliesMetricInformation.MetricInformation[Put] {
val name = "puts"
}
class CountedDatabaseActor(db: Database) extends DatabaseActor(db) {
val wrapped = SuppliesMetricInformation.wrapReceive(super.receive)(
List(SuppliesMetricInformationForGet(getClass,this), SuppliesMetricInformationForPut(getClass,this))
)
override def receive = wrapped
}
@erikvanoosten
Copy link

Looks good! Not sure if I would want something elaborate like this in the library yet. Perhaps we should just put it in the docs as an example.

If you do, please rename clazz to owner, or better yet: metricOwner.

What would be even more interesting is a way to count messages per type without having to set up the MetricInformation subclasses. WDYT?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment