Skip to main content
Version: ZIO 2.x

Introduction to ZIO Logging

ZIO Logging is simple logging for ZIO apps, with correlation, context, and pluggable backends out of the box with integrations for common logging backends.

Production Ready CI Badge Sonatype Releases Sonatype Snapshots javadoc ZIO Logging

Introduction

When we are writing our applications using ZIO effects, to log easy way we need a ZIO native solution for logging. ZIO Logging is an environmental effect for adding logging into our ZIO applications.

Key features of ZIO Logging:

  • ZIO Native — Other than it is a type-safe and purely functional solution, it leverages ZIO's features.
  • Multi-Platform - It supports both JVM and JS platforms.
  • Composable — Loggers are composable together via contraMap.
  • Pluggable Backends — Support multiple backends like ZIO Console, SLF4j, JS Console, JS HTTP endpoint.
  • Logger Context — It has a first citizen Logger Context implemented on top of FiberRef. The Logger Context maintains information like logger name, filters, correlation id, and so forth across different fibers. It supports Mapped Diagnostic Context (MDC) which manages contextual information across fibers in a concurrent environment.
  • Richly integrated into ZIO 2's built-in logging facilities
  • ZIO Console, SLF4j, and other backends

Installation

In order to use this library, we need to add the following line in our build.sbt file:

libraryDependencies += "dev.zio" %% "zio-logging" % "2.1.8"

There are also some optional dependencies:

// JPL integration
libraryDependencies += "dev.zio" %% "zio-logging-jpl" % "2.1.8"

// SLF4j integration
libraryDependencies += "dev.zio" %% "zio-logging-slf4j" % "2.1.8"

// Using ZIO Logging for SLF4j loggers, usually third-party non-ZIO libraries
libraryDependencies += "dev.zio" %% "zio-logging-slf4j-bridge" % "2.1.8"

Example

Let's try an example of ZIO Logging which demonstrates a simple application of ZIO logging.

The recommended place for setting the logger is application boostrap. In this case, custom logger will be set for whole application runtime (also application failures will be logged with specified logger).

import zio.logging.{ LogFormat, console }
import zio.{ ExitCode, Runtime, Scope, ZIO, ZIOAppArgs, ZIOAppDefault, ZLayer }

object SimpleApp extends ZIOAppDefault {

override val bootstrap: ZLayer[ZIOAppArgs, Any, Any] =
Runtime.removeDefaultLoggers >>> console(LogFormat.default)

override def run: ZIO[Scope, Any, ExitCode] =
for {
_ <- ZIO.logInfo("Start")
_ <- ZIO.fail("FAILURE")
_ <- ZIO.logInfo("Done")
} yield ExitCode.success

}

Expected console output:

timestamp=2022-10-28T18:40:25.517623+02:00 level=INFO thread=zio-fiber-6 message="Start"
timestamp=2022-10-28T18:40:25.54676+02:00 level=ERROR thread=zio-fiber-0 message="" cause=Exception in thread "zio-fiber-6" java.lang.String: FAILURE
at zio.logging.example.SimpleApp.run(SimpleApp.scala:14)

You can find the source code of examples here