Natchez SLF4J

The module provides a natchez EntryPoint that sends tracing information to an SLF4J logger. At OVO, we use this to make it easy to see tracing information in the terminal when running locally. Once you have the EntryPoint you can then use natchez as described in its README.

Installation

Add this module and an SLF4J binding (in this example we’re using Logback) to your build.sbt:

val natchezExtrasVersion = "8.1.0"

libraryDependencies ++= Seq(
  "ch.qos.logback"  %  "logback-classic"      % "1.2.3",
  "com.ovoenergy"   %% "natchez-extras-slf4j" % natchezExtrasVersion
)

Example usage

import cats.effect.{ExitCode, IO, IOApp}
import com.ovoenergy.natchez.extras.slf4j.Slf4j
import natchez.EntryPoint

import scala.concurrent.duration._

object MyTracedApp extends IOApp {

  /**
   * Create a Natchez entrypoint that will send traces to SLF4J
   */
  val slf4j: EntryPoint[IO] = Slf4j.entryPoint[IO]

  /**
   * This app creates a root span, adds a tag to set the env to UAT
   * then creates a subspan that sleeps for two seconds
   */
  def run(args: List[String]): IO[ExitCode] =
    slf4j.root("root-span").use { rootSpan =>
      for {
        _ <- rootSpan.put("env" -> "uat")
        _ <- rootSpan.span("child-span").use(_ => IO.sleep(2.seconds))
      } yield ExitCode.Success
    }
}

If you run this example, you should see some output like this:

sbt> run
[info] Running MyTracedApp
14:14:26.296 [ioapp-compute-0] INFO natchez - root-span started
14:14:26.305 [ioapp-compute-0] INFO natchez - child-span started
14:14:28.318 [ioapp-compute-1] INFO natchez - child-span success
14:14:28.320 [ioapp-compute-1] INFO natchez - root-span success
[success] Total time: 3 s, completed 22-May-2020 14:14:28

Although you can see when each trace started and ended, eagle-eyed readers will notice that the env tag we added to the root span is not visible. This is because span tags get added to the SLF4J MDC (mapped diagnostic context) and by default Logback doesn’t print the MDC to the console.

We can fix this by creating a Logback config file at src/main/resources/logback.xml with the following content (the important part is that the <pattern> element includes the %mdc pattern):


<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
  <appender name="CONSOLE"
		    class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %level %logger{36} - %msg {%mdc}%n</pattern>
    </encoder>
  </appender>

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

Now if we run the code again, we can see the span tags in the console too:

[info] Running MyTracedApp
14:31:19.835 [ioapp-compute-0] INFO natchez - root-span started {traceToken=b54bfc5d-91e7-497e-9227-f2380da4ba28}
14:31:19.846 [ioapp-compute-0] INFO natchez - child-span started {env=uat, traceToken=b54bfc5d-91e7-497e-9227-f2380da4ba28}
14:31:21.859 [ioapp-compute-1] INFO natchez - child-span success {env=uat, traceToken=b54bfc5d-91e7-497e-9227-f2380da4ba28}
14:31:21.860 [ioapp-compute-1] INFO natchez - root-span success {env=uat, traceToken=b54bfc5d-91e7-497e-9227-f2380da4ba28}
[success] Total time: 3 s, completed 22-May-2020 14:31:21