Каков наилучший способ обернуть задачу моникса временем начала и окончания печати?

Это то, что я пытаюсь сейчас, но он печатает только "эй", а не метрики. Я не хочу добавлять метрическую информацию в основную функцию.

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)

2 ответа

Решение

Вы можете описать такую ​​функцию:

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))
    )
  }

Несколько советов:

  1. Task значения должны быть чистыми, наряду с функциями, возвращающими Tasks - функции, которые запускают побочные эффекты и возвращают Task как результаты сломаны
    • Task не является заменой 1:1 для Future; при описании Task, все побочные эффекты должны быть приостановлены Task
    • foreach вызывает Taskоценка и это не хорошо, потому что это вызывает побочные эффекты; Я думал об устаревании и удалении его, так как его присутствие заманчиво
  2. прекратите использовать наследование признаков и просто используйте простые функции - если вы не глубоко понимаете ООП и подтипы, лучше по возможности избегать их; и если вы в шаблоне Cake, прекратите это делать и, возможно, присоединитесь к группе поддержки
  3. никогда не измеряйте продолжительность времени с помощью new Date()вам нужны монотонные часы для этого и на вершине JVM это System.nanoTime, который может быть доступен через Monix's Scheduler от clockMonotonicкак показано выше, Scheduler дается вам через deferAction
  4. прекратить блокировать потоки, потому что это подвержено ошибкам - вместо того, чтобы делать Thread.sleep, делать Task.sleep и все Await.result вызовы проблематичны, если они не находятся в main или в каком-то другом месте, где невозможно работать с асинхронностью

Надеюсь это поможет.

Ура,

Как упоминалось @Pierre, последняя версия Monix Task имеет Task.timed, ты можешь сделать

      timed <- task.timed
(duration, t) = timed
Другие вопросы по тегам