Log
The natchez-log
module provides a back end that logs traces locally (as JSON) to a log4cats Logger
, with no distributed functionality. To use it, add the following dependency.
- sbt
libraryDependencies += "org.tpolecat" %% "natchez-log" % "0.1.5"
- Maven
<dependencies> <dependency> <groupId>org.tpolecat</groupId> <artifactId>natchez-log_2.13</artifactId> <version>0.1.5</version> </dependency> </dependencies>
- Gradle
dependencies { implementation "org.tpolecat:natchez-log_2.13:0.1.5" }
Example Trace
The log handler constructs a JSON object for each root span, with a children
collection of child spans. On completion of the root span the entire JSON blob is logged as a single message. Here is an example with a root span containing two custom fields and two child spans.
{
"name" : "root span",
"service" : "example-service",
"timestamp" : "2021-05-26T16:41:09.221325Z",
"duration_ms" : 108,
"trace.span_id" : "dd817430-c00a-423e-9db4-0a24897b9cb9",
"trace.parent_id" : null,
"trace.trace_id" : "ef7758f0-7b33-4358-81f5-4f2070f7196d",
"exit.case" : "succeeded",
"person.name" : "bob",
"person.age" : 42,
"children" : [
{
"name" : "thing one",
"service" : "example-service",
"timestamp" : "2021-05-26T16:41:09.301796Z",
"duration_ms" : 3,
"trace.span_id" : "93f6aab7-b89d-4c11-b21a-2272ae6f5697",
"trace.parent_id" : "ef7758f0-7b33-4358-81f5-4f2070f7196d",
"trace.trace_id" : "ef7758f0-7b33-4358-81f5-4f2070f7196d",
"exit.case" : "succeeded",
"children" : [
]
},
{
"name" : "thing two",
"service" : "example-service",
"timestamp" : "2021-05-26T16:41:09.328357Z",
"duration_ms" : 1,
"trace.span_id" : "f94c8eed-8c1a-4c02-b40e-36266e40b4d5",
"trace.parent_id" : "ef7758f0-7b33-4358-81f5-4f2070f7196d",
"trace.trace_id" : "ef7758f0-7b33-4358-81f5-4f2070f7196d",
"exit.case" : "succeeded",
"children" : [
]
}
]
}
Constructing an EntryPoint
You can construct a log EntryPoint
given an implicit Logger[F]
.
import cats.effect.IO
import natchez.EntryPoint
import natchez.log.Log
import org.typelevel.log4cats.Logger
import org.typelevel.log4cats.slf4j.Slf4jLogger
implicit val log: Logger[IO] =
Slf4jLogger.getLoggerFromName("example-logger")
val ep: EntryPoint[IO] =
Log.entryPoint[IO]("example-service")
Log.entryPoint
takes an optional second parameter format: io.circe.Json => String
that can be used to manipulate the structure and content of the trace and customize the way it is formatted. The default value is _.spaces2
.
Log Fields
Log spans include the following fields, in addition to any user-specified fields:
Field | Json Type | Meaning |
---|---|---|
service |
String | User-supplied service name. |
timestamp |
String | ISO-8601 date and time of span start. |
name |
String | User-supplied span name. |
trace.trace_id |
String (UUID) | Id shared by all spans in a trace. |
trace.span_id |
String (UUID) | Id of the parent span, if any. |
trace.parent_id |
String (UUID, Optional) | Id of the parent span, if any. |
duration_ms |
Number | Span duration, in milliseconds. |
exit.case |
String | completed , canceled , or error |
exit.error.class |
String (Optional) | Exception classname, if any. |
exit.error.message |
String (Optional) | Exception message, if any. |
exit.error.stackTrace |
List of String (Optional) | Exception stack trace, if any. |
If you don’t want to see the trace/span IDs or other fields, you can filter them out by supplying a format
argument to entryPoint
that manipulates the JSON however you like.