Skip to content

Commit d643fcd

Browse files
authored
feat(rails): add binds to ActiveRecord logs (#2761)
* feat(rails): add binds to ActiveRecord logs * Update CHANGELOG * Binds could be `nil` so don't crash if they are * Follow conventions for db.query.params attributes * Make it work under jruby too
1 parent 582aeb9 commit d643fcd

File tree

8 files changed

+94
-0
lines changed

8 files changed

+94
-0
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## Unreleased
2+
3+
### Features
4+
5+
- Add support for ActiveRecord binds in the log events ([#2761](https://github.com/getsentry/sentry-ruby/pull/2761))
6+
17
## 6.0.0
28

39
### Breaking Changes

sentry-rails/lib/sentry/rails/log_subscribers/active_record_subscriber.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,17 @@ def sql(event)
4646
cached: cached
4747
}
4848

49+
binds = event.payload[:binds]
50+
51+
if Sentry.configuration.send_default_pii && !binds&.empty?
52+
type_casted_binds = type_casted_binds(event)
53+
54+
binds.each_with_index do |bind, index|
55+
name = bind.is_a?(Symbol) ? bind : bind.name
56+
attributes["db.query.parameter.#{name}"] = type_casted_binds[index].to_s
57+
end
58+
end
59+
4960
attributes[:statement_name] = statement_name if statement_name && statement_name != "SQL"
5061
attributes[:connection_id] = connection_id if connection_id
5162

@@ -60,6 +71,16 @@ def sql(event)
6071
)
6172
end
6273

74+
if RUBY_ENGINE == "jruby"
75+
def type_casted_binds(event)
76+
event.payload[:type_casted_binds].call
77+
end
78+
else
79+
def type_casted_binds(event)
80+
event.payload[:type_casted_binds]
81+
end
82+
end
83+
6384
private
6485

6586
def build_log_message(statement_name)

sentry-rails/spec/dummy/test_rails_app/apps/5-2.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
end
3131

3232
create_table :posts, force: true do |t|
33+
t.string :title
34+
t.timestamps
3335
end
3436

3537
create_table :comments, force: true do |t|

sentry-rails/spec/dummy/test_rails_app/apps/6-0.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
end
3131

3232
create_table :posts, force: true do |t|
33+
t.string :title
34+
t.timestamps
3335
end
3436

3537
create_table :comments, force: true do |t|

sentry-rails/spec/dummy/test_rails_app/apps/6-1.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
end
3131

3232
create_table :posts, force: true do |t|
33+
t.string :title
34+
t.timestamps
3335
end
3436

3537
create_table :comments, force: true do |t|

sentry-rails/spec/dummy/test_rails_app/apps/7-0.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
end
3131

3232
create_table :posts, force: true do |t|
33+
t.string :title
34+
t.timestamps
3335
end
3436

3537
create_table :comments, force: true do |t|

sentry-rails/spec/dummy/test_rails_app/apps/7-1.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
end
3131

3232
create_table :posts, force: true do |t|
33+
t.string :title
34+
t.timestamps
3335
end
3436

3537
create_table :comments, force: true do |t|

sentry-rails/spec/sentry/rails/log_subscribers/active_record_subscriber_spec.rb

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
config.rails.structured_logging.subscribers = { active_record: Sentry::Rails::LogSubscribers::ActiveRecordSubscriber }
1313
end
1414
end
15+
1516
describe "integration with ActiveSupport::Notifications" do
1617
it "logs SQL events when database queries are executed" do
1718
Post.create!
@@ -45,6 +46,62 @@
4546
expect(log_event[:attributes][:sql][:value]).to include("posts")
4647
end
4748

49+
context "when send_default_pii is enabled" do
50+
before do
51+
Sentry.configuration.send_default_pii = true
52+
end
53+
54+
after do
55+
Sentry.configuration.send_default_pii = false
56+
end
57+
58+
it "logs SELECT queries with binds in attributes" do
59+
post = Post.create!(title: "test")
60+
61+
Sentry.get_current_client.flush
62+
sentry_transport.events.clear
63+
sentry_transport.envelopes.clear
64+
65+
created_at = Time.new(2025, 10, 28, 13, 11, 44)
66+
Post.where(id: post.id, title: post.title, created_at: created_at).to_a
67+
68+
Sentry.get_current_client.flush
69+
70+
log_event = sentry_logs.find { |log| log[:body]&.include?("Database query") }
71+
expect(log_event).not_to be_nil
72+
73+
# Follow Sentry convention: db.query.parameter.<key> with string values
74+
expect(log_event[:attributes]["db.query.parameter.id"][:value]).to eq(post.id.to_s)
75+
expect(log_event[:attributes]["db.query.parameter.id"][:type]).to eql("string")
76+
77+
expect(log_event[:attributes]["db.query.parameter.title"][:value]).to eql(post.title)
78+
expect(log_event[:attributes]["db.query.parameter.title"][:type]).to eql("string")
79+
80+
expect(log_event[:attributes]["db.query.parameter.created_at"][:value]).to include("2025-10-28 13:11:44")
81+
expect(log_event[:attributes]["db.query.parameter.created_at"][:type]).to eql("string")
82+
end
83+
end
84+
85+
context "when send_default_pii is disabled" do
86+
it "logs SELECT queries without binds in attributes" do
87+
post = Post.create!(title: "test")
88+
89+
Sentry.get_current_client.flush
90+
sentry_transport.events.clear
91+
sentry_transport.envelopes.clear
92+
93+
Post.where(id: post.id, title: post.title).to_a
94+
95+
Sentry.get_current_client.flush
96+
97+
log_event = sentry_logs.find { |log| log[:body]&.include?("Database query") }
98+
expect(log_event).not_to be_nil
99+
100+
expect(log_event[:attributes]["db.query.parameter.id"]).to be_nil
101+
expect(log_event[:attributes]["db.query.parameter.title"]).to be_nil
102+
end
103+
end
104+
48105
if Rails.version.to_f > 5.1
49106
it "excludes SCHEMA events" do
50107
ActiveSupport::Notifications.instrument("sql.active_record",

0 commit comments

Comments
 (0)