Scala:如果代码块的执行时间超过一定时间发出警告?
Scala: Warn if block of code is executing for more than certain duration?
我想做这样的事情:
def warnEvery[A](duration: Duration)(block: => A): A = {
val start = DateTime.now
val f = Future(f)
while(!f.isComplete) {
Thread.sleep(duration)
if (!f.isComplete) {
// Trigger a stack trace warning message
Log.warn(s"Block is running for ${DateTime.now() - start}", new Throwable())
}
}
f.result
}
目标是这样使用上面的助手:
warnEvery(1 minute) {
// slow operation
}
在我的日志中,我想查看一段缓慢代码块的堆栈跟踪。
在 Scala 中完成此任务的最佳方法是什么。指向现有库的指针也很好。
您可以使用 Akka 的调度程序来安排检查未来是否完成的任务。这样,就不需要 Thread.sleep
,它会阻塞线程直到任务完成。
def warnEvery[A](duration: FiniteDuration)(block: => A): Future[A] = {
val start = DateTime.now
val f = Future(f)
def warn {
if (!f.isCompleted) {
Log.warn(s"Block is running for ${DateTime.now() - start}")
Akka.system.scheduler.scheduleOnce(duration)(warn)
}
}
Akka.system.scheduler.scheduleOnce(duration)(warn)
f
}
小毛病:从技术上讲,此解决方案衡量的是创造未来与现在之间的时间。如果创建未来时执行上下文中的所有线程都很忙,则块的执行可能会稍后开始。因此,更好的日志消息是 "Block has been queued for execution .... seconds ago and has not finished running yet."
只是 运行 块,最后检查它是否已经 运行ning 太久
import org.joda.time.{Interval, DateTime}
import scala.concurrent.duration.Duration
def warnEvery[A](duration: Duration)(block: => A): A = {
val start = DateTime.now
try {
block
}
finally {
val millis = new Interval(start, DateTime.now).toDurationMillis
if (millis > duration.toMillis) {
// Log here ...
}
}
}
编辑:抱歉,没有正确理解您的问题。然后你可以使用计时器来完成-
import java.util.{TimerTask, Timer}
import org.joda.time.{Interval, DateTime}
import scala.concurrent.duration.Duration
def warnEvery[A](duration: Duration)(block: => A): A = {
val task = new TimerTask() {
@Override
def run() {
// Log here
}
}
val timer = new Timer()
val delay = duration.toMillis
val intevalPeriod = duration.toMillis
timer.scheduleAtFixedRate(task, delay, intevalPeriod)
try {
block
}
finally {
timer.cancel()
}
}
我想做这样的事情:
def warnEvery[A](duration: Duration)(block: => A): A = {
val start = DateTime.now
val f = Future(f)
while(!f.isComplete) {
Thread.sleep(duration)
if (!f.isComplete) {
// Trigger a stack trace warning message
Log.warn(s"Block is running for ${DateTime.now() - start}", new Throwable())
}
}
f.result
}
目标是这样使用上面的助手:
warnEvery(1 minute) {
// slow operation
}
在我的日志中,我想查看一段缓慢代码块的堆栈跟踪。
在 Scala 中完成此任务的最佳方法是什么。指向现有库的指针也很好。
您可以使用 Akka 的调度程序来安排检查未来是否完成的任务。这样,就不需要 Thread.sleep
,它会阻塞线程直到任务完成。
def warnEvery[A](duration: FiniteDuration)(block: => A): Future[A] = {
val start = DateTime.now
val f = Future(f)
def warn {
if (!f.isCompleted) {
Log.warn(s"Block is running for ${DateTime.now() - start}")
Akka.system.scheduler.scheduleOnce(duration)(warn)
}
}
Akka.system.scheduler.scheduleOnce(duration)(warn)
f
}
小毛病:从技术上讲,此解决方案衡量的是创造未来与现在之间的时间。如果创建未来时执行上下文中的所有线程都很忙,则块的执行可能会稍后开始。因此,更好的日志消息是 "Block has been queued for execution .... seconds ago and has not finished running yet."
只是 运行 块,最后检查它是否已经 运行ning 太久
import org.joda.time.{Interval, DateTime}
import scala.concurrent.duration.Duration
def warnEvery[A](duration: Duration)(block: => A): A = {
val start = DateTime.now
try {
block
}
finally {
val millis = new Interval(start, DateTime.now).toDurationMillis
if (millis > duration.toMillis) {
// Log here ...
}
}
}
编辑:抱歉,没有正确理解您的问题。然后你可以使用计时器来完成-
import java.util.{TimerTask, Timer}
import org.joda.time.{Interval, DateTime}
import scala.concurrent.duration.Duration
def warnEvery[A](duration: Duration)(block: => A): A = {
val task = new TimerTask() {
@Override
def run() {
// Log here
}
}
val timer = new Timer()
val delay = duration.toMillis
val intevalPeriod = duration.toMillis
timer.scheduleAtFixedRate(task, delay, intevalPeriod)
try {
block
}
finally {
timer.cancel()
}
}