Key Features
Supported for every popular style
Section titled “Supported for every popular style”You can use tofu.logging
in any style you want:
- Tagless Final style;
- Simple
cats.effect.IO
or(monix|zio).Task
andReaderT
; ZIO
and ZLayers — with the help of dedicated moduletofu-zio-logging
andZLogs
;- Even with
Future
s (although it’s kinda in the past).
Concise syntax
Section titled “Concise syntax”With the implicit instance of Logging
one can log messages with ease:
import tofu.logging._import tofu.syntax.logging._
val error = new Throwable("Oh no.")
def log[F[_] : Logging : Monad] = for { _ <- info"Hi! I'm logging" _ <- warn"Hello again!" _ <- error"It's me, error!" _ <- errorCause"So sad, I've got an error"(error)} yield ()
Structured and controllable
Section titled “Structured and controllable”You can easily put any necessary values into the structure of the log message with Loggable
; also you can fully
control what is logged and what is not:
import derevo._import tofu.logging._
@derive(Loggable)case class Payment(id: String, @hidden cardNumber: String, amount: Long)
def log[F[_] : Logging : Monad](payment: Payment) = info"Got payment $payment"
Given that there’s a defined Loggable
instance for this context and provided logger is context aware (e.g. created
with contextual
method), every logged message will contain information about context, for example:
{ "message": "Got payment payment", "level": "INFO", "payment": { "id": "131234234", "amount": 432 }}
Note that card number is not present at all as it was @hidden
.
Context support
Section titled “Context support”Let’s say your effect type has some context — it could be trace id or some domain info:
import cats._import cats.effect._
case class TraceId(id: Long)
type TracedIO[A] = ReaderT[TraceId, IO, A]
tofu.logging can extract it and automatically add into the structure of every log message:
class MyService[F[_] : Logging] { def sayHello: F[Unit] = info"Hello!"}
val ioservice = new MyService[IO]val tracedService = new MyService[TracedIO]
(Note the absence of anything related to context in MyService, logging doest it all itself.)
Now if we run tracedService.sayHello
the log message structure will contain the trace id:
{ "message": "Hello!", "level": "INFO", "trace.id": 64534}
and if we run ioService.sayHello
the message will be clean:
{ "message": "Hello!", "level": "INFO"}
More on that can be found on the dedicated recipe page.