Gate Sentry on SENTRY_DSN presence
ENV.fetch("SENTRY_DSN") crashed without the var set.
Consolidate env reading into Config with a nested Sentry object.

Assisted-by: Claude Opus 4.6 via Claude Code
change yqyvyvyoyklnwuqwlwtssqtqluzkwuvx
commit bb68ff2afa16e45a9d13db85d2707e06cbec1d73
author Alpha Chen <alpha@kejadlen.dev>
date
parent qtyylrpl
diff --git a/config.ru b/config.ru
index fed2e93..2da94df 100644
--- a/config.ru
+++ b/config.ru
@@ -1,19 +1,19 @@
 # frozen_string_literal: true
 
-require "sentry-ruby"
-
-Sentry.init do |config|
-  config.dsn = ENV.fetch("SENTRY_DSN")
-
-  # Add data like request headers and IP for users,
-  # see https://docs.sentry.io/platforms/ruby/data-management/data-collected/ for more info
-  config.send_default_pii = true
-end
-
 $LOAD_PATH.unshift(File.expand_path("lib", __dir__))
 
 require_relative "lib/ketchup/web"
 
-use Sentry::Rack::CaptureExceptions
+if CONFIG.sentry
+  require "sentry-ruby"
+
+  Sentry.init do |config|
+    config.dsn = CONFIG.sentry.dsn
+    config.environment = CONFIG.sentry.env if CONFIG.sentry.env
+    config.send_default_pii = true
+  end
+
+  use Sentry::Rack::CaptureExceptions
+end
 
 run Web.freeze.app
diff --git a/lib/ketchup/config.rb b/lib/ketchup/config.rb
index d94de88..fa8f901 100644
--- a/lib/ketchup/config.rb
+++ b/lib/ketchup/config.rb
@@ -1,9 +1,13 @@
 # frozen_string_literal: true
 
-Config = Data.define(:database_url) do
+Config = Data.define(:database_url, :sentry) do
+  SentryConfig = Data.define(:dsn, :env)
+
   def self.from_env(env = ENV)
+    sentry_dsn = env["SENTRY_DSN"]
     new(
-      database_url: env.fetch("DATABASE_URL") { "db/ketchup.db" }
+      database_url: env.fetch("DATABASE_URL") { "db/ketchup.db" },
+      sentry: sentry_dsn ? SentryConfig.new(dsn: sentry_dsn, env: env["SENTRY_ENV"]) : nil
     )
   end
 end