Skip to content

Commit 5c4e109

Browse files
committed
Add StructuredLogger and re-purpose Sentry.logger
1 parent a6482dc commit 5c4e109

File tree

5 files changed

+157
-6
lines changed

5 files changed

+157
-6
lines changed

sentry-ruby/lib/sentry-ruby.rb

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
require "sentry/utils/encoding_helper"
1212
require "sentry/utils/logging_helper"
1313
require "sentry/configuration"
14-
require "sentry/logger"
14+
require "sentry/structured_logger"
1515
require "sentry/event"
1616
require "sentry/error_event"
1717
require "sentry/transaction_event"
@@ -54,6 +54,7 @@ module Sentry
5454

5555
GLOBALS = %i[
5656
main_hub
57+
logger
5758
session_flusher
5859
backpressure_monitor
5960
metrics_aggregator
@@ -95,9 +96,8 @@ def exception_locals_tp
9596
attr_reader :metrics_aggregator
9697

9798
# @!attribute [r] logger
98-
# @return [Logger]
99-
# @!visibility private
100-
attr_reader :sdk_logger
99+
# @return [Logging::Device]
100+
attr_reader :logger
101101

102102
##### Patch Registration #####
103103

@@ -244,8 +244,8 @@ def init(&block)
244244
config = Configuration.new
245245
yield(config) if block_given?
246246

247-
# Internal SDK logger
248-
@sdk_logger = config.sdk_logger
247+
# Public-facing Structured Logger
248+
@logger = StructuredLogger.new(config) if config._experiments[:enable_logs]
249249

250250
config.detect_release
251251
apply_patches(config)
@@ -624,6 +624,11 @@ def sys_command(command)
624624
result.strip
625625
end
626626

627+
# @!visibility private
628+
def sdk_logger
629+
configuration.sdk_logger
630+
end
631+
627632
# @!visibility private
628633
def sdk_meta
629634
META

sentry-ruby/lib/sentry/configuration.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
require "sentry/metrics/configuration"
1313
require "sentry/linecache"
1414
require "sentry/interfaces/stacktrace_builder"
15+
require "sentry/logger"
1516
require "sentry/log_event_buffer"
1617

1718
module Sentry
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# frozen_string_literal: true
2+
3+
module Sentry
4+
module Logging
5+
class Device
6+
attr_reader :handlers
7+
8+
def initialize(options)
9+
@handlers = options.fetch(:handlers)
10+
end
11+
12+
def trace(message, payload = {})
13+
log(:trace, message, payload)
14+
end
15+
16+
def debug(message, payload = {})
17+
log(:debug, message, payload)
18+
end
19+
20+
def info(message, payload = {})
21+
log(:info, message, payload)
22+
end
23+
24+
def warn(message, payload = {})
25+
log(:warn, message, payload)
26+
end
27+
28+
def error(message, payload = {})
29+
log(:error, message, payload)
30+
end
31+
32+
def fatal(message, payload = {})
33+
log(:fatal, message, payload)
34+
end
35+
36+
def log(level, message, payload)
37+
handlers.each do |handler|
38+
case handler
39+
when Sentry::Logger
40+
handler.public_send(level, message)
41+
else
42+
handler.public_send(level, message, payload)
43+
end
44+
end
45+
end
46+
end
47+
end
48+
end
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# frozen_string_literal: true
2+
3+
module Sentry
4+
class StructuredLogger
5+
# https://develop.sentry.dev/sdk/telemetry/logs/#log-severity-number
6+
LEVELS = {
7+
"trace" => 1,
8+
"debug" => 5,
9+
"info" => 9,
10+
"warn" => 13,
11+
"error" => 17,
12+
"fatal" => 21
13+
}.freeze
14+
15+
attr_reader :config
16+
17+
def initialize(config)
18+
@config = config
19+
end
20+
21+
def trace(message, payload = {})
22+
log(:trace, message, payload)
23+
end
24+
25+
def debug(message, payload = {})
26+
log(:debug, message, payload)
27+
end
28+
29+
def info(message, payload = {})
30+
log(:info, message, payload)
31+
end
32+
33+
def warn(message, payload = {})
34+
log(:warn, message, payload)
35+
end
36+
37+
def error(message, payload = {})
38+
log(:error, message, payload)
39+
end
40+
41+
def fatal(message, payload = {})
42+
log(:fatal, message, payload)
43+
end
44+
45+
def log(level, message, payload)
46+
Sentry.capture_log(message, level: level, severity: LEVELS[level], **payload)
47+
end
48+
end
49+
end
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# frozen_string_literal: true
2+
3+
require "spec_helper"
4+
5+
RSpec.describe Sentry::StructuredLogger do
6+
context "when log events are not enabled" do
7+
before do
8+
perform_basic_setup
9+
end
10+
11+
it "logger is not set up" do
12+
expect(Sentry.logger).to be_nil
13+
end
14+
end
15+
16+
context "when log events are enabled" do
17+
before do
18+
perform_basic_setup do |config|
19+
config.max_log_events = 1
20+
config._experiments = { enable_logs: true }
21+
end
22+
end
23+
24+
let(:logs) do
25+
Sentry.get_current_client.log_event_buffer.pending_events
26+
end
27+
28+
# TODO: At the moment the Sentry::Logger enforces info - is that intentional?
29+
["info", "warn", "error", "fatal"].each do |level|
30+
describe "##{level}" do
31+
it "logs using default logger and LogEvent logger with extra attributes" do
32+
payload = { user_id: 123, action: "create" }
33+
34+
Sentry.logger.public_send(level, "Hello World", payload)
35+
36+
expect(logs).to_not be_empty
37+
38+
log_event = logs.last
39+
40+
expect(log_event.type).to eql("log")
41+
expect(log_event.level).to eql(level.to_sym)
42+
expect(log_event.body).to eql("Hello World")
43+
expect(log_event.attributes).to include(payload)
44+
end
45+
end
46+
end
47+
end
48+
end

0 commit comments

Comments
 (0)