My opinionated ruby on rails template
1# frozen_string_literal: true
2
3say 'Setting up structured logging...', :green
4
5gem 'lograge'
6gem 'logstop'
7
8say ' Creating Lograge initializer...', :cyan
9initializer 'lograge.rb', <<~RUBY
10 # frozen_string_literal: true
11
12 return unless defined?(Lograge)
13
14 Rails.application.configure do
15 # Enable lograge for structured logging
16 config.lograge.enabled = true
17
18 # Use JSON format in production for log aggregation
19 config.lograge.formatter = if Rails.env.production?
20 Lograge::Formatters::Json.new
21 else
22 Lograge::Formatters::KeyValue.new
23 end
24
25 # Include request_id for tracing across services
26 config.lograge.custom_options = lambda do |event|
27 {
28 request_id: event.payload[:request_id],
29 user_id: event.payload[:user_id],
30 ip: event.payload[:ip],
31 host: event.payload[:host]
32 }.compact
33 end
34
35 # Add custom data to the payload
36 config.lograge.custom_payload do |controller|
37 {
38 request_id: controller.request.request_id,
39 user_id: controller.try(:current_user)&.id,
40 ip: controller.request.remote_ip,
41 host: controller.request.host
42 }
43 end
44
45 # Keep original Rails logs in development
46 config.lograge.keep_original_rails_log = Rails.env.development?
47 end
48RUBY
49
50say ' Creating Logstop initializer...', :cyan
51initializer 'logstop.rb', <<~RUBY
52 # frozen_string_literal: true
53
54 # Logstop filters sensitive data from logs
55 # By default it filters: email, phone, credit card, SSN, IP addresses
56
57 if defined?(Logstop)
58 Logstop.guard(Rails.logger)
59
60 # Add custom scrubbers for application-specific sensitive data
61 # Logstop.scrub(pattern, replacement)
62 #
63 # Example: Scrub API keys
64 # Logstop.scrub(/api_key=\\w+/, 'api_key=[FILTERED]')
65 end
66RUBY
67
68say 'Structured logging configured!', :green
69say ' Logs include request_id for tracing', :cyan
70say ' PII is automatically filtered by Logstop', :cyan