Skip to content

Commit

Permalink
Fix Log::Builder mutate user-provided broadcast backend
Browse files Browse the repository at this point in the history
  • Loading branch information
straight-shoota committed May 2, 2023
1 parent bca65cf commit 0a1573e
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 12 deletions.
23 changes: 21 additions & 2 deletions spec/std/log/builder_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,25 @@ describe Log::Builder do
log.level.should eq(s(:info))
end

it "does not alter user-provided broadcast backend" do
builder = Log::Builder.new
a = Log::MemoryBackend.new
b = Log::MemoryBackend.new

broadcast = Log::BroadcastBackend.new
broadcast.append(a, :fatal)
previous_backends = broadcast.@backends.dup

builder.bind("db", :trace, broadcast)
builder.bind("db", :info, b)

log = builder.for("db")

backend = log.backend.should be_a(Log::BroadcastBackend)
backend.should_not be broadcast
broadcast.@backends.should eq(previous_backends)
end

it "creates a log for broadcast backend" do
builder = Log::Builder.new
a = Log::MemoryBackend.new
Expand All @@ -61,9 +80,9 @@ describe Log::Builder do
log = builder.for("db")

backend = log.backend.should be_a(Log::BroadcastBackend)
backend.@backends.should eq({a => s(:fatal), b => s(:info)})
backend.@backends.should eq({broadcast => s(:trace), b => s(:info)})
log.source.should eq("db")
log.level.should eq(s(:info))
log.level.should eq(s(:trace))
end

it "creates a log for same broadcast backend added multiple times" do
Expand Down
6 changes: 6 additions & 0 deletions src/log/broadcast_backend.cr
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
class Log::BroadcastBackend < Log::Backend
property level : Severity? = nil

# :nodoc:
#
# Indicates whether this backend is used by a `Log` instance to distribute
# its messages to multiple backends.
property? internal = false

@backends = Hash(Log::Backend, Severity).new

def initialize
Expand Down
17 changes: 7 additions & 10 deletions src/log/builder.cr
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,16 @@ class Log::Builder
# if the bind applies for the same backend, the last applied
# level should be used
log.initial_level = level
when BroadcastBackend
current_backend.append(backend, level)
# initial_level needs to be recomputed since the append_backend
# might be called with the same backend as before but with a
# different (higher) level
log.initial_level = current_backend.min_level
current_backend.level = log.changed_level
else
broadcast = BroadcastBackend.new
broadcast.append(current_backend, log.initial_level)
broadcast = current_backend.as?(BroadcastBackend)
unless broadcast && broadcast.internal?
broadcast = BroadcastBackend.new
broadcast.internal = true
broadcast.append(current_backend, log.initial_level)
log.backend = broadcast
end
broadcast.append(backend, level)
broadcast.level = log.changed_level
log.backend = broadcast
log.initial_level = broadcast.min_level
end
end
Expand Down

0 comments on commit 0a1573e

Please sign in to comment.