Scala 记录行号 - slf4s/slf4j?

发布于 2024-10-14 14:30:09 字数 444 浏览 1 评论 0原文

更新:已解决!!!
请参阅我在下面添加的答案


有谁知道是否有一种方法可以进行日志记录,将真实的行号输出到控制台?我试图在这里进入 Scala,但是如果无法获得我所依赖的像这样的基本东西,那么真的很难取得进展。

我已经设置 slf4s 来用 slf4j - log4j - jcl-over-slf4j 包装。问题是我得到的行号根本不匹配。它们的行数甚至比 Scala 类包含的行数要高得多。这是因为行号实际上是 Java 中间行号吗?

是否有任何简单方法来设置满足这些要求的日志记录?:

  1. 可互操作,可与 java 和 java 一起使用。 scala
  2. 可以轻松地更改各个包的日志记录级别,就像 log4j
  3. 提供准确的行号一样容易。

谢谢!

杰米

UPDATE: SOLVED!!!
Please see the answer I added below


Does anyone know if there is a way to do logging that outputs real line numbers to the console? I'm trying to get into Scala here, but without being able to get basic stuff like this that I depend on, it's really hard to get much going.

I have set up slf4s to wrap with slf4j - log4j - jcl-over-slf4j. The problem is I get line numbers that do not match at all. The are much higher line numbers than the Scala class even contains. Is this because the line numbers are actually Java-intermediate line numbers?

Is there any EASY way to get set up logging that meets these requirements?:

  1. interoperable, working with both java & scala
  2. as easy to change the logging level of individual packages as easily as log4j
  3. provides ACCURATE line numbers.

Thanks!

Jamie

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

反话 2024-10-21 14:30:09

我发现 logback (由 Ceki Gülcü)效果很好,并且也保留了行号!
(它可以替代 log4j:太棒了! )

import ch.qos.logback._
import org.slf4j._

object Main {

    def logger = LoggerFactory.getLogger("Main")
    var thingy = {
        x:Int =>
        logger.info("x=" + x)
        x + 1
    }
    def main(args: Array[String]) {
        logger.info("Hello.")
        logger.info("Hello again!")

        val myInts : List[Int] = List(-25,1,5,20)

        val myInts2 : List[Int] = myInts.filter { x:Int => x > 0 }

        logger.info("my ints2:" + myInts2)

        val myInts3 = myInts2.map(p =>  p * 2 )
        logger.info("my ints3:" + myInts3)

        logger.info(thingy(1) + "")
    }
}

对于那些努力开始使用 Scala 的人,这就是我为获得基本框架所做的事情:

1)下载 sbt-launcher.jar 并将其放在 /opt/ 等位置
我使用了“sbt-launch-0.7.5.RC0.jar"

2) 创建一个 bash 脚本作为 nano/ 中 sbt 启动器的快捷方式opt/bin/sbt:(

#!/bin/bash
java -jar /opt/sbt-launch-0.7.5.RC0.jar "$@"

使其可执行)

$ sudo chmod ug+x ./sbt

确保它也在您的路径中。

3)创建并配置 sbt 项目:

$ mkdir ./sc01
$ cd ./sc01
$ sbt
$ mkdir ./project/build</pre>
$ nano ./project/build/Project.scala</pre>

将其放在那里:

import sbt._

class sc01(info: ProjectInfo) extends DefaultProject(info)
{
    // dependencies
    val logback_core = "ch.qos.logback" % "logback-core" % "0.9.24" % "compile" //LGPL 2.1
    val logback_classic = "ch.qos.logback" % "logback-classic" % "0.9.24" % "compile" //LGPL 2.1
    val log4j_over_slf4j = "org.slf4j" % "log4j-over-slf4j" % "1.6.1"


   // if you are going to have any unmanaged (manually-added) jars
   //    def baseDirectories = "lib"
   //    def extraJars = descendents(baseDirectories, "*.jar")
   //    override def unmanagedClasspath = super.unmanagedClasspath +++ extraJars

    // tasks - easy to define
    lazy val hi = task { println("Hello World"); None }

    // classpath
    //override def mainScalaSourcePath = "src"

}

4)将上面的内容粘贴到 Main 中:

$ nano ./src/main/scala/Main.scala

5)我差点忘了!将其放入 /src/main/resources/logback.xml
(需要获取行号)

<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type
     ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %line --- %msg%n</pattern>
        </encoder>
    </appender>

    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

6) $ sbt

现在您应该位于 shell 的 sbt 控制台中:

> update
> compile
> run

希望这会有所帮助。

I have found that logback (by Ceki Gülcü) works great and preserves line numbers too!
(And it works as a replacement for log4j: Awesome!)

import ch.qos.logback._
import org.slf4j._

object Main {

    def logger = LoggerFactory.getLogger("Main")
    var thingy = {
        x:Int =>
        logger.info("x=" + x)
        x + 1
    }
    def main(args: Array[String]) {
        logger.info("Hello.")
        logger.info("Hello again!")

        val myInts : List[Int] = List(-25,1,5,20)

        val myInts2 : List[Int] = myInts.filter { x:Int => x > 0 }

        logger.info("my ints2:" + myInts2)

        val myInts3 = myInts2.map(p =>  p * 2 )
        logger.info("my ints3:" + myInts3)

        logger.info(thingy(1) + "")
    }
}

For anyone struggling to get started with Scala, this is what I did to get the basic skeleton up:

1) Download sbt-launcher.jar and put it someplace like /opt/
I used "sbt-launch-0.7.5.RC0.jar"

2) Create a bash script as a shortcut to the sbt launcher in nano /opt/bin/sbt:

#!/bin/bash
java -jar /opt/sbt-launch-0.7.5.RC0.jar "$@"

(make it executable)

$ sudo chmod ug+x ./sbt

Make sure it's in your path too.

3) Create and configure the sbt project:

$ mkdir ./sc01
$ cd ./sc01
$ sbt
$ mkdir ./project/build</pre>
$ nano ./project/build/Project.scala</pre>

put this in there:

import sbt._

class sc01(info: ProjectInfo) extends DefaultProject(info)
{
    // dependencies
    val logback_core = "ch.qos.logback" % "logback-core" % "0.9.24" % "compile" //LGPL 2.1
    val logback_classic = "ch.qos.logback" % "logback-classic" % "0.9.24" % "compile" //LGPL 2.1
    val log4j_over_slf4j = "org.slf4j" % "log4j-over-slf4j" % "1.6.1"


   // if you are going to have any unmanaged (manually-added) jars
   //    def baseDirectories = "lib"
   //    def extraJars = descendents(baseDirectories, "*.jar")
   //    override def unmanagedClasspath = super.unmanagedClasspath +++ extraJars

    // tasks - easy to define
    lazy val hi = task { println("Hello World"); None }

    // classpath
    //override def mainScalaSourcePath = "src"

}

4) Paste the stuff from above into Main:

$ nano ./src/main/scala/Main.scala

5) I almost forgot! put this in /src/main/resources/logback.xml
(it's required to get the line numbers)

<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type
     ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %line --- %msg%n</pattern>
        </encoder>
    </appender>

    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

6) $ sbt

Now you should be in the sbt console in your shell:

> update
> compile
> run

Hope this helps.

雨夜星沙 2024-10-21 14:30:09

正如您在 Scala 日志记录 问题中评论时,在 Scala 中获取精确的行号信息很困难。

  • 为什么 Scala 不只是通过保存来使现有基础设施超载
    绝对偏移量而不是 LineNumberTable 中的行号?
    另一种寻址方式是对标记进行编号,而不是对标记进行编号。
    源文件中的实际偏移量。
  • 虽然我喜欢按标记建立索引的想法,但这意味着任何能够使用调试信息的工具都需要访问完整的解析器。
    另一种可能性是根据一些严格定义的规则集重新格式化文件,然后继续使用行编号。
  • 我开始致力于改善 Scala 程序的调试体验,其中一个痛点确实是行号。理想情况下,不仅仅支持行号。我正在查看 JSR 45(对其他语言的调试支持)。我还不确定这是否足够,但也许 Scala 层可以使用你的方案。
    我认为更好的方法是在 classfile 属性或注释中提供额外的、Scala 特定的调试信息。据我所知,JDI 不允许访问 classfile 属性,也不允许访问注释,但是我们可以使用一些技巧来访问它们。这样我们就可以保留现有功能,并允许工具在了解 Scala 属性时执行更多操作。

(注:Scalate 报告在 scalate-24 用于不同类型的源文件)

As you are commenting in Scala logging question, getting precise line number information in Scala is hard.

  • Why does Scala not just overload the existing infrastructure by saving
    absolute offsets instead of line numbers in the LineNumberTable?
    Another way of addressing could be by numbering the tokens instead of
    the actual offsets into source files.
  • While I love the idea of indexing by tokens, this means that any tool capable of using the debug information would need to have access to a full parser.
    Another possibility would be to reformat the file according to some strictly-defined set of rules, and then continue to use line numbering.
  • I started working on improving the debugging experience for Scala programs, and one of the sore-points is indeed line numbers. Ideally there would be support for more than just line numbers. I am looking at JSR 45 (Debugging support for other languages). I am not sure yet if that is enough, but maybe a Scala stratum could use your scheme.
    I think the better way is to provide additional, Scala specific, debugging information in classfile attributes or annotations. As far as I know, JDI does not give access to classfile attributes, nor to annotations, but there are some tricks we could use to get to them. This way we'd preserve existing functionality, and allow tools to do more when they know about Scala attributes.

(Note: Scalate reports having done a similar work in scalate-24 for a different kind of source files)

拿命拼未来 2024-10-21 14:30:09

2016 年更新:像 lihaoyi/sourcecode 这样的库确实包含 日志用例采用新方法:

您可以使用sourcecode.File和sourcecode.Line来定义自动捕获的日志函数他们的行号和文件名

def log(foo: String)(implicit line: sourcecode.Line, file: sourcecode.File) = {
  println(s"${file.value}:${line.value} $foo")
}

log("Foooooo") // sourcecode/shared/src/test/scala/sourcecode/Tests.scala:86 Fooooo

这可以很方便地让您查看日志行的来源,而无需用唯一的前缀繁琐地标记每个日志语句。
此外,这发生在编译时,因此比通过生成堆栈跟踪获取此信息要快几个数量级,并且可以在 Scala.js 上工作,而堆栈检查无法实现 .
最后,如果您希望向日志记录函数提供其他信息,例如方法名称、类名称或包,您可以通过询问 sourcecode.Namesourcecode 轻松实现。 FullNamesourcecode.Pkg 隐式。

Update 2016: a library like lihaoyi/sourcecode does include a logging use case with a new approach:

You can use sourcecode.File and sourcecode.Line to define log functions that automatically capture their line number and file-name

def log(foo: String)(implicit line: sourcecode.Line, file: sourcecode.File) = {
  println(s"${file.value}:${line.value} $foo")
}

log("Foooooo") // sourcecode/shared/src/test/scala/sourcecode/Tests.scala:86 Fooooo

This can be handy for letting you see where the log lines are coming from, without tediously tagging every log statement with a unique prefix.
Furthermore, this happens at compile time, and is thus orders of magnitude faster than getting this information by generating stack traces, and works on Scala.js where stack-inspection does not.
Lastly, if you want additional information such as method names, class names, or packages to be provided to your logging function, you can easily do so by asking for the sourcecode.Name or sourcecode.FullName or sourcecode.Pkg implicits.

草莓味的萝莉 2024-10-21 14:30:09

我建议看看 Scribe。它是 Scala 的完整日志记录解决方案,使用宏在编译时生成行号和其他信息,因此不会降低速度,而且它是内置的,因此您不必使用诸如 sourcecode 并手动集成:

https://github.com/outr/scribe

I would recommend taking a look at Scribe. It's a complete logging solution for Scala using Macros to generate line numbers and other information at compile-time so there is no reduction in speed, and it's built-in so you don't have to use something like sourcecode and integrate it manually:

https://github.com/outr/scribe

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文