Skip to content

Commit 6b41b9c

Browse files
authored
Add user attributes to logs (#2647)
* Include default user attributes in logs * Update CHANGELOG
1 parent e126f72 commit 6b41b9c

File tree

5 files changed

+82
-1
lines changed

5 files changed

+82
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
### Features
44

55
- Support for `before_send_log` ([#2634](https://github.com/getsentry/sentry-ruby/pull/2634))
6+
- Default user attributes are now automatically added to logs ([#2647](https://github.com/getsentry/sentry-ruby/pull/2647))
67

78
### Bug Fixes
89

sentry-ruby/lib/sentry/log_event.rb

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,15 @@ class LogEvent
3232
"sentry.message.template" => :template
3333
}
3434

35+
USER_ATTRIBUTES = {
36+
"user.id" => :user_id,
37+
"user.name" => :user_username,
38+
"user.email" => :user_email
39+
}
40+
3541
LEVELS = %i[trace debug info warn error fatal].freeze
3642

37-
attr_accessor :level, :body, :template, :attributes
43+
attr_accessor :level, :body, :template, :attributes, :user
3844

3945
attr_reader :configuration, *SERIALIZEABLE_ATTRIBUTES
4046

@@ -47,6 +53,9 @@ class LogEvent
4753
sdk_version
4854
timestamp
4955
trace_id
56+
user_id
57+
user_username
58+
user_email
5059
].map { |name| [name, :"serialize_#{name}"] }.to_h
5160

5261
VALUE_TYPES = Hash.new("string").merge!({
@@ -69,6 +78,7 @@ def initialize(configuration: Sentry.configuration, **options)
6978
@body = options[:body]
7079
@template = @body if is_template?
7180
@attributes = options[:attributes] || DEFAULT_ATTRIBUTES
81+
@user = options[:user] || {}
7282
@contexts = {}
7383
end
7484

@@ -124,6 +134,18 @@ def serialize_body
124134
end
125135
end
126136

137+
def serialize_user_id
138+
user[:id]
139+
end
140+
141+
def serialize_user_username
142+
user[:username]
143+
end
144+
145+
def serialize_user_email
146+
user[:email]
147+
end
148+
127149
def serialize_attributes
128150
hash = {}
129151

@@ -137,6 +159,12 @@ def serialize_attributes
137159
end
138160
end
139161

162+
USER_ATTRIBUTES.each do |key, name|
163+
if (value = serialize(name))
164+
hash[key] = value
165+
end
166+
end
167+
140168
hash
141169
end
142170

sentry-ruby/lib/sentry/scope.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ def apply_to_event(event, hint = nil)
6060
event.attachments = attachments
6161
end
6262

63+
if event.is_a?(LogEvent)
64+
event.user = user.merge(event.user)
65+
end
66+
6367
if span
6468
event.contexts[:trace] ||= span.get_trace_context
6569

sentry-ruby/spec/sentry/log_event_spec.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,26 @@
118118
expect(hash[:attributes]["boolean_attr"]).to eq({ value: true, type: "boolean" })
119119
expect(hash[:attributes]["float_attr"]).to eq({ value: 3.14, type: "double" })
120120
end
121+
122+
it "serializes user attributes correctly" do
123+
user = {
124+
id: 123,
125+
username: "john_doe",
126+
127+
}
128+
129+
event = described_class.new(
130+
configuration: configuration,
131+
level: :info,
132+
body: "User action performed",
133+
user: user
134+
)
135+
136+
hash = event.to_hash
137+
138+
expect(hash[:attributes]["user.id"]).to eq(123)
139+
expect(hash[:attributes]["user.name"]).to eq("john_doe")
140+
expect(hash[:attributes]["user.email"]).to eq("[email protected]")
141+
end
121142
end
122143
end

sentry-ruby/spec/sentry/scope_spec.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@
207207

208208
let(:event) { client.event_from_message("test message") }
209209
let(:check_in_event) { client.event_from_check_in("test_slug", :ok) }
210+
let(:log_event) { client.event_from_log("test log message", level: :info) }
210211

211212
it "applies the contextual data to event" do
212213
subject.apply_to_event(event)
@@ -238,6 +239,32 @@
238239
expect(check_in_event.contexts).to include(:trace)
239240
end
240241

242+
context "with LogEvent" do
243+
it "adds user attributes to log event" do
244+
scope = described_class.new
245+
scope.set_user({ id: 123, username: "john_doe", email: "[email protected]" })
246+
247+
scope.apply_to_event(log_event)
248+
249+
log_hash = log_event.to_hash
250+
251+
expect(log_hash[:attributes]["user.id"]).to eq(123)
252+
expect(log_hash[:attributes]["user.name"]).to eq("john_doe")
253+
expect(log_hash[:attributes]["user.email"]).to eq("[email protected]")
254+
end
255+
256+
it "does not add user attributes when user is empty" do
257+
scope = described_class.new
258+
scope.apply_to_event(log_event)
259+
260+
log_hash = log_event.to_hash
261+
262+
expect(log_hash[:attributes]).not_to have_key("user.id")
263+
expect(log_hash[:attributes]).not_to have_key("user.name")
264+
expect(log_hash[:attributes]).not_to have_key("user.email")
265+
end
266+
end
267+
241268
it "doesn't override event's pre-existing data" do
242269
event.tags = { foo: "baz" }
243270
event.user = { id: 2 }

0 commit comments

Comments
 (0)