
com.wordnik.util.perf.Profile.scala Maven / Gradle / Ivy
The newest version!
package com.wordnik.util.perf
import akka.dispatch.Future
import com.yammer.metrics.Metrics
import java.util.concurrent.TimeUnit
import util.control.Exception.allCatch
import com.yammer.metrics.core.MetricName
/**
* A utility for fine-grained code instrumentation.
* Simply pass a function to the Profile class with a name and the Profiler will keep track of performance statistics.
* It registers timings and has support for akka's futures
*
*
* // For application level metrics
* Profile.global("delete user")) {
* // do something
* }
*
* // or for instance level metrics
* val profiler = Profile[UserDao]
* profiler("delete user") {
* // do something
* }
*
*
*/
object Profile {
private class Global
/**
* Provides a global profiler to group application level metrics together
* @return a global profiler instance
*/
lazy val global: Profiler = apply[Global]
/** A metrics collector */
trait Profiler {
/**
* Profile the provided block of code
* @param name The name for this metric
* @param scope An optional scope for this metric
* @param thunk The block of code to profile
* @tparam T The result type of the code block
* @return The result of the code block
*/
def apply[T](name: String, scope: String = null)(thunk: ⇒ T): T
/**
* Profile the provided block of code
* @param name The name for this metric
* @param scope An optional scope for this metric
* @param thunk The block of code to profile
* @tparam T The result type of the code block
* @return The result of the code block
*/
def profile[T](name: String, scope: String = null)(thunk: ⇒ T): T =
apply(name, scope)(thunk)
def clear(name: String, scope: String = null)
}
private class DefaultProfiler(group: String, `type`: String) extends Profiler {
def apply[T](name: String, scope: String = null)(thunk: ⇒ T): T = {
val timer = Metrics.newTimer(new MetricName(group, `type`, name, scope), TimeUnit.MILLISECONDS, TimeUnit.MINUTES)
val p = timer.time()
var isSync = true
allCatch.andFinally( if (isSync) p.stop() ) {
val r = thunk
r match {
case f: Future[_] =>
isSync = false
f onComplete { case _ => p.stop() }
case _ =>
}
r
}
}
def clear(name: String, scope: String = null) {
val timer = Metrics.newTimer(new MetricName(group, `type`, name, scope), TimeUnit.MILLISECONDS, TimeUnit.MINUTES)
timer.clear()
}
}
/**
* Create a timer configured for getting rates in milliseconds and averages in minutes
*
* @param mf type information manifest
* @tparam S The class this profiler applies to
* @return a profiler which can be used sync or async
*/
def apply[S](implicit mf: Manifest[S]): Profiler =
new DefaultProfiler(packageName(mf.erasure), mf.erasure.getSimpleName.replaceAll("\\$$", ""))
/**
* Create a timer configured for getting rates in milliseconds and averages in minutes
*
* @param `type` the subgroup of this timer
* @param group the top level group of this timer
* @return a Profiler which can be used sync or async
*/
def apply(`type`: String, group: String = packageName(getClass)): Profiler = new DefaultProfiler(group, `type`)
private[this] def packageName(cl: Class[_]) = if (cl.getPackage == null) "reverb" else cl.getPackage.getName
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy