Created
October 2, 2013 01:57
-
-
Save scullxbones/6788038 to your computer and use it in GitHub Desktop.
Another take on fine-grained metrics
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
clazztoowner, 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?