Skip to content

Commit

Permalink
Accept log messages via block (#28)
Browse files Browse the repository at this point in the history
Allow a dry-logger instance to accept log messages via a block.

If a block is passed to `#unknown`, `#debug`, `#info`, `#warn`, `#error`, or `#fatal`, the block's return value becomes the logged message much like the Ruby standardlib Logger.

Co-authored-by: Tim Riley <[email protected]>
  • Loading branch information
komidore64 and timriley authored May 10, 2024
1 parent ded0988 commit 1679541
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 15 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/_yardoc/
/coverage/
/doc/
/log/
/pkg/
/spec/reports/
/tmp/
Expand Down
3 changes: 3 additions & 0 deletions docsite/source/index.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ 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
Expand Down
41 changes: 26 additions & 15 deletions lib/dry/logger/dispatcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,53 +110,53 @@ def initialize(
# @see Dispatcher#log
# @api public
# @return [true]
def unknown(message = nil, **payload)
log(:unknown, message, **payload)
def unknown(message = nil, **payload, &block)
log(:unknown, message, **payload, &block)
end

# Log an entry with DEBUG severity
#
# @see Dispatcher#log
# @api public
# @return [true]
def debug(message = nil, **payload)
log(:debug, message, **payload)
def debug(message = nil, **payload, &block)
log(:debug, message, **payload, &block)
end

# Log an entry with INFO severity
#
# @see Dispatcher#log
# @api public
# @return [true]
def info(message = nil, **payload)
log(:info, message, **payload)
def info(message = nil, **payload, &block)
log(:info, message, **payload, &block)
end

# Log an entry with WARN severity
#
# @see Dispatcher#log
# @api public
# @return [true]
def warn(message = nil, **payload)
log(:warn, message, **payload)
def warn(message = nil, **payload, &block)
log(:warn, message, **payload, &block)
end

# Log an entry with ERROR severity
#
# @see Dispatcher#log
# @api public
# @return [true]
def error(message = nil, **payload)
log(:error, message, **payload)
def error(message = nil, **payload, &block)
log(:error, message, **payload, &block)
end

# Log an entry with FATAL severity
#
# @see Dispatcher#log
# @api public
# @return [true]
def fatal(message = nil, **payload)
log(:fatal, message, **payload)
def fatal(message = nil, **payload, &block)
log(:fatal, message, **payload, &block)
end

BACKEND_METHODS.each do |name|
Expand All @@ -179,6 +179,9 @@ def level
# @example logging a message
# logger.log(:info, "Hello World")
#
# @example logging a message by passing a block
# logger.log(:debug, "Sidecar") { "Hello World" }
#
# @example logging payload
# logger.log(:info, verb: "GET", path: "/users")
#
Expand All @@ -196,17 +199,25 @@ def level
# @param [Symbol] severity The log severity name
# @param [String] message Optional message
# @param [Hash] payload Optional log entry payload
# @yield
# @yieldreturn [String] Message to be logged
#
# @since 1.0.0
# @return [true]
# @api public
def log(severity, message = nil, **payload)
def log(severity, message = nil, **payload, &block)
case message
when Hash then log(severity, nil, **message)
when Hash then log(severity, **message, &block)
else
if block
progname = message
message = block.call
end
progname ||= id

entry = Entry.new(
clock: clock,
progname: id,
progname: progname,
severity: severity,
tags: @tags,
message: message,
Expand Down
52 changes: 52 additions & 0 deletions spec/dry/logger_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,58 @@

expect(output).to match("#{message} test=true")
end

it "logs to $stdout by default using a plain text block message" do
message = "hello, world"

logger.info { message }

expect(output).to match(message)
end

it "logs to $stdout by default using a plain text block message and payload" do
message = "hello, world"

logger.info(test: true) { message }

expect(output).to match("#{message} test=true")
end
end

context "using progname" do
subject(:logger) { Dry.Logger(:test, stream: stream, template: "%<progname>s: %<message>s %<payload>s") }

it "uses the logger ID as the progname" do
message = "hello, world"

logger.info(message)

expect(output).to match("test: #{message}")
end

it "replaces the default progname with the progname: keyword argument" do
message = "hello, world"

logger.info(message, progname: "newprog", test: true)

expect(output).to match("newprog: #{message} test=true")
end

it "replaces the progname with the first string argument when the message is given as a block" do
message = "hello, world"

logger.info("newprog") { message }

expect(output).to match("newprog: hello, world")
end

it "replaces the progname with the progname: keyword argument when the message is given as a block" do
message = "hello, world"

logger.info(progname: "newprog", test: true) { message }

expect(output).to match("newprog: #{message} test=true")
end
end

context "adding backends via block only" do
Expand Down

0 comments on commit 1679541

Please sign in to comment.