Skip to content

Commit 28bb893

Browse files
committed
Improve DebugTransport
1 parent 37b4261 commit 28bb893

File tree

4 files changed

+77
-47
lines changed

4 files changed

+77
-47
lines changed

sentry-ruby/lib/sentry/test_helper.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ module Sentry
44
module TestHelper
55
DUMMY_DSN = "http://12345:67890@sentry.localdomain/sentry/42"
66

7+
# Not really real, but it will be resolved as a non-local for testing needs
8+
REAL_DSN = "https://user:pass@getsentry.io/project/42"
9+
710
# Alters the existing SDK configuration with test-suitable options. Mainly:
811
# - Sets a dummy DSN instead of `nil` or an actual DSN.
912
# - Sets the transport to DummyTransport, which allows easy access to the captured events.

sentry-ruby/lib/sentry/transport/debug_transport.rb

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,35 @@
22

33
require "json"
44
require "fileutils"
5+
require "pathname"
6+
require "delegate"
57

68
module Sentry
79
# DebugTransport is a transport that logs events to a file for debugging purposes.
810
#
911
# It can optionally also send events to Sentry via HTTP transport if a real DSN
1012
# is provided.
13+
class DebugTransport < SimpleDelegator
14+
DEFAULT_LOG_FILE_PATH = File.join("log", "sentry_debug_events.log")
1115

12-
DEFAULT_LOG_FILE_PATH = File.join("log", "sentry_debug_events.log")
16+
attr_reader :log_file, :backend
1317

14-
class DebugTransport < Transport
15-
attr_reader :log_file_path, :http_transport
18+
alias_method :__getobj, :backend
1619

1720
def initialize(configuration)
18-
super
21+
@log_file = initialize_log_file(configuration)
22+
@backend = initialize_backend(configuration)
1923

20-
@log_file_path = configuration.sdk_debug_transport_log_file || DEFAULT_LOG_FILE_PATH
21-
22-
FileUtils.mkdir_p(File.dirname(@log_file_path))
23-
24-
log_debug("DebugTransport: Initialized with log file: #{@log_file_path}")
25-
26-
if configuration.dsn && !configuration.dsn.to_s.include?("localhost")
27-
@http_transport = Sentry::HTTPTransport.new(configuration)
28-
log_debug("DebugTransport: Initialized with HTTP transport for DSN: #{configuration.dsn}")
29-
else
30-
@http_transport = nil
31-
log_debug("DebugTransport: Using local-only mode for DSN: #{configuration.dsn}")
32-
end
24+
super(@backend)
3325
end
3426

3527
def send_event(event)
36-
envelope = envelope_from_event(event)
37-
send_envelope(envelope)
38-
event
28+
log_envelope(envelope_from_event(event))
29+
backend.send_event(event)
3930
end
4031

41-
def send_envelope(envelope)
42-
envelope_data = {
32+
def log_envelope(envelope)
33+
envelope_json = {
4334
timestamp: Time.now.utc.iso8601,
4435
envelope_headers: envelope.headers,
4536
items: envelope.items.map do |item|
@@ -50,26 +41,35 @@ def send_envelope(envelope)
5041
end
5142
}
5243

53-
File.open(log_file_path, "a") do |file|
54-
file << JSON.dump(envelope_data) << "\n"
55-
end
56-
57-
if http_transport
58-
http_transport.send_envelope(envelope)
59-
end
44+
File.open(log_file, "a") { |file| file << JSON.dump(envelope_json) << "\n" }
6045
end
6146

62-
def events
63-
return [] unless File.exist?(log_file_path)
47+
def logged_envelopes
48+
return [] unless File.exist?(log_file)
6449

65-
File.readlines(log_file_path).map do |line|
50+
File.readlines(log_file).map do |line|
6651
JSON.parse(line)
6752
end
6853
end
6954

7055
def clear
71-
File.write(log_file_path, "")
72-
log_debug("DebugTransport: Cleared events from #{log_file_path}")
56+
File.write(log_file, "")
57+
log_debug("DebugTransport: Cleared events from #{log_file}")
58+
end
59+
60+
private
61+
62+
def initialize_backend(configuration)
63+
backend = configuration.dsn.local? ? DummyTransport : HTTPTransport
64+
backend.new(configuration)
65+
end
66+
67+
def initialize_log_file(configuration)
68+
log_file = Pathname(configuration.sdk_debug_transport_log_file || DEFAULT_LOG_FILE_PATH)
69+
70+
FileUtils.mkdir_p(log_file.dirname) unless log_file.dirname.exist?
71+
72+
log_file
7373
end
7474
end
7575
end

sentry-ruby/lib/sentry/transport/dummy_transport.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ def initialize(*)
1212

1313
def send_event(event)
1414
@events << event
15+
super
1516
end
1617

1718
def send_envelope(envelope)
Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,62 @@
11
# frozen_string_literal: true
22

3-
require 'contexts/with_request_mock'
4-
53
RSpec.describe Sentry do
6-
include_context "with request mock"
7-
84
let(:client) { Sentry.get_current_client }
95
let(:transport) { Sentry.get_current_client.transport }
6+
let(:error) { StandardError.new("test error") }
107

11-
before :all do
8+
before do
129
perform_basic_setup
13-
end
1410

15-
before do
1611
setup_sentry_test do |config|
12+
config.dsn = dsn
1713
config.transport.transport_class = Sentry::DebugTransport
14+
config.debug = true
1815
end
1916
end
2017

2118
after do
2219
teardown_sentry_test
2320
end
2421

25-
describe ".send_event" do
26-
let(:event) { Sentry.get_current_client.event_from_message("test message") }
22+
context "with local DSN for testing" do
23+
let(:dsn) { Sentry::TestHelper::DUMMY_DSN }
24+
25+
describe ".capture_exception with debug transport" do
26+
it "logs envelope data and stores an event internally" do
27+
Sentry.capture_exception(error)
28+
29+
expect(transport.events.count).to be(1)
30+
expect(transport.backend.events.count).to be(1)
31+
expect(transport.backend.envelopes.count).to be(1)
32+
33+
event = transport.logged_envelopes.last
34+
item = event["items"].first
35+
payload = item["payload"]
36+
37+
expect(payload["exception"]["values"].first["value"]).to include("test error")
38+
end
39+
end
40+
end
41+
42+
context "with a real DSN for testing" do
43+
let(:dsn) { Sentry::TestHelper::REAL_DSN }
44+
45+
describe ".capture_exception with debug transport" do
46+
it "sends an event and logs envelope" do
47+
stub_request(:post, "https://getsentry.io/project/api/42/envelope/")
48+
.to_return(status: 200, body: "", headers: {})
49+
50+
Sentry.capture_exception(error)
2751

28-
it "sends the event and logs to a file" do
29-
sentry_stub_request(build_fake_response("200"))
52+
expect(transport.logged_envelopes.count).to be(1)
3053

31-
Sentry.send_event(event)
54+
event = transport.logged_envelopes.last
55+
item = event["items"].first
56+
payload = item["payload"]
3257

33-
expect(transport.events.count).to be(1)
58+
expect(payload["exception"]["values"].first["value"]).to include("test error")
59+
end
3460
end
3561
end
3662
end

0 commit comments

Comments
 (0)