Last active
July 13, 2017 13:22
-
-
Save SystemFw/06d558791b35c807b55153e7b0343f36 to your computer and use it in GitHub Desktop.
Logging failures on Task
This file contains 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
import scalaz.{-\/, \/-} | |
import scalaz.concurrent.Task | |
import scalaz.syntax.monad._ | |
/* | |
* Easily adaptable to Monix, cats, fs2, cats-effect and so on | |
*/ | |
object Logger { | |
sealed trait Level | |
object Level { | |
case object Error extends Level | |
case object Info extends Level | |
case object Warn extends Level | |
case object Debug extends Level | |
} | |
implicit class LogFailures[A](t: Task[A]) { | |
/** | |
* If the input task is a failure, it logs the resulting error | |
* and rethrows it within another failed task. | |
* | |
* If the input task is a success, does nothing. | |
* | |
* @param reporter A partial function that can return a different | |
* error and level for each error. If an error is | |
* not handled by `reporter`, its message (as | |
* given by `Throwable.getMessage`) is logged, at | |
* Debug Level | |
* | |
* @return A `Task[A]` that logs exceptions. Note that | |
* `logFailures`, as evident from its type, doesn't | |
* change the status of the task: a successful task | |
* remains successful, and a failed task remains failed. | |
*/ | |
def logFailures( | |
reporter: PartialFunction[Throwable, (Level, String)]): Task[A] = { | |
def logMsgFor(e: Throwable): Task[Unit] = | |
reporter.lift(e) map { | |
case (level, msg) => log(msg, level) | |
} getOrElse { | |
log(e.getMessage, Level.Debug) | |
} | |
t.attempt flatMap { | |
case -\/(e) => logMsgFor(e) >> Task.fail(e) | |
case \/-(a) => Task.now(a) | |
} | |
} | |
} | |
private def log(msg: String, level: Level): Task[Unit] = Task.delay { | |
level match { | |
case Level.Error => logger.error(msg) | |
case Level.Info => logger.info(msg) | |
case Level.Warn => logger.warn(msg) | |
case Level.Debug => logger.debug(msg) | |
} | |
} | |
private val logger = journal.Logger[this.type] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment