Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### Features

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

### Bug Fixes

Expand Down
30 changes: 29 additions & 1 deletion sentry-ruby/lib/sentry/log_event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,15 @@ class LogEvent
"sentry.message.template" => :template
}

USER_ATTRIBUTES = {
"user.id" => :user_id,
"user.name" => :user_username,
"user.email" => :user_email
}

LEVELS = %i[trace debug info warn error fatal].freeze

attr_accessor :level, :body, :template, :attributes
attr_accessor :level, :body, :template, :attributes, :user

attr_reader :configuration, *SERIALIZEABLE_ATTRIBUTES

Expand All @@ -47,6 +53,9 @@ class LogEvent
sdk_version
timestamp
trace_id
user_id
user_username
user_email
].map { |name| [name, :"serialize_#{name}"] }.to_h

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

Expand Down Expand Up @@ -124,6 +134,18 @@ def serialize_body
end
end

def serialize_user_id
user[:id]
end

def serialize_user_username
user[:username]
end

def serialize_user_email
user[:email]
end

def serialize_attributes
hash = {}

Expand All @@ -137,6 +159,12 @@ def serialize_attributes
end
end

USER_ATTRIBUTES.each do |key, name|
if (value = serialize(name))
hash[key] = value
end
end

hash
end

Expand Down
4 changes: 4 additions & 0 deletions sentry-ruby/lib/sentry/scope.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ def apply_to_event(event, hint = nil)
event.attachments = attachments
end

if event.is_a?(LogEvent)
event.user = user.merge(event.user)
end

if span
event.contexts[:trace] ||= span.get_trace_context

Expand Down
21 changes: 21 additions & 0 deletions sentry-ruby/spec/sentry/log_event_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,26 @@
expect(hash[:attributes]["boolean_attr"]).to eq({ value: true, type: "boolean" })
expect(hash[:attributes]["float_attr"]).to eq({ value: 3.14, type: "double" })
end

it "serializes user attributes correctly" do
user = {
id: 123,
username: "john_doe",
email: "john@example.com"
}

event = described_class.new(
configuration: configuration,
level: :info,
body: "User action performed",
user: user
)

hash = event.to_hash

expect(hash[:attributes]["user.id"]).to eq(123)
expect(hash[:attributes]["user.name"]).to eq("john_doe")
expect(hash[:attributes]["user.email"]).to eq("john@example.com")
end
end
end
27 changes: 27 additions & 0 deletions sentry-ruby/spec/sentry/scope_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@

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

it "applies the contextual data to event" do
subject.apply_to_event(event)
Expand Down Expand Up @@ -238,6 +239,32 @@
expect(check_in_event.contexts).to include(:trace)
end

context "with LogEvent" do
it "adds user attributes to log event" do
scope = described_class.new
scope.set_user({ id: 123, username: "john_doe", email: "john@example.com" })

scope.apply_to_event(log_event)

log_hash = log_event.to_hash

expect(log_hash[:attributes]["user.id"]).to eq(123)
expect(log_hash[:attributes]["user.name"]).to eq("john_doe")
expect(log_hash[:attributes]["user.email"]).to eq("john@example.com")
end

it "does not add user attributes when user is empty" do
scope = described_class.new
scope.apply_to_event(log_event)

log_hash = log_event.to_hash

expect(log_hash[:attributes]).not_to have_key("user.id")
expect(log_hash[:attributes]).not_to have_key("user.name")
expect(log_hash[:attributes]).not_to have_key("user.email")
end
end

it "doesn't override event's pre-existing data" do
event.tags = { foo: "baz" }
event.user = { id: 2 }
Expand Down
Loading