web-dev-qa-db-ja.com

ログインScala

Scalaアプリケーションにログインする良い方法は何ですか?言語哲学と一致し、コードを乱雑にせず、保守が少なくて邪魔にならないもの。基本的な要件リストは次のとおりです。

  • シンプルな
  • コードを乱雑にしません。 Scalaは簡潔さの点で優れています。コードの半分をステートメントのロギングにしたくない
  • ログのフォーマットは、エンタープライズログおよび監視ソフトウェアの残りに合わせて変更できます。
  • ロギングのレベルをサポートします(すなわち、デバッグ、トレース、エラー)
  • ディスクと他の宛先(つまり、ソケット、コンソールなど)にログを記録できます
  • 最小構成(ある場合)
  • コンテナー(つまり、Webサーバー)で動作します
  • (オプションですが、持っておくといい)は、言語の一部として、またはMavenアーティファクトとして提供されるため、使用するためにビルドをハックする必要はありません。

既存のJavaロギングソリューションを使用できることは知っていますが、上記の少なくとも2つ、つまり混乱と構成では失敗します。

返信いただきありがとうございます。

160
George

slf4jラッパー

Scalaのロギングライブラリのほとんどは、Javaロギングフレームワーク(slf4j、log4jなど)のラッパーでしたが、2015年3月現在、残っているログライブラリはすべてslf4jです。これらのログライブラリは、info(...)debug(...)などを呼び出すことができるlogオブジェクトを提供します。私はslf4jの大ファンではありませんが、今では支配的になっているようですロギングフレームワーク。 SLF4J の説明は次のとおりです。

Javaまたは(SLF4J)のSimple Logging Facadeは、さまざまなロギングフレームワークの単純なファサードまたは抽象化として機能します。 Java.util.logging、log4j、およびlogback。エンドユーザーがデプロイメント時に目的のロギングフレームワークをプラグインできるようにします。

展開時に基礎となるログライブラリを変更する機能は、ロガーのslf4jファミリ全体に固有の特性をもたらします。

  1. classpath as configurationアプローチ。 slf4jが使用しているロギングライブラリの基礎を知る方法は、クラスを何らかの名前でロードすることです。クラスローダーをカスタマイズしたときに、slf4jがロガーを認識しないという問題がありました。
  2. simple facadeは共通分母になろうとするため、実際のログ呼び出しのみに制限されます。言い換えれば、コードを介して構成を行うことはできません。

大規模なプロジェクトでは、全員がslf4jを使用した場合に、推移的な依存関係のログ記録動作を制御できると実際に便利です。

Scalaロギング

Scala Logging は、Heiko Seebergerが slf4s の後継として書いています。マクロを使用して呼び出しをif式に展開し、潜在的に負荷の高いログ呼び出しを回避します。

Scala Loggingは、SLF4Jなどのロギングライブラリをラップする便利でパフォーマンスの高いロギングライブラリです。

履歴ロガー

  • Logula 、Coda Haleが作成したLog4Jラッパー。昔はこれが好きだったが、今では放棄されている。
  • configgy 、Scalaの初期の頃に人気があったJava.util.loggingラッパー。放棄されました。
117
Eugene Yokota

Scala 2.10+では、タイプセーフによるScalaLoggingを検討してください。マクロを使用して非常にクリーンなAPIを提供します

https://github.com/typesafehub/scala-logging

Wikiから引用:

幸いなことに、Scalaマクロを使用すると、生活が楽になります。ScalaLoggingは、上記のイディオムに拡張される軽量のロギングメソッドを備えたLoggerクラスを提供します。したがって、私たちが書かなければならないことは次のとおりです。

logger.debug(s"Some ${expensiveExpression} message!")

マクロが適用された後、コードは上記のイディオムに変換されます。

さらに、ScalaLoggingはLogging特性を提供します。これは、クラスの名前を次のように混合して初期化されたLoggerインスタンスを便利に提供します。

import com.typesafe.scalalogging.slf4j.LazyLogging

class MyClass extends LazyLogging {
  logger.debug("This is very convenient ;-)")
}
62
fracca

Slf4jとラッパーを使用するのはいいですが、補間する値の配列を作成する必要があるため、補間する値が3つ以上ある場合、組み込みの補間の使用は失敗します。

さらにScalaのような解決策は、サンクまたはクラスターを使用してエラーメッセージの連結を遅らせることです。これの良い例は、Liftのロガーです

Log.scalaSlf4jLog.scala

これは次のようになります。

class Log4JLogger(val logger: Logger) extends LiftLogger {
  override def trace(msg: => AnyRef) = if (isTraceEnabled) logger.trace(msg)
}

Msgは名前による呼び出しであり、isTraceEnabledがtrueでない限り評価されないため、Niceメッセージ文字列の生成に費用はかかりません。これは、エラーメッセージの解析を必要とするslf4jの補間メカニズムを回避します。このモデルを使用すると、任意の数の値をエラーメッセージに挿入できます。

このLog4JLoggerをクラスにミックスする別の特性がある場合は、次のことができます。

trace("The foobar from " + a + " doesn't match the foobar from " +
      b + " and you should reset the baz from " + c")

の代わりに

info("The foobar from {0} doesn't match the foobar from {1} and you should reset the baz from {c},
     Array(a, b, c))
14
Blair Zajac

Logulaを使用しないでください

私は実際にEugeneの推奨に従い、それを試してみましたが、それは不器用な構成を持ち、修正されないバグにさらされていることがわかりました( this one など)。よく維持されているようには見えず、Scala 2.10をサポートしていません。

Slf4s + slf4j-simpleを使用する

主な利点:

  • 最新のScala 2.10をサポート(これまではM7です)
  • 構成は多目的ですが、これ以上簡単にすることはできません。 システムプロパティ を使用して実行されます。実行コマンドに-Dorg.slf4j.simplelogger.defaultlog=traceのようなものを追加するか、スクリプトのハードコードSystem.setProperty("org.slf4j.simplelogger.defaultlog", "trace")のいずれかを設定できます。くだらない設定ファイルを管理する必要はありません!
  • IDEにうまく適合します。たとえば、IDEAの特定の実行構成でログレベルを「トレース」に設定するには、Run/Debug Configurationsに移動して、-Dorg.slf4j.simplelogger.defaultlog=traceVM optionsに追加します。
  • 簡単なセットアップ:この回答の下部から依存関係をドロップするだけです

Mavenで実行するために必要なものは次のとおりです。

<dependency>
  <groupId>com.weiglewilczek.slf4s</groupId>
  <artifactId>slf4s_2.9.1</artifactId>
  <version>1.0.7</version>
</dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-simple</artifactId>
  <version>1.6.6</version>
</dependency>
12
Nikita Volkov

これが私が得た方法です Scala Logging 私のために働いています:

これをbuild.sbtに入れてください:

libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.7.2",
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3"

次に、sbt updateを実行すると、わかりやすいログメッセージが出力されます。

import com.typesafe.scalalogging._
object MyApp extends App with LazyLogging {
  logger.info("Hello there")
}

Playを使用している場合、もちろんimport play.api.Loggerでログメッセージを書き込むことができます:Logger.debug("Hi")

詳細については、 docs を参照してください。

11
Matthias Braun

Loggingscalax特性から作業を少し引き出し、MessageFormat-basedライブラリも統合する特性を作成しました。

次に、次のようなものがあります:

class Foo extends Loggable {
    info( "Dude, I'm an {0} with {1,number,#}", "Log message", 1234 )
}

これまでのアプローチが気に入っています。

実装:

trait Loggable {

    val logger:Logger = Logging.getLogger(this)

    def checkFormat(msg:String, refs:Seq[Any]):String =
        if (refs.size > 0) msgfmtSeq(msg, refs) else msg 

    def trace(msg:String, refs:Any*) = logger trace checkFormat(msg, refs)

    def trace(t:Throwable, msg:String, refs:Any*) = logger trace (checkFormat(msg, refs), t)

    def info(msg:String, refs:Any*) = logger info checkFormat(msg, refs)

    def info(t:Throwable, msg:String, refs:Any*) = logger info (checkFormat(msg, refs), t)

    def warn(msg:String, refs:Any*) = logger warn checkFormat(msg, refs)

    def warn(t:Throwable, msg:String, refs:Any*) = logger warn (checkFormat(msg, refs), t)

    def critical(msg:String, refs:Any*) = logger error checkFormat(msg, refs)

    def critical(t:Throwable, msg:String, refs:Any*) = logger error (checkFormat(msg, refs), t)

}

/**
 * Note: implementation taken from scalax.logging API
 */
object Logging {  

    def loggerNameForClass(className: String) = {  
        if (className endsWith "$") className.substring(0, className.length - 1)  
        else className  
    }  

    def getLogger(logging: AnyRef) = LoggerFactory.getLogger(loggerNameForClass(logging.getClass.getName))  
}
7
Tristan Juricek

SLF4J + Logback classicを使用して、次のように適用します。

trait Logging {
  lazy val logger = LoggerFactory.getLogger(getClass)

  implicit def logging2Logger(anything: Logging): Logger = anything.logger
}

次に、あなたのスタイルに合った方を使用できます:

class X with Logging {
    logger.debug("foo")
    debug("bar")
}

ただし、このアプローチでは、クラスインスタンスごとにロガーインスタンスを使用します。

6
Kristof Jozsa

Scalaxライブラリをご覧ください。 http://scalax.scalaforge.org/ このライブラリには、sl4jをバックエンドとして使用するLogging特性があります。この特性を使用すると、非常に簡単にログを記録できます(特性を継承するクラスのロガーフィールドを使用するだけです)。

4
Gilles

WriterMonoid、およびMonad実装。

4
Tony Morris

まだ試していませんが、Configgyは設定とロギングの両方について有望に見えます:

http://github.com/robey/configgy/tree/master

3
dberesford

すばやく簡単なフォーム。

Scala 2.10以前:

import com.typesafe.scalalogging.slf4j.Logger
import org.slf4j.LoggerFactory
val logger = Logger(LoggerFactory.getLogger("TheLoggerName"))
logger.debug("Useful message....")

そして、build.sbt:

libraryDependencies += "com.typesafe" %% "scalalogging-slf4j" % "1.1.0"

Scala 2.11以降:

import import com.typesafe.scalalogging.Logger
import org.slf4j.LoggerFactory
val logger = Logger(LoggerFactory.getLogger("TheLoggerName"))
logger.debug("Useful message....")

そして、build.sbt:

libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.1.0"
2
xgMz

何らかの種類のJavaロガー、たとえばsl4jを使用して、単純なscalaラッパーを使用すると非常に便利です。

val #! = new Logger(..) // somewhere deep in dsl.logging.

object User with dsl.logging {

  #! ! "info message"
  #! dbg "debug message"
  #! trace "var a=true"

}

私の意見では、Java実証済みのロギングフレームワークとscalaの派手な構文の非常に便利なミックスインです。

2
Alex Povar

Slf4sとlogulaをしばらく使用した後、私はlogladyを作成しました。これはslf4jをラップする簡単なログ特性です。

Pythonのロギングライブラリと同様のAPIを提供します。これにより、一般的なケース(基本的な文字列、単純な書式設定)が簡単になり、定型的な書式設定が回避されます。

http://github.com/dln/loglady/

2
dln