Skip to content

Commit bebb667

Browse files
committed
fix(web): enforce opt-in sentry log forwarding
1 parent 1934b7d commit bebb667

5 files changed

Lines changed: 52 additions & 10 deletions

File tree

app/web/telemetry/app_logger.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def build_logger
3636
# @return [String]
3737
def format_entry(severity, datetime, _progname, message)
3838
payload = base_payload(severity, datetime).merge(normalize_message(message))
39-
SentryLogs.emit(payload)
39+
emit_to_sentry(payload)
4040
"#{payload.to_json}\n"
4141
end
4242

@@ -97,6 +97,14 @@ def normalize_logfmt_value(raw_value)
9797

9898
value
9999
end
100+
101+
# @param payload [Hash{Symbol=>Object}]
102+
# @return [void]
103+
def emit_to_sentry(payload)
104+
SentryLogs.emit(payload)
105+
rescue StandardError
106+
nil
107+
end
100108
end
101109
end
102110
end

app/web/telemetry/sentry_logs.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ def emit(payload)
2424

2525
# @return [Boolean]
2626
def enabled?
27-
RuntimeEnv.sentry_enabled? && defined?(::Sentry) && !logger.nil?
27+
RuntimeEnv.sentry_enabled? &&
28+
RuntimeEnv.sentry_logs_enabled? &&
29+
defined?(::Sentry) &&
30+
!logger.nil?
2831
end
2932

3033
# @return [Object, nil]

spec/html2rss/web/app_logger_spec.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# frozen_string_literal: true
22

33
require 'spec_helper'
4-
require 'climate_control'
54
require 'stringio'
65

76
require_relative '../../../app/web/config/runtime_env'
@@ -25,5 +24,16 @@
2524
)
2625
expect(io.string).to include('"event_name":"boot.test"')
2726
end
27+
28+
it 'still writes structured logs when the Sentry bridge raises' do
29+
allow(Logger).to receive(:new).and_return(test_logger)
30+
allow(Html2rss::Web::SentryLogs).to receive(:emit).and_raise(StandardError, 'boom')
31+
32+
described_class.reset_logger!
33+
expect do
34+
described_class.logger.info({ event_name: 'boot.test', component: 'boot' }.to_json)
35+
end.not_to raise_error
36+
expect(io.string).to include('"event_name":"boot.test"')
37+
end
2838
end
2939
end

spec/html2rss/web/boot/setup_spec.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,13 @@
4747
end
4848

4949
it 'captures and scrubs sensitive env vars after validation', :aggregate_failures do
50-
stub_environment_validation
50+
allow(Html2rss::Web::EnvironmentValidator).to receive(:validate_environment!).ordered do
51+
expect(ENV.fetch('HTML2RSS_SECRET_KEY', nil)).to eq(boot_secret_key)
52+
expect(ENV.fetch('HEALTH_CHECK_TOKEN', nil)).to eq('health-token')
53+
end
54+
allow(Html2rss::Web::EnvironmentValidator).to receive(:validate_production_security!).ordered do
55+
expect(ENV.fetch('SENTRY_DSN', nil)).to eq(sentry_dsn)
56+
end
5157

5258
ClimateControl.modify(scrubbed_env) do
5359
described_class.call!

spec/html2rss/web/sentry_logs_spec.rb

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,30 @@
2929

3030
it 'filters auth and security pii before forwarding payloads to Sentry', :aggregate_failures do
3131
stub_const('Sentry', fake_sentry)
32-
allow(described_class).to receive_messages(enabled?: true, logger: sentry_logger)
33-
32+
allow(Html2rss::Web::RuntimeEnv).to receive_messages(sentry_enabled?: true, sentry_logs_enabled?: true)
33+
allow(described_class).to receive(:logger).and_return(sentry_logger)
34+
expect(described_class.send(:enabled?)).to be(true)
3435
described_class.emit(raw_payload)
3536

3637
expect_forwarded_payload
3738
end
3839

40+
it 'does not forward payloads when sentry logs are disabled' do
41+
stub_const('Sentry', fake_sentry)
42+
allow(Html2rss::Web::RuntimeEnv).to receive_messages(sentry_enabled?: true, sentry_logs_enabled?: false)
43+
described_class.emit(raw_payload)
44+
45+
expect(captured_call).to eq({})
46+
end
47+
48+
it 'does not forward payloads when sentry is disabled' do
49+
stub_const('Sentry', fake_sentry)
50+
allow(Html2rss::Web::RuntimeEnv).to receive_messages(sentry_enabled?: false, sentry_logs_enabled?: true)
51+
described_class.emit(raw_payload)
52+
53+
expect(captured_call).to eq({})
54+
end
55+
3956
def build_sentry_logger
4057
logger_class = Struct.new(:captured_call) do
4158
def info(message, **attributes)
@@ -44,13 +61,11 @@ def info(message, **attributes)
4461
end
4562
end
4663

47-
logger_class.new(captured_call).tap do |logger|
48-
allow(logger).to receive(:info).and_call_original
49-
end
64+
logger_class.new(captured_call)
5065
end
5166

5267
def expect_forwarded_payload
53-
expect(sentry_logger).to have_received(:info)
68+
expect(captured_call).to include(:message, :attributes)
5469
expect_forwarded_message
5570
expect_forwarded_attributes
5671
end

0 commit comments

Comments
 (0)