-
Notifications
You must be signed in to change notification settings - Fork 170
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Support ActiveSupport::BroadcastLogger
Rails 7.1+ uses ActiveSupport::BroadcastLogger. This needs to protect against emitting duplicate logs in a different way than ActiveSupport::Logger.broadcast. Emits the log record for the first logger in the broadcast, skip the others. Reset everything at the end of the method call.
- Loading branch information
1 parent
7f8dce1
commit e5cc573
Showing
5 changed files
with
154 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
...ogger/lib/opentelemetry/instrumentation/logger/patches/active_support_broadcast_logger.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# frozen_string_literal: true | ||
|
||
# Copyright The OpenTelemetry Authors | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
module OpenTelemetry | ||
module Instrumentation | ||
module Logger | ||
module Patches | ||
# Patches for the ActiveSupport::BroadcastLogger class included in Rails 7.1+ | ||
module ActiveSupportBroadcastLogger | ||
def add(*args) | ||
emit_one_broadcast(*args) { super } | ||
end | ||
|
||
def debug(*args) | ||
emit_one_broadcast(*args) { super } | ||
end | ||
|
||
def info(*args) | ||
emit_one_broadcast(*args) { super } | ||
end | ||
|
||
def warn(*args) | ||
emit_one_broadcast(*args) { super } | ||
end | ||
|
||
def error(*args) | ||
emit_one_broadcast(*args) { super } | ||
end | ||
|
||
def fatal(*args) | ||
emit_one_broadcast(*args) { super } | ||
end | ||
|
||
def unknown(*args) | ||
emit_one_broadcast(*args) { super } | ||
end | ||
|
||
private | ||
|
||
# Emit logs from only one of the loggers in the broadcast. | ||
# Set @skip_instrumenting to `true` to the rest of the loggers before emitting the logs. | ||
# Set @skip_instrumenting to `false` after the log is emitted. | ||
def emit_one_broadcast(*args) | ||
broadcasts[1..-1].each { |broadcasted_logger| broadcasted_logger.instance_variable_set(:@skip_instrumenting, true) } | ||
yield | ||
broadcasts.each { |broadcasted_logger| broadcasted_logger.instance_variable_set(:@skip_instrumenting, false) } | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
88 changes: 88 additions & 0 deletions
88
...test/opentelemetry/instrumentation/logger/patches/active_support_broadcast_logger_test.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# frozen_string_literal: true | ||
|
||
# Copyright The OpenTelemetry Authors | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
require 'test_helper' | ||
|
||
require_relative '../../../../../lib/opentelemetry/instrumentation/logger/patches/active_support_broadcast_logger' | ||
|
||
describe OpenTelemetry::Instrumentation::Logger::Patches::ActiveSupportBroadcastLogger do | ||
let(:instrumentation) { OpenTelemetry::Instrumentation::Logger::Instrumentation.instance } | ||
let(:logger) { Logger.new(LOG_STREAM) } | ||
let(:logger2) { Logger.new(BROADCASTED_STREAM) } | ||
let(:broadcast) { ActiveSupport::BroadcastLogger.new(logger, logger2) } | ||
|
||
before do | ||
skip unless defined?(::ActiveSupport::BroadcastLogger) | ||
EXPORTER.reset | ||
instrumentation.install | ||
end | ||
|
||
after { instrumentation.instance_variable_set(:@installed, false) } | ||
|
||
describe '#add' do | ||
it 'emits the log to the broadcasted loggers' do | ||
body = "Ground control to Major Tom" | ||
broadcast.add(Logger::DEBUG, body) | ||
|
||
assert_includes(LOG_STREAM.string, body) | ||
assert_includes(BROADCASTED_STREAM.string, body) | ||
end | ||
|
||
it 'emits only one OpenTelemetry log record' do | ||
body = "Wake up, you sleepyhead" | ||
broadcast.add(Logger::DEBUG, body) | ||
log_records = EXPORTER.emitted_log_records | ||
|
||
assert_equal 1, log_records.size | ||
assert_equal 'DEBUG', log_records.first.severity_text | ||
assert_equal body, log_records.first.body | ||
end | ||
end | ||
|
||
describe '#unknown' do | ||
it 'emits the log to the broadcasted loggers' do | ||
body = "I know when to go out" | ||
broadcast.unknown(body) | ||
|
||
assert_includes(LOG_STREAM.string, body) | ||
assert_includes(BROADCASTED_STREAM.string, body) | ||
end | ||
|
||
it 'emits only one OpenTelemetry log record' do | ||
body = "You've got your mother in a whirl" | ||
broadcast.unknown(body) | ||
|
||
log_records = EXPORTER.emitted_log_records | ||
|
||
assert_equal 1, log_records.size | ||
assert_equal 'ANY', log_records.first.severity_text | ||
assert_equal body, log_records.first.body | ||
end | ||
end | ||
|
||
%w[debug info warn error fatal].each do |severity| | ||
describe "##{severity}" do | ||
it 'emits the log to the broadcasted loggers' do | ||
body = "Still don't know what I was waiting for...#{rand(7)}" | ||
broadcast.send(severity.to_sym, body) | ||
|
||
assert_includes(LOG_STREAM.string, body) | ||
assert_includes(BROADCASTED_STREAM.string, body) | ||
end | ||
|
||
it 'emits only one OpenTelemetry log record' do | ||
body = "They pulled in just behind the bridge...#{rand(7)}" | ||
broadcast.send(severity.to_sym, body) | ||
|
||
log_records = EXPORTER.emitted_log_records | ||
|
||
assert_equal 1, log_records.size | ||
assert_equal severity.upcase, log_records.first.severity_text | ||
assert_equal body, log_records.first.body | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters