Вход в Scala



Что такое хороший способ сделать вход в приложение Scala? Что-то, что согласуется с философией языка, не загромождает код, а является низким уровнем обслуживания и ненавязчивым. Вот список основных требований:




  • простой

  • не загромождать код. Scala отлично подходит для своей краткости. Я не хочу, чтобы половина моего кода регистрировала операторы

  • формат журнала может быть изменен, чтобы соответствовать остальной части моих корпоративных журналов и мониторинга программное обеспечение

  • поддерживает уровни ведения журнала (т. е. отладки, трассировки, ошибки)

  • может войти на диск, а также в другие места назначения (т. е. сокет, консоль и т. д.)

  • минимальная конфигурация, если какой-либо

  • строительство в контейнерах (т. е. веб-сервер)

  • (необязательно, но приятно иметь) поставляется либо как часть языка, либо как артефакт maven, поэтому мне не нужно взломать мои сборки, чтобы использовать его


Я знаю, что могу использовать существующие решения для ведения журнала Java, но они терпят неудачу по крайней мере на двух из вышеперечисленных, а именно беспорядок и конфигурация.



Спасибо за ваши ответы.

578   13  

13 ответов:

фантики slf4j

большинство библиотек журналов Scala были некоторыми оболочками вокруг Java logging framework (slf4j, log4j и т. д.), Но по состоянию на март 2015 года сохранившиеся библиотеки журналов-это все slf4j. эти библиотеки журналов предоставляют своего рода log объект, к которому можно обратиться info(...),debug(...) и т. д. Я не большой поклонник slf4j, но теперь, похоже, это преобладающая структура ведения журнала. Вот описание SLF4J:

Простой Logging Facade for Java или (SLF4J) служит простым фасадом или абстракцией для различных фреймворков ведения журнала, например java.утиль.logging, log4j и logback, что позволяет конечному пользователю подключать нужную структуру ведения журнала во время развертывания.

возможность изменения базовой библиотеки журналов во время развертывания дает уникальную характеристику всему семейству регистраторов slf4j, о которой вам нужно знать:

  1. classpath as конфигурация подход. Способ slf4j знает, какую базовую библиотеку журналов вы используете, загружая класс по некоторому имени. У меня были проблемы, в которых slf4j не распознал мой регистратор, когда classloader был настроен.
  2. потому что простой фасад пытается быть общим знаменателем, он ограничен только фактическими вызовами журнала. Другими словами, конфигурация не может быть выполнена с помощью кода.

в большом проекте это может быть удобно иметь возможность контролировать поведение журнала транзитивных зависимостей, если все использовали slf4j.

Scala Logging

Scala Logging написано Хайко Сеебергер в качестве преемника его slf4s. Он использует макрос для расширения вызовов в выражение if, чтобы избежать потенциально дорогостоящего вызова журнала.

Scala Logging-это удобная и производительная библиотека журналов, обертывающая библиотеки журналов, такие как SLF4J и потенциально другие.

исторические лесорубы

  • Logula, обертка Log4J, написанная Coda Hale. Раньше он мне нравился, но теперь заброшен.
  • configgy, java.утиль.лесозаготовительная обертка, которая была популярна в ранние дни Scala. Теперь заброшен.

С помощью Scala 2.10 + рассмотрим Скалалогирование по типам. Использует макросы для доставки очень чистого API

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

цитирую из Вики:

к счастью, макросы Scala могут быть использованы, чтобы сделать нашу жизнь проще: ScalaLogging предлагает класс Logger с облегченными методами ведения журнала, которые будут расширены до вышеуказанной идиомы. Так что все, что мы должны написать это:

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

после применения макроса код будет преобразован в описанную выше идиому.

кроме того, Скалалогирование предлагает признак Logging, который удобно представлен Logger экземпляр инициализируется с именем класса, смешанного в:

import com.typesafe.scalalogging.slf4j.LazyLogging

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

использование slf4j и оболочки приятно, но использование его встроено в интерполяцию ломается, когда у вас есть более двух значений для интерполяции, с тех пор вам нужно создать массив значений для интерполяции.

более Scala как решение заключается в использовании thunk или кластера для задержки конкатенации сообщения об ошибке. Хорошим примером этого является регистратор Lift

Log.скала Slf4jLog.скала

который выглядит как это:

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

обратите внимание, что msg является вызовом по имени и не будет оцениваться, если isTraceEnabled не имеет значения true, поэтому нет никаких затрат на создание хорошей строки сообщения. Это работает вокруг механизма интерполяции 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))

не используйте Logula

Я на самом деле следовал рекомендации Евгения и попробовал его и узнал, что он имеет неуклюжую конфигурацию и подвергается ошибкам, которые не исправляются (например,этот). Он не выглядит в хорошем состоянии, и это не поддерживает Scala 2.10.

используйте slf4s + slf4j-simple

ключевые преимущества:

  • поддерживает последнюю версию Scala 2.10(to дата это М7)
  • конфигурация универсальна, но не может быть проще. Это делается с свойства системы, который вы можете установить либо добавляя что-то вроде -Dorg.slf4j.simplelogger.defaultlog=trace для выполнения команды или записать в ваш скрипт: System.setProperty("org.slf4j.simplelogger.defaultlog", "trace"). Не нужно управлять дрянными конфигурационными файлами!
  • прекрасно сочетается с IDEs. Например, чтобы установить уровень ведения журнала для "трассировки" в определенной конфигурации запуска в IDEA просто перейдите к Run/Debug Configurations и добавить -Dorg.slf4j.simplelogger.defaultlog=trace to VM 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>

вот как я получил 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 для получения дополнительной информации.

я вытащил немного работы изLogging черт scalax, и создал черту, которая также интегрировала a 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))  
}

Я использую 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")
}

но этот подход использует экземпляр logger для каждого экземпляра класса.

вы должны взглянуть на библиотеку scalax : http://scalax.scalaforge.org/ В этой библиотеке есть функция ведения журнала, использующая sl4j в качестве бэкэнда. Используя эту особенность, вы можете войти довольно легко (просто используйте поле logger в классе, наследующем признак).

Writer,Monoid и Monad реализация.

еще не пробовал, но Configgy выглядит многообещающе как для конфигурации, так и для ведения журнала:

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

после использования slf4s и logula на некоторое время, я написал loglady, простая запись признака обертывания slf4j.

он предлагает API, похожий на библиотеку журналов Python, что делает общие случаи (базовая строка, простое форматирование) тривиальными и позволяет избежать форматирования шаблона.

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

Мне очень удобно использовать какой-то Java logger, 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.

быстрые и легкие формы.

Scala 2.10 и старше:

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

и строить.СБТ:

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....")

и строить.СБТ:

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

Comments

    Ничего не найдено.