dry-logger

v1.1
  1. Introduction

TOC

  1. Basic setup
  2. Using multiple logging destinations
  3. Skipping default behaviour
  4. Conditional logging
  5. Using custom templates
  6. Using colorized text output
  7. Customizing formatters
  8. Configuring log rotation

Introduction

dry-logger provides a standalone, dependency-free logging solution suitable for any Ruby application.

Basic setup

To configure a basic $stdout logger simply use the main setup method Dry.Logger:

logger = Dry.Logger(:my_app)

logger.info "Hello World"
# Hello World

The setup method accepts various options to configure the logger. You can change default formatter,
provide customized text templates, and so on.

Let's use a more detailed logging template that gives more logging context in the output:

logger = Dry.Logger(:test, template: :details)

logger.info "Hello World"
# [test] [INFO] [2022-11-17 11:43:52 +0100] Hello World

logger.info { "Hello World from a block" }
# [test] [INFO] [2022-11-17 11:44:12 +0100] Hello World from a block

Using multiple logging destinations

You can configure your logger to log to more than one destination. In case of the default logger,
the destination is set to $stdout. Let's say you want to log both to $stdout and a file:

logger = Dry.Logger(:test, template: :details).add_backend(stream: "logs/test.log")

# This goes to $stdout and logs/test.log too
logger.info "Hello World"
# [test] [INFO] [2022-11-17 11:46:12 +0100] Hello World

Skipping default behaviour

If you don't want to log to the default $stdout you can skip it by passing in a block to the
constructor:

logger = Dry.Logger(:test) do |dispatcher|
  dispatcher.add_backend(stream: "logs/test.log", template: :details)
end

# This goes to logs/test.log
logger.info "Hello World"
# [test] [INFO] [2022-11-17 11:46:12 +0100] Hello World

Conditional logging

You can tell your backends when exactly they should be logging using log_if option. It can be set
to either a symbol that represents a method that Dry::Logger::Entry implements or a custom proc.

Here's a simple example:

logger = Dry.Logger(:test, template: :details)
  .add_backend(stream: "logs/requests.log", log_if: -> entry { entry.key?(:request) })

# This goes only to $stdout
logger.info "Hello World"
# [test] [INFO] [2022-11-17 11:50:12 +0100] Hello World

# This goes to $stdout and logs/requests.log
logger.info "GET /posts", request: true
# [test] [INFO] [2022-11-17 11:51:50 +0100] GET /posts request=true

Using custom templates

You can provide customized text log templates using regular Ruby syntax for tokenized string templates:

logger = Dry.Logger(:test, template: "[%<severity>s] %<message>s")

logger.info "Hello World"
# [INFO] Hello World

The following tokens are supported:

Furthermore, you can use payload keys that are expected to be passed to a specific logging backend.
Here's an example:

logger = Dry.Logger(:test, template: "[%<severity>s] %<verb>s %<path>s")

logger.info verb: "GET", path: "/users"
# [INFO] GET /users

Using colorized text output

You can use simple color tags to colorize specific values in the text output:

logger = Dry.Logger(:test, template: "[%<severity>s] <blue>%<verb>s</blue> <green>%<path>s</green>")

# This is now colorized, you gotta trust us
logger.info verb: "GET", path: "/users"
# [INFO] GET /users

Following built-in color tags are supported:

Customizing formatters

There are three built-in formatters:

To configure a specific formatter, use the formatter option:

logger = Dry.Logger(:test, formatter: :rack)

logger.info verb: "GET", path: "/users", elapsed: "12ms", ip: "127.0.0.1", status: 200, length: 312, params: {}
# [test] [INFO] [2022-11-17 12:04:30 +0100] GET 200 12ms 127.0.0.1 /users 312

Configuring log rotation

You can use the Ruby Logger's log rotation support for any stream-based logger backend.

To rotate log files based on size, provide:

# Five 10-megabyte files.
logger = Dry.logger(:test, stream: "logs/test.log", shift_age: 5, shift_size: 10485760)

To rotate log files based on age, provide:

logger = Dry.logger(:test, stream: "logs/test.log", shift_age: "daily")

See the Ruby Logger documentation for more detail on its log rotation support.