Skip to content
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
## Unreleased

### Feature

- Support for `:logger` patch which enables sending logs to Sentry when `enabled_logs` is set to true ([#2657](https://github.com/getsentry/sentry-ruby/pull/2657))

Here's a sample config:

```ruby
Sentry.init do |config|
# ... your setup ...
config.enable_logs = true
config.enabled_patches = [:logger]
end
```

### Bug Fixes
- Skip creating `LogEventBuffer` if logging is not enabled ([#2652](https://github.com/getsentry/sentry-ruby/pull/2652))

## 5.25.0
Expand Down
1 change: 1 addition & 0 deletions sentry-ruby/lib/sentry-ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -690,3 +690,4 @@ def dependency_installed?(name)
require "sentry/graphql"
require "sentry/faraday"
require "sentry/excon"
require "sentry/std_lib_logger"
50 changes: 50 additions & 0 deletions sentry-ruby/lib/sentry/std_lib_logger.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# frozen_string_literal: true

module Sentry
# Ruby Logger support Add commentMore actions
# intercepts any logger instance and send the log to Sentry too.
module StdLibLogger
SEVERITY_MAP = {
0 => :debug,
1 => :info,
2 => :warn,
3 => :error,
4 => :fatal
}.freeze

def add(severity, message = nil, progname = nil, &block)
result = super

return unless Sentry.initialized? && Sentry.get_current_hub

# exclude sentry SDK logs -- to prevent recursive log action,
# do not process internal logs again
if message.nil? && progname != Sentry::Logger::PROGNAME

# handle different nature of Ruby Logger class:
# inspo from Sentry::Breadcrumb::SentryLogger
if block_given?
message = yield
else
message = progname
end

message = message.to_s.strip

if !message.nil? && message != Sentry::Logger::PROGNAME && method = SEVERITY_MAP[severity]
Sentry.logger.send(method, message)
end
end

result
end
end
end

Sentry.register_patch(:logger) do |config|
if config.enable_logs
::Logger.prepend(Sentry::StdLibLogger)
else
config.sdk_logger.warn(":logger patch enabled but `enable_logs` is turned off - skipping applying patch")
end
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also needs a SimpleCov.command_name since it is now isolated

Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
# frozen_string_literal: true

SimpleCov.command_name "SentryLogger"

RSpec.describe "Sentry::Breadcrumbs::SentryLogger" do
before do
perform_basic_setup do |config|
config.breadcrumbs_logger = [:sentry_logger]
config.enable_logs = true
config.max_log_events = 1
config.enabled_patches = [:logger]
end
end

Expand Down Expand Up @@ -100,4 +105,22 @@
end
end
end

it "does not conflict with :logger patch" do
logger = ::Logger.new(nil)

logger.info("Hello World")

expect(sentry_logs).to_not be_empty

log_event = sentry_logs.last

expect(log_event[:level]).to eql("info")
expect(log_event[:body]).to eql("Hello World")

breadcrumb = breadcrumbs.peek

expect(breadcrumb.level).to eq("info")
expect(breadcrumb.message).to eq("Hello World")
end
end
64 changes: 64 additions & 0 deletions sentry-ruby/spec/isolated/std_lib_logger_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# frozen_string_literal: true

SimpleCov.command_name "StdLibLogger"

RSpec.describe Sentry::StdLibLogger do
let(:logger) { ::Logger.new($stdout) }

context "when logger patch is enabled but enable_logs is turned off" do
it "logs a warning message" do
string_io = StringIO.new

perform_basic_setup do |config|
config.enable_logs = false
config.enabled_patches = [:logger]
config.sdk_logger = ::Logger.new(string_io)
end

expect(string_io.string).to include("WARN -- : :logger patch enabled but `enable_logs` is turned off - skipping applying patch")
end
end

context "when enable_logs is set to true but logger patch is not enabled" do
before do
perform_basic_setup do |config|
config.enable_logs = true
end
end

it "does not send log using stdlib logger" do
expect {
logger.send(:info, "Hello World")
}.to output(/Hello World/).to_stdout

expect(sentry_logs).to be_empty
end
end

context "when enable_logs is set to true and logger patch is set" do
before do
perform_basic_setup do |config|
config.max_log_events = 1
config.enable_logs = true
config.enabled_patches = [:redis, :puma, :http, :logger]
end
end

["info", "warn", "error", "fatal"].each do |level|
describe "##{level}" do
it "send logs using stdlib logger" do
expect {
logger.send(level, "Hello World")
}.to output(/Hello World/).to_stdout

expect(sentry_logs).to_not be_empty

log_event = sentry_logs.last

expect(log_event[:level]).to eql(level)
expect(log_event[:body]).to eql("Hello World")
end
end
end
end
end
Loading