This is what I'm trying right now but it only prints "hey" and not metrics. I don't want to add metric related stuff in the main function.
import java.util.Date
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration.Duration
class A {
def fellow(): Task[Unit] = {
val result = Task {
println("hey")
Thread.sleep(1000)
}
result
}
}
trait AA extends A {
override def fellow(): Task[Unit] = {
println("AA")
val result = super.fellow()
val start = new Date()
result.foreach(e => {
println("AA", new Date().getTime - start.getTime)
})
result
}
}
val a = new A with AA
val res: Task[Unit] = a.fellow()
Await.result(res.runAsync, Duration.Inf)
You can describe a function such as this:
def measure[A](task: Task[A], logMillis: Long => Task[Unit]): Task[A] =
Task.deferAction { sc =>
val start = sc.clockMonotonic(TimeUnit.MILLISECONDS)
val stopTimer = Task.suspend {
val end = sc.clockMonotonic(TimeUnit.MILLISECONDS)
logMillis(end - start)
}
task.redeemWith(
a => stopTimer.map(_ => a)
e => stopTimer.flatMap(_ => Task.raiseError(e))
)
}
Some piece of advice:
Task
values should be pure, along with the functions returning Task
s — functions that trigger side effects and return Task
as results are broken
Task
is not a 1:1 replacement for Future
; when describing a Task
, all side effects should be suspended (wrapped) in Task
foreach
triggers the Task
's evaluation and that's not good, because it triggers the side effects; I was thinking of deprecating and removing it, since its presence is temptingnew Date()
, you need a monotonic clock for that and on top of the JVM that's System.nanoTime
, which can be accessed via Monix's Scheduler
by clockMonotonic
, as exemplified above, the Scheduler
being given to you via deferAction
Thread.sleep
, do Task.sleep
and all Await.result
calls are problematic, unless they are in main
or in some other place where dealing with asynchrony is not possibleHope this helps.
Cheers,