Quel est un bon moyen de vous connecter à une application Scala?)? Quelque chose qui est cohérent avec la philosophie de la langue, n'encombre pas le code, et nécessite peu de maintenance et est discret. Voici une liste d'exigences de base :
Je sais que je peux utiliser les solutions de journalisation Java existantes), mais elles échouent sur au moins deux des solutions ci-dessus, à savoir l'encombrement et la configuration.
Merci pour vos réponses.
La plupart des bibliothèques de journalisation de Scala ont été intégrées à un (= $) cadre de journalisation Java (slf4j, log4j, etc.)), mais depuis mars 2015, les bibliothèques de journaux restantes sont toutes slf4j. Ces bibliothèques de journaux fournissent une sorte de log
objet auquel vous pouvez appeler info(...)
, debug(...)
, etc. Je ne suis pas un grand fan de slf4j, mais il semble maintenant que ce soit la journalisation prédominante Voici la description de SLF4J :
La façade de journalisation simple pour Java ou (SLF4J) sert de façade simple ou d’abstraction pour divers structure de journalisation souhaitée au moment du déploiement.
La possibilité de modifier la bibliothèque de journaux sous-jacente au moment du déploiement confère une caractéristique unique à la famille des enregistreurs slf4j, que vous devez connaître:
Dans un grand projet, il pourrait être pratique de pouvoir contrôler le comportement de journalisation des dépendances transitives si tout le monde utilisait slf4j.
Scala Logging est écrit par Heiko Seeberger comme successeur de son slf4s . Il utilise la macro pour développer les appels dans if si pour éviter les appels de journal potentiellement coûteux.
La journalisation Scala est une bibliothèque de journalisation commode et performante qui encapsule des bibliothèques de journalisation telles que SLF4J et éventuellement d’autres.
With Scala 2.10+ Envisagez ScalaLogging by Typesafe. Utilise des macros pour fournir une API très propre.
https://github.com/typesafehub/scala-logging
Citant de leur wiki:
Heureusement, des macros Scala peuvent être utilisées pour nous simplifier la vie: ScalaLogging offre à la classe
Logger
des méthodes de journalisation allégées qui seront étendues à l'idiome précédent. Tout ce que nous avons à écrire est:
logger.debug(s"Some ${expensiveExpression} message!")
Une fois la macro appliquée, le code aura été transformé en idiome décrit ci-dessus.
De plus, ScalaLogging offre le trait Logging
qui fournit commodément une instance de Logger
initialisée avec le nom de la classe mélangée dans:
import com.typesafe.scalalogging.slf4j.LazyLogging
class MyClass extends LazyLogging {
logger.debug("This is very convenient ;-)")
}
Utiliser slf4j et un wrapper est agréable, mais l'utilisation de son interpolation intégrée s'interrompt lorsque vous avez plus de deux valeurs à interpoler, car vous devez alors créer un tableau de valeurs à interpoler.
Une solution similaire = Scala) consiste à utiliser un thunk ou un cluster pour retarder la concaténation du message d'erreur. Un bon exemple en est le journal de Lift.
Qui ressemble à ceci:
class Log4JLogger(val logger: Logger) extends LiftLogger {
override def trace(msg: => AnyRef) = if (isTraceEnabled) logger.trace(msg)
}
Notez que msg est un appel par nom et qu'il ne sera pas évalué à moins que isTraceEnabled soit à true, il est donc inutile de générer une chaîne de message Nice. Cela fonctionne autour du mécanisme d'interpolation de slf4j qui nécessite l'analyse du message d'erreur. Avec ce modèle, vous pouvez interpoler un nombre quelconque de valeurs dans le message d'erreur.
Si vous avez un trait distinct qui mélange ce Log4JLogger à votre classe, alors vous pouvez faire
trace("The foobar from " + a + " doesn't match the foobar from " +
b + " and you should reset the baz from " + c")
au lieu de
info("The foobar from {0} doesn't match the foobar from {1} and you should reset the baz from {c},
Array(a, b, c))
En fait, j'ai suivi la recommandation d'Eugene et l'ai essayée et découvert qu'elle avait une configuration maladroite et qu'elle était sujette à des bogues non corrigés (comme celui-ci ). Il ne semble pas être bien entretenu et il ne supporte pas Scala 2.10 .
-Dorg.slf4j.simplelogger.defaultlog=trace
À la commande d'exécution ou au code fixe dans votre script: System.setProperty("org.slf4j.simplelogger.defaultlog", "trace")
. Pas besoin de gérer les fichiers de configuration Trashy!Run/Debug Configurations
Et ajoutez -Dorg.slf4j.simplelogger.defaultlog=trace
À VM options
.Voici ce que vous devez exécuter avec 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>
Voici comment j'ai obtenu Scala Logging pour moi:
Mettez ceci dans votre build.sbt
:
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.7.2",
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3"
Ensuite, après avoir effectué un sbt update
, Ceci affiche un message de journal convivial:
import com.typesafe.scalalogging._
object MyApp extends App with LazyLogging {
logger.info("Hello there")
}
Si vous utilisez Play, vous pouvez bien sûr simplement import play.api.Logger
Pour écrire les messages du journal: Logger.debug("Hi")
.
Voir le docs pour plus d'informations.
J'ai tiré un peu de travail du trait Logging
de scalax
et créé un trait intégrant également un MessageFormat-based
bibliothèque.
Alors ça ressemble un peu à ça:
class Foo extends Loggable {
info( "Dude, I'm an {0} with {1,number,#}", "Log message", 1234 )
}
Nous aimons l'approche jusqu'à présent.
La mise en oeuvre:
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))
}
J'utilise SLF4J + Logback classic et l'applique comme ceci:
trait Logging {
lazy val logger = LoggerFactory.getLogger(getClass)
implicit def logging2Logger(anything: Logging): Logger = anything.logger
}
Ensuite, vous pourrez l’utiliser selon votre style:
class X with Logging {
logger.debug("foo")
debug("bar")
}
mais cette approche utilise bien sûr une instance de consignateur par instance de classe.
Vous devriez jeter un coup d'œil à la bibliothèque scalax: http://scalax.scalaforge.org/ Dans cette bibliothèque, il existe un trait de journalisation, utilisant sl4j en tant que backend. En utilisant ce trait, vous pouvez vous connecter assez facilement (utilisez simplement le champ logger de la classe héritant du trait).
Writer
, Monoid
et une implémentation de Monad
.
Je n'ai pas encore essayé, mais Configgy semble prometteur pour la configuration et la journalisation:
Formulaires rapides et faciles.
Scala 2.10 et plus vieux:
import com.typesafe.scalalogging.slf4j.Logger
import org.slf4j.LoggerFactory
val logger = Logger(LoggerFactory.getLogger("TheLoggerName"))
logger.debug("Useful message....")
Et build.sbt:
libraryDependencies += "com.typesafe" %% "scalalogging-slf4j" % "1.1.0"
Scala 2.11+ et plus récent:
import import com.typesafe.scalalogging.Logger
import org.slf4j.LoggerFactory
val logger = Logger(LoggerFactory.getLogger("TheLoggerName"))
logger.debug("Useful message....")
Et build.sbt:
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.1.0"
Je trouve très pratique d’utiliser une sorte de Java enregistreur, sl4j par exemple, avec un simple scala wrapper, qui m'apporte une telle syntaxe
val #! = new Logger(..) // somewhere deep in dsl.logging.
object User with dsl.logging {
#! ! "info message"
#! dbg "debug message"
#! trace "var a=true"
}
À mon avis, très utile mélange de Java infrastructures de journalisation éprouvées et de la syntaxe sophistiquée de scala.
Après avoir utilisé slf4s et logula pendant un certain temps, j’ai écrit loglady
, un trait de journalisation simple enveloppant slf4j.
Il offre une API similaire à celle de la bibliothèque de journalisation de Python, ce qui rend les cas courants (chaîne de base, formatage simple) triviaux et évite le formatage passe-partout.