Skip to content

Commit a5cee1b

Browse files
authored
fix(rails): handle positioned binds in logging (#2787)
* fix(rails): handle positioned binds in logging Fixes #2786 * Update CHANGELOG
1 parent 17d6e49 commit a5cee1b

File tree

3 files changed

+77
-3
lines changed

3 files changed

+77
-3
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+
### Fixes
4+
5+
- Handle positioned binds in logging ([#2787](https://github.com/getsentry/sentry-ruby/pull/2787))
6+
17
## 6.1.1
28

39
### Improvements

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,14 @@ def sql(event)
5050

5151
binds = event.payload[:binds]
5252

53-
if Sentry.configuration.send_default_pii && !binds&.empty?
53+
if Sentry.configuration.send_default_pii && binds&.any?
5454
type_casted_binds = type_casted_binds(event)
5555

5656
binds.each_with_index do |bind, index|
57-
name = bind.is_a?(Symbol) ? bind : bind.name
58-
attributes["db.query.parameter.#{name}"] = type_casted_binds[index].to_s
57+
key = bind.respond_to?(:name) ? bind.name : index.to_s
58+
value = type_casted_binds[index].to_s
59+
60+
attributes["db.query.parameter.#{key}"] = value
5961
end
6062
end
6163

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

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,72 @@
8080
expect(log_event[:attributes]["db.query.parameter.created_at"][:value]).to include("2025-10-28 13:11:44")
8181
expect(log_event[:attributes]["db.query.parameter.created_at"][:type]).to eql("string")
8282
end
83+
84+
it "logs queries with positional (unnamed) binds", skip: RAILS_VERSION >= 8.0 do
85+
Sentry.get_current_client.flush
86+
sentry_transport.events.clear
87+
sentry_transport.envelopes.clear
88+
89+
Post.where("id = ? AND title = ?", 1, "Hello World").first
90+
91+
Sentry.get_current_client.flush
92+
93+
log_event = sentry_logs.find { |log| log[:body]&.include?("Database query") }
94+
expect(log_event).not_to be_nil
95+
end
96+
97+
it "logs queries with positional (unnamed) binds", skip: RAILS_VERSION < 8.0 do
98+
Sentry.get_current_client.flush
99+
sentry_transport.events.clear
100+
sentry_transport.envelopes.clear
101+
102+
Post.where("id = ? AND title = ?", 1, "Hello World").first
103+
104+
Sentry.get_current_client.flush
105+
106+
log_event = sentry_logs.find { |log| log[:body]&.include?("Database query") }
107+
expect(log_event).not_to be_nil
108+
109+
expect(log_event[:attributes]["db.query.parameter.0"][:value]).to eq("1")
110+
expect(log_event[:attributes]["db.query.parameter.1"][:value]).to eq("Hello World")
111+
end
112+
113+
it "handles nil binds gracefully" do
114+
Sentry.get_current_client.flush
115+
sentry_transport.events.clear
116+
sentry_transport.envelopes.clear
117+
118+
# In theory, this should never happened
119+
ActiveSupport::Notifications.instrument("sql.active_record",
120+
sql: "SELECT 1",
121+
name: "SQL",
122+
connection: ActiveRecord::Base.connection,
123+
binds: nil
124+
)
125+
126+
Sentry.get_current_client.flush
127+
128+
log_event = sentry_logs.find { |log| log[:attributes]&.dig(:sql, :value) == "SELECT 1" }
129+
expect(log_event).not_to be_nil
130+
expect(log_event[:attributes][:sql][:value]).to eq("SELECT 1")
131+
end
132+
133+
it "when binds are empty array" do
134+
Sentry.get_current_client.flush
135+
sentry_transport.events.clear
136+
sentry_transport.envelopes.clear
137+
138+
Post.connection.execute("SELECT posts.* FROM posts")
139+
140+
Sentry.get_current_client.flush
141+
142+
log_event = sentry_logs.find { |log|
143+
log[:attributes].dig(:sql, :value).include?("SELECT") &&
144+
log[:attributes].dig(:sql, :value).include?("posts")
145+
}
146+
147+
expect(log_event).not_to be_nil
148+
end
83149
end
84150

85151
context "when send_default_pii is disabled" do

0 commit comments

Comments
 (0)