Scala - 尝试使用异常日志记录

SRo*_*mes 23 logging scala exception

Scala Try 是非常有用的.我想使用该模式,但记录所有异常.我怎样才能做到这一点?

sjr*_*jrd 30

定义以下帮助器:

import scala.util.{Try, Failure}

def LogTry[A](computation: => A): Try[A] = {
  Try(computation) recoverWith {
    case e: Throwable =>
      log(e)
      Failure(e)
  }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以像使用它一样使用它Try,但是将记录任何异常log(e).


Xav*_*hot 8

从 开始Scala 2.13,链接操作tap可用于在返回原始值的同时对任何值应用副作用(在本例中为一些日志记录):

import util.chaining._

val x = Try("aa".toInt).tap(_.failed.foreach(println))
// java.lang.NumberFormatException: For input string: "aa"
// x: Try[Int] = Failure(java.lang.NumberFormatException: For input string: "aa")
Run Code Online (Sandbox Code Playgroud)

或者等效的模式匹配版本:

val x = Try("aa".toInt).tap { case Failure(e) => println(e) case _ => }
// java.lang.NumberFormatException: For input string: "aa"
// x: Try[Int] = Failure(java.lang.NumberFormatException: For input string: "aa")
Run Code Online (Sandbox Code Playgroud)

链接tap操作对值(在本例中为 a )施加副作用(println在本例中为或某些日志记录) ,同时返回所应用的Try原始未修改值(在):tapTry

def tap[U](f: (A) => U): A


gor*_*ral 5

您可以使用隐式类进一步调整它

def someMethod[A](f: => A): Try[A] = Try(f)

implicit class LogTry[A](res: Try[A]) {
  def log() = res match {
    case Success(s) => println("Success :) " + s); res
    case Failure(f) => println("Failure :( " + f); res
  }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以像这样调用someMethod和调用结果调用log:

scala> someMethod(1/0).log
Failure :( java.lang.ArithmeticException: / by zero
Run Code Online (Sandbox Code Playgroud)

scala> someMethod(1).log
Success :) 1
Run Code Online (Sandbox Code Playgroud)

当然println,隐式类中的方法可以替换为您想要的任何日志记录.