diff --git a/sentry-rails/lib/sentry/rails/active_job.rb b/sentry-rails/lib/sentry/rails/active_job.rb index c8108e7e9..fd00fbbb8 100644 --- a/sentry-rails/lib/sentry/rails/active_job.rb +++ b/sentry-rails/lib/sentry/rails/active_job.rb @@ -37,7 +37,7 @@ def serialize sentry_data["trace_propagation_headers"] = headers if headers && !headers.empty? end - if Sentry.configuration.send_default_pii + if Sentry.configuration.data_collection.user_info user = Sentry.get_current_scope.user allowed = user.transform_keys(&:to_s).slice(*USER_FIELDS_ALLOWLIST) sentry_data["user"] = allowed unless allowed.empty? diff --git a/sentry-rails/spec/active_job/shared_examples/tracing/user_propagation.rb b/sentry-rails/spec/active_job/shared_examples/tracing/user_propagation.rb index 52dd9df5e..5c8ffeed9 100644 --- a/sentry-rails/spec/active_job/shared_examples/tracing/user_propagation.rb +++ b/sentry-rails/spec/active_job/shared_examples/tracing/user_propagation.rb @@ -113,4 +113,52 @@ def perform expect(consumer_transaction.user).to eq({}) end end + + context "data collection" do + context "when user_info is enabled" do + let(:configure_sentry) do + proc do |config| + config.traces_sample_rate = 1.0 + config.data_collection.user_info = true + end + end + + it "propagates user context to the consumer transaction" do + Sentry.set_user(full_user) + + successful_job.perform_later + Sentry.set_user({}) + + drain + + expect(consumer_transaction).not_to be_nil + expect(consumer_transaction.user).to eq( + id: "u1", + email: "alice@example.com", + username: "alice" + ) + end + end + + context "when user_info is disabled" do + let(:configure_sentry) do + proc do |config| + config.traces_sample_rate = 1.0 + config.data_collection.user_info = false + end + end + + it "does not propagate user context to the consumer transaction" do + Sentry.set_user(full_user) + + successful_job.perform_later + Sentry.set_user({}) + + drain + + expect(consumer_transaction).not_to be_nil + expect(consumer_transaction.user).to eq({}) + end + end + end end diff --git a/sentry-ruby/lib/sentry/event.rb b/sentry-ruby/lib/sentry/event.rb index 09db52f1f..785df8e5b 100644 --- a/sentry-ruby/lib/sentry/event.rb +++ b/sentry-ruby/lib/sentry/event.rb @@ -28,7 +28,7 @@ class Event MAX_MESSAGE_SIZE_IN_BYTES = 1024 * 8 - SKIP_INSPECTION_ATTRIBUTES = [:@modules, :@stacktrace_builder, :@send_default_pii, :@trusted_proxies, :@rack_env_whitelist] + SKIP_INSPECTION_ATTRIBUTES = [:@modules, :@stacktrace_builder, :@send_default_pii, :@data_collection, :@trusted_proxies, :@rack_env_whitelist] include CustomInspection @@ -74,6 +74,7 @@ def initialize(configuration:, integration_meta: nil, message: nil) # configuration options to help events process data @send_default_pii = configuration.send_default_pii + @data_collection = configuration.data_collection @trusted_proxies = configuration.trusted_proxies @stacktrace_builder = configuration.stacktrace_builder @rack_env_whitelist = configuration.rack_env_whitelist @@ -103,7 +104,7 @@ def rack_env=(env) unless request || env.empty? add_request_interface(env) - user[:ip_address] ||= calculate_real_ip_from_rack(env) if @send_default_pii + user[:ip_address] ||= calculate_real_ip_from_rack(env) if @data_collection.user_info if request_id = Utils::RequestId.read_from(env) tags[:request_id] = request_id diff --git a/sentry-ruby/spec/sentry/event_spec.rb b/sentry-ruby/spec/sentry/event_spec.rb index 0f00ced00..08a60335f 100644 --- a/sentry-ruby/spec/sentry/event_spec.rb +++ b/sentry-ruby/spec/sentry/event_spec.rb @@ -170,6 +170,30 @@ end end end + + context "data collection" do + it "does not auto-populate user information when user_info is disabled" do + Sentry.configuration.data_collection.user_info = false + Sentry.get_current_scope.apply_to_event(event) + + expect(event.to_h[:user][:ip_address]).to be_nil + end + + it "auto-populates user information when user_info is enabled" do + Sentry.configuration.data_collection.user_info = true + Sentry.get_current_scope.apply_to_event(event) + + expect(event.to_h[:user][:ip_address]).to eq("2.2.2.2") + end + + it "preserves explicitly set user data set on the scope even when user_info is disabled" do + Sentry.configuration.data_collection.user_info = false + Sentry.set_user(id: "user-1", username: "alice") + Sentry.get_current_scope.apply_to_event(event) + + expect(event.to_h[:user]).to include(id: "user-1", username: "alice") + end + end end describe '#to_json_compatible' do diff --git a/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb b/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb index c1fb4b6b1..8a06b38d5 100644 --- a/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb +++ b/sentry-sidekiq/lib/sentry/sidekiq/sentry_context_middleware.rb @@ -108,8 +108,10 @@ class SentryContextClientMiddleware def call(worker_class, job, queue, _redis_pool) return yield unless Sentry.initialized? - user = Sentry.get_current_scope.user - job["sentry_user"] = user unless user.empty? + if Sentry.configuration.data_collection.user_info + user = Sentry.get_current_scope.user + job["sentry_user"] = user unless user.empty? + end if Sentry.configuration.sidekiq.propagate_traces job["trace_propagation_headers"] ||= Sentry.get_trace_propagation_headers diff --git a/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb b/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb index 85bb9e3fd..c1b1a4b62 100644 --- a/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb +++ b/sentry-sidekiq/spec/sentry/sidekiq/sentry_context_middleware_spec.rb @@ -168,17 +168,26 @@ def ensure_queue_empty(queue, timeout: 0.1) expect(queue.first["sentry_user"]).to be_nil end - describe "with user" do + context "user data collection" do before do Sentry.set_user(user) end - it "sets user of the current scope to the job" do + it "propagates user information when user_info is enabled" do + Sentry.configuration.data_collection.user_info = true + client.push('queue' => 'default', 'class' => HappyWorker, 'args' => []) - expect(queue.size).to be(1) expect(queue.first["sentry_user"]).to eq(user) end + + it "does not propagate user information when user_info is disabled" do + Sentry.configuration.data_collection.user_info = false + + client.push('queue' => 'default', 'class' => HappyWorker, 'args' => []) + + expect(queue.first["sentry_user"]).to be_nil + end end describe "with transaction" do