honeybadger 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. data/Gemfile +13 -0
  2. data/Gemfile.lock +114 -0
  3. data/Guardfile +5 -0
  4. data/MIT-LICENSE +22 -0
  5. data/README.md +271 -0
  6. data/Rakefile +261 -0
  7. data/SUPPORTED_RAILS_VERSIONS +26 -0
  8. data/TESTING.md +33 -0
  9. data/features/metal.feature +18 -0
  10. data/features/rack.feature +56 -0
  11. data/features/rails.feature +211 -0
  12. data/features/rake.feature +27 -0
  13. data/features/sinatra.feature +29 -0
  14. data/features/step_definitions/file_steps.rb +10 -0
  15. data/features/step_definitions/metal_steps.rb +23 -0
  16. data/features/step_definitions/rack_steps.rb +23 -0
  17. data/features/step_definitions/rails_application_steps.rb +394 -0
  18. data/features/step_definitions/rake_steps.rb +17 -0
  19. data/features/support/env.rb +17 -0
  20. data/features/support/honeybadger_shim.rb.template +8 -0
  21. data/features/support/rails.rb +201 -0
  22. data/features/support/rake/Rakefile +68 -0
  23. data/features/support/terminal.rb +107 -0
  24. data/generators/honeybadger/honeybadger_generator.rb +94 -0
  25. data/generators/honeybadger/lib/insert_commands.rb +34 -0
  26. data/generators/honeybadger/lib/rake_commands.rb +24 -0
  27. data/generators/honeybadger/templates/capistrano_hook.rb +6 -0
  28. data/generators/honeybadger/templates/honeybadger_tasks.rake +25 -0
  29. data/generators/honeybadger/templates/initializer.rb +6 -0
  30. data/honeybadger.gemspec +109 -0
  31. data/lib/honeybadger.rb +162 -0
  32. data/lib/honeybadger/backtrace.rb +123 -0
  33. data/lib/honeybadger/capistrano.rb +43 -0
  34. data/lib/honeybadger/configuration.rb +273 -0
  35. data/lib/honeybadger/notice.rb +314 -0
  36. data/lib/honeybadger/rack.rb +55 -0
  37. data/lib/honeybadger/rails.rb +34 -0
  38. data/lib/honeybadger/rails/action_controller_catcher.rb +30 -0
  39. data/lib/honeybadger/rails/controller_methods.rb +69 -0
  40. data/lib/honeybadger/rails/middleware/exceptions_catcher.rb +29 -0
  41. data/lib/honeybadger/rails3_tasks.rb +84 -0
  42. data/lib/honeybadger/railtie.rb +45 -0
  43. data/lib/honeybadger/rake_handler.rb +65 -0
  44. data/lib/honeybadger/sender.rb +120 -0
  45. data/lib/honeybadger/shared_tasks.rb +36 -0
  46. data/lib/honeybadger/tasks.rb +82 -0
  47. data/lib/honeybadger_tasks.rb +65 -0
  48. data/lib/rails/generators/honeybadger/honeybadger_generator.rb +99 -0
  49. data/rails/init.rb +1 -0
  50. data/resources/README.md +34 -0
  51. data/resources/ca-bundle.crt +3376 -0
  52. data/script/integration_test.rb +38 -0
  53. data/test/test_helper.rb +143 -0
  54. data/test/unit/backtrace_test.rb +180 -0
  55. data/test/unit/capistrano_test.rb +34 -0
  56. data/test/unit/configuration_test.rb +201 -0
  57. data/test/unit/honeybadger_tasks_test.rb +163 -0
  58. data/test/unit/logger_test.rb +72 -0
  59. data/test/unit/notice_test.rb +406 -0
  60. data/test/unit/notifier_test.rb +245 -0
  61. data/test/unit/rack_test.rb +56 -0
  62. data/test/unit/rails/action_controller_catcher_test.rb +300 -0
  63. data/test/unit/rails_test.rb +35 -0
  64. data/test/unit/sender_test.rb +257 -0
  65. metadata +315 -0
@@ -0,0 +1,43 @@
1
+ # Defines deploy:notify_honeybadger which will send information about the deploy to Honeybadger.
2
+ require 'capistrano'
3
+
4
+ module Honeybadger
5
+ module Capistrano
6
+ def self.load_into(configuration)
7
+ configuration.load do
8
+ after "deploy", "honeybadger:deploy"
9
+ after "deploy:migrations", "honeybadger:deploy"
10
+
11
+ namespace :honeybadger do
12
+ desc <<-DESC
13
+ Notify Honeybadger of the deployment by running the notification on the REMOTE machine.
14
+ - Run remotely so we use remote API keys, environment, etc.
15
+ DESC
16
+ task :deploy, :except => { :no_release => true } do
17
+ rails_env = fetch(:rails_env, "production")
18
+ honeybadger_env = fetch(:honeybadger_env, fetch(:rails_env, "production"))
19
+ local_user = ENV['USER'] || ENV['USERNAME']
20
+ executable = RUBY_PLATFORM.downcase.include?('mswin') ? fetch(:rake, 'rake.bat') : fetch(:rake, 'rake')
21
+ directory = configuration.current_release
22
+ notify_command = "cd #{directory}; #{executable} RAILS_ENV=#{rails_env} honeybadger:deploy TO=#{honeybadger_env} REVISION=#{current_revision} REPO=#{repository} USER=#{local_user}"
23
+ notify_command << " DRY_RUN=true" if dry_run
24
+ notify_command << " API_KEY=#{ENV['API_KEY']}" if ENV['API_KEY']
25
+ logger.info "Notifying Honeybadger of Deploy (#{notify_command})"
26
+ if configuration.dry_run
27
+ logger.info "DRY RUN: Notification not actually run."
28
+ else
29
+ result = ""
30
+ run(notify_command, :once => true) { |ch, stream, data| result << data }
31
+ # TODO: Check if SSL is active on account via result content.
32
+ end
33
+ logger.info "Honeybadger Notification Complete."
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ if Capistrano::Configuration.instance
42
+ Honeybadger::Capistrano.load_into(Capistrano::Configuration.instance)
43
+ end
@@ -0,0 +1,273 @@
1
+ module Honeybadger
2
+ class Configuration
3
+ OPTIONS = [:api_key, :backtrace_filters, :development_environments, :environment_name,
4
+ :host, :http_open_timeout, :http_read_timeout, :ignore, :ignore_by_filters,
5
+ :ignore_user_agent, :notifier_name, :notifier_url, :notifier_version,
6
+ :params_filters, :project_root, :port, :protocol, :proxy_host, :proxy_pass,
7
+ :proxy_port, :proxy_user, :secure, :use_system_ssl_cert_chain, :framework,
8
+ :user_information, :rescue_rake_exceptions].freeze
9
+
10
+ # The API key for your project, found on the project edit form.
11
+ attr_accessor :api_key
12
+
13
+ # The host to connect to (defaults to honeybadger.io).
14
+ attr_accessor :host
15
+
16
+ # The port on which your Honeybadger server runs (defaults to 443 for secure
17
+ # connections, 80 for insecure connections).
18
+ attr_accessor :port
19
+
20
+ # +true+ for https connections, +false+ for http connections.
21
+ attr_accessor :secure
22
+
23
+ # +true+ to use whatever CAs OpenSSL has installed on your system. +false+ to use the ca-bundle.crt file included in Honeybadger itself (reccomended and default)
24
+ attr_accessor :use_system_ssl_cert_chain
25
+
26
+ # The HTTP open timeout in seconds (defaults to 2).
27
+ attr_accessor :http_open_timeout
28
+
29
+ # The HTTP read timeout in seconds (defaults to 5).
30
+ attr_accessor :http_read_timeout
31
+
32
+ # The hostname of your proxy server (if using a proxy)
33
+ attr_accessor :proxy_host
34
+
35
+ # The port of your proxy server (if using a proxy)
36
+ attr_accessor :proxy_port
37
+
38
+ # The username to use when logging into your proxy server (if using a proxy)
39
+ attr_accessor :proxy_user
40
+
41
+ # The password to use when logging into your proxy server (if using a proxy)
42
+ attr_accessor :proxy_pass
43
+
44
+ # A list of parameters that should be filtered out of what is sent to Honeybadger.
45
+ # By default, all "password" attributes will have their contents replaced.
46
+ attr_reader :params_filters
47
+
48
+ # A list of filters for cleaning and pruning the backtrace. See #filter_backtrace.
49
+ attr_reader :backtrace_filters
50
+
51
+ # A list of filters for ignoring exceptions. See #ignore_by_filter.
52
+ attr_reader :ignore_by_filters
53
+
54
+ # A list of exception classes to ignore. The array can be appended to.
55
+ attr_reader :ignore
56
+
57
+ # A list of user agents that are being ignored. The array can be appended to.
58
+ attr_reader :ignore_user_agent
59
+
60
+ # A list of environments in which notifications should not be sent.
61
+ attr_accessor :development_environments
62
+
63
+ # The name of the environment the application is running in
64
+ attr_accessor :environment_name
65
+
66
+ # The path to the project in which the error occurred, such as the Rails.root
67
+ attr_accessor :project_root
68
+
69
+ # The name of the notifier library being used to send notifications (such as "Honeybadger Notifier")
70
+ attr_accessor :notifier_name
71
+
72
+ # The version of the notifier library being used to send notifications (such as "1.0.2")
73
+ attr_accessor :notifier_version
74
+
75
+ # The url of the notifier library being used to send notifications
76
+ attr_accessor :notifier_url
77
+
78
+ # The logger used by Honeybadger
79
+ attr_accessor :logger
80
+
81
+ # The text that the placeholder is replaced with. {{error_id}} is the actual error number.
82
+ attr_accessor :user_information
83
+
84
+ # The framework Honeybadger is configured to use
85
+ attr_accessor :framework
86
+
87
+ # Should Honeybadger catch exceptions from Rake tasks?
88
+ # (boolean or nil; set to nil to catch exceptions when rake isn't running from a terminal; default is nil)
89
+ attr_accessor :rescue_rake_exceptions
90
+
91
+ DEFAULT_PARAMS_FILTERS = %w(password password_confirmation).freeze
92
+
93
+ DEFAULT_BACKTRACE_FILTERS = [
94
+ lambda { |line|
95
+ if defined?(Honeybadger.configuration.project_root) && Honeybadger.configuration.project_root.to_s != ''
96
+ line.sub(/#{Honeybadger.configuration.project_root}/, "[PROJECT_ROOT]")
97
+ else
98
+ line
99
+ end
100
+ },
101
+ lambda { |line| line.gsub(/^\.\//, "") },
102
+ lambda { |line|
103
+ if defined?(Gem)
104
+ Gem.path.inject(line) do |line, path|
105
+ line.gsub(/#{path}/, "[GEM_ROOT]")
106
+ end
107
+ end
108
+ },
109
+ lambda { |line| line if line !~ %r{lib/honeybadger} }
110
+ ].freeze
111
+
112
+ IGNORE_DEFAULT = ['ActiveRecord::RecordNotFound',
113
+ 'ActionController::RoutingError',
114
+ 'ActionController::InvalidAuthenticityToken',
115
+ 'CGI::Session::CookieStore::TamperedWithCookie',
116
+ 'ActionController::UnknownAction',
117
+ 'AbstractController::ActionNotFound',
118
+ 'Mongoid::Errors::DocumentNotFound']
119
+
120
+ alias_method :secure?, :secure
121
+ alias_method :use_system_ssl_cert_chain?, :use_system_ssl_cert_chain
122
+
123
+ def initialize
124
+ @secure = false
125
+ @use_system_ssl_cert_chain= false
126
+ @host = 'api.honeybadger.io'
127
+ @http_open_timeout = 2
128
+ @http_read_timeout = 5
129
+ @params_filters = DEFAULT_PARAMS_FILTERS.dup
130
+ @backtrace_filters = DEFAULT_BACKTRACE_FILTERS.dup
131
+ @ignore_by_filters = []
132
+ @ignore = IGNORE_DEFAULT.dup
133
+ @ignore_user_agent = []
134
+ @development_environments = %w(development test cucumber)
135
+ @notifier_name = 'Honeybadger Notifier'
136
+ @notifier_version = VERSION
137
+ @notifier_url = 'https://github.com/honeybadger/honeybadger'
138
+ @framework = 'Standalone'
139
+ @user_information = 'Honeybadger Error {{error_id}}'
140
+ @rescue_rake_exceptions = nil
141
+ end
142
+
143
+ # Public: Takes a block and adds it to the list of backtrace filters. When
144
+ # the filters run, the block will be handed each line of the backtrace and
145
+ # can modify it as necessary.
146
+ #
147
+ # &block - The new backtrace filter.
148
+ #
149
+ # Examples:
150
+ #
151
+ # config.filter_bracktrace do |line|
152
+ # line.gsub(/^#{Rails.root}/, "[Rails.root]")
153
+ # end
154
+ #
155
+ # Yields a line in the backtrace.
156
+ def filter_backtrace(&block)
157
+ self.backtrace_filters << block
158
+ end
159
+
160
+ # Public: Takes a block and adds it to the list of ignore filters. When
161
+ # the filters run, the block will be handed the exception.
162
+ #
163
+ # &block - The new ignore filter
164
+ # If the block returns true the exception will be ignored, otherwise it
165
+ # will be processed by honeybadger.
166
+ #
167
+ # Examples:
168
+ #
169
+ # config.ignore_by_filter do |exception_data|
170
+ # true if exception_data[:error_class] == "RuntimeError"
171
+ # end
172
+ #
173
+ # Yields the the exception data given to Honeybadger.notify
174
+ def ignore_by_filter(&block)
175
+ self.ignore_by_filters << block
176
+ end
177
+
178
+ # Public: Overrides the list of default ignored errors.
179
+ #
180
+ # names - A list of exceptions to ignore.
181
+ #
182
+ # Returns nothing
183
+ def ignore_only=(names)
184
+ @ignore = [names].flatten
185
+ end
186
+
187
+ # Public: Overrides the list of default ignored user agents
188
+ #
189
+ # names - A list of user agents to ignore
190
+ #
191
+ # Returns nothing
192
+ def ignore_user_agent_only=(names)
193
+ @ignore_user_agent = [names].flatten
194
+ end
195
+
196
+ # Public: Allows config options to be read like a hash
197
+ #
198
+ # option - Key for a given attribute
199
+ #
200
+ # Returns value of requested attribute
201
+ def [](option)
202
+ send(option)
203
+ end
204
+
205
+ # Public
206
+ # Returns a hash of all configurable options
207
+ def to_hash
208
+ OPTIONS.inject({}) do |hash, option|
209
+ hash[option.to_sym] = self.send(option)
210
+ hash
211
+ end
212
+ end
213
+
214
+ # Public
215
+ #
216
+ # hash - A set of configuration options that will take precedence over the defaults
217
+ #
218
+ # Returns a hash of all configurable options merged with +hash+
219
+ def merge(hash)
220
+ to_hash.merge(hash)
221
+ end
222
+
223
+ # Public: Determines if the notifier will send notices.
224
+ #
225
+ # Returns false if in a development environment, true otherwise.
226
+ def public?
227
+ !development_environments.include?(environment_name)
228
+ end
229
+
230
+ def port
231
+ @port || default_port
232
+ end
233
+
234
+ # Public: Determines whether protocol should be "http" or "https".
235
+ #
236
+ # Returns 'http' if you've set secure to false in
237
+ # configuration, and 'https' otherwise.
238
+ def protocol
239
+ if secure?
240
+ 'https'
241
+ else
242
+ 'http'
243
+ end
244
+ end
245
+
246
+ def ca_bundle_path
247
+ if use_system_ssl_cert_chain? && File.exist?(OpenSSL::X509::DEFAULT_CERT_FILE)
248
+ OpenSSL::X509::DEFAULT_CERT_FILE
249
+ else
250
+ local_cert_path # ca-bundle.crt built from source, see resources/README.md
251
+ end
252
+ end
253
+
254
+ def local_cert_path
255
+ File.expand_path(File.join("..", "..", "..", "resources", "ca-bundle.crt"), __FILE__)
256
+ end
257
+
258
+ private
259
+
260
+ # Private: Determines what port should we use for sending notices.
261
+ #
262
+ # Returns 443 if you've set secure to true in your
263
+ # configuration, and 80 otherwise.
264
+ def default_port
265
+ if secure?
266
+ 443
267
+ else
268
+ 80
269
+ end
270
+ end
271
+ end
272
+ end
273
+
@@ -0,0 +1,314 @@
1
+ require 'socket'
2
+
3
+ module Honeybadger
4
+ class Notice
5
+ # The exception that caused this notice, if any
6
+ attr_reader :exception
7
+
8
+ # The backtrace from the given exception or hash.
9
+ attr_reader :backtrace
10
+
11
+ # The name of the class of error (such as RuntimeError)
12
+ attr_reader :error_class
13
+
14
+ # The name of the server environment (such as "production")
15
+ attr_reader :environment_name
16
+
17
+ # CGI variables such as HTTP_METHOD
18
+ attr_reader :cgi_data
19
+
20
+ # The message from the exception, or a general description of the error
21
+ attr_reader :error_message
22
+
23
+ # See Configuration#backtrace_filters
24
+ attr_reader :backtrace_filters
25
+
26
+ # See Configuration#params_filters
27
+ attr_reader :params_filters
28
+
29
+ # A hash of parameters from the query string or post body.
30
+ attr_reader :parameters
31
+ alias_method :params, :parameters
32
+
33
+ # The component (if any) which was used in this request (usually the controller)
34
+ attr_reader :component
35
+ alias_method :controller, :component
36
+
37
+ # The action (if any) that was called in this request
38
+ attr_reader :action
39
+
40
+ # A hash of session data from the request
41
+ attr_reader :session_data
42
+
43
+ # The path to the project that caused the error (usually Rails.root)
44
+ attr_reader :project_root
45
+
46
+ # The URL at which the error occurred (if any)
47
+ attr_reader :url
48
+
49
+ # See Configuration#ignore
50
+ attr_reader :ignore
51
+
52
+ # See Configuration#ignore_by_filters
53
+ attr_reader :ignore_by_filters
54
+
55
+ # The name of the notifier library sending this notice, such as "Honeybadger Notifier"
56
+ attr_reader :notifier_name
57
+
58
+ # The version number of the notifier library sending this notice, such as "2.1.3"
59
+ attr_reader :notifier_version
60
+
61
+ # A URL for more information about the notifier library sending this notice
62
+ attr_reader :notifier_url
63
+
64
+ # The host name where this error occurred (if any)
65
+ attr_reader :hostname
66
+
67
+ def initialize(args)
68
+ self.args = args
69
+ self.exception = args[:exception]
70
+ self.project_root = args[:project_root]
71
+ self.url = args[:url] || rack_env(:url)
72
+
73
+ self.notifier_name = args[:notifier_name]
74
+ self.notifier_version = args[:notifier_version]
75
+ self.notifier_url = args[:notifier_url]
76
+
77
+ self.ignore = args[:ignore] || []
78
+ self.ignore_by_filters = args[:ignore_by_filters] || []
79
+ self.backtrace_filters = args[:backtrace_filters] || []
80
+ self.params_filters = args[:params_filters] || []
81
+ self.parameters = args[:parameters] ||
82
+ action_dispatch_params ||
83
+ rack_env(:params) ||
84
+ {}
85
+ self.component = args[:component] || args[:controller] || parameters['controller']
86
+ self.action = args[:action] || parameters['action']
87
+
88
+ self.environment_name = args[:environment_name]
89
+ self.cgi_data = args[:cgi_data] || args[:rack_env]
90
+ self.backtrace = Backtrace.parse(exception_attribute(:backtrace, caller), :filters => self.backtrace_filters)
91
+ self.error_class = exception_attribute(:error_class) {|exception| exception.class.name }
92
+ self.error_message = exception_attribute(:error_message, 'Notification') do |exception|
93
+ "#{exception.class.name}: #{exception.message}"
94
+ end
95
+
96
+ self.hostname = local_hostname
97
+
98
+ also_use_rack_params_filters
99
+ find_session_data
100
+ clean_params
101
+ clean_rack_request_data
102
+ end
103
+
104
+ # Public: Template used to create JSON payload
105
+ #
106
+ # Returns JSON representation of notice
107
+ def as_json(options = {})
108
+ {
109
+ :notifier => {
110
+ :name => notifier_name,
111
+ :url => notifier_url,
112
+ :version => notifier_version
113
+ },
114
+ :error => {
115
+ :class => error_class,
116
+ :message => error_message,
117
+ :backtrace => backtrace
118
+ },
119
+ :request => {
120
+ :url => url,
121
+ :component => component,
122
+ :action => action,
123
+ :params => parameters,
124
+ :session => session_data,
125
+ :cgi_data => cgi_data
126
+ },
127
+ :server => {
128
+ :project_root => project_root,
129
+ :environment_name => environment_name,
130
+ :hostname => hostname
131
+ }
132
+ }
133
+ end
134
+
135
+ # Public: Creates JSON
136
+ #
137
+ # Returns valid JSON representation of notice
138
+ def to_json(*a)
139
+ as_json.to_json(*a)
140
+ end
141
+
142
+ # Determines if this notice should be ignored
143
+ def ignore?
144
+ ignored_class_names.include?(error_class) ||
145
+ ignore_by_filters.any? {|filter| filter.call(self) }
146
+ end
147
+
148
+ # Public: Allows properties to be accessed using a hash-like syntax
149
+ #
150
+ # method - The given key for an attribute
151
+ #
152
+ # Examples:
153
+ #
154
+ # notice[:error_message]
155
+ #
156
+ # Returns the attribute value, or self if given +:request+
157
+ def [](method)
158
+ case method
159
+ when :request
160
+ self
161
+ else
162
+ send(method)
163
+ end
164
+ end
165
+
166
+ private
167
+
168
+ attr_writer :exception, :backtrace, :error_class, :error_message,
169
+ :backtrace_filters, :parameters, :params_filters, :environment_filters,
170
+ :session_data, :project_root, :url, :ignore, :ignore_by_filters,
171
+ :notifier_name, :notifier_url, :notifier_version, :component, :action,
172
+ :cgi_data, :environment_name, :hostname
173
+
174
+ # Private: Arguments given in the initializer
175
+ attr_accessor :args
176
+
177
+ # Private: Gets a property named +attribute+ of an exception, either from an actual
178
+ # exception or a hash.
179
+ #
180
+ # If an exception is available, #from_exception will be used. Otherwise,
181
+ # a key named +attribute+ will be used from the #args.
182
+ #
183
+ # If no exception or hash key is available, +default+ will be used.
184
+ def exception_attribute(attribute, default = nil, &block)
185
+ (exception && from_exception(attribute, &block)) || args[attribute] || default
186
+ end
187
+
188
+ # Private: Gets a property named +attribute+ from an exception.
189
+ #
190
+ # If a block is given, it will be used when getting the property from an
191
+ # exception. The block should accept and exception and return the value for
192
+ # the property.
193
+ #
194
+ # If no block is given, a method with the same name as +attribute+ will be
195
+ # invoked for the value.
196
+ def from_exception(attribute)
197
+ if block_given?
198
+ yield(exception)
199
+ else
200
+ exception.send(attribute)
201
+ end
202
+ end
203
+
204
+ # Private: Removes non-serializable data from the given attribute.
205
+ # See #clean_unserializable_data
206
+ def clean_unserializable_data_from(attribute)
207
+ self.send(:"#{attribute}=", clean_unserializable_data(send(attribute)))
208
+ end
209
+
210
+ # Private: Removes non-serializable data. Allowed data types are strings, arrays,
211
+ # and hashes. All other types are converted to strings.
212
+ # TODO: move this onto Hash
213
+ def clean_unserializable_data(data, stack = [])
214
+ return "[possible infinite recursion halted]" if stack.any?{|item| item == data.object_id }
215
+
216
+ if data.respond_to?(:to_hash)
217
+ data.to_hash.inject({}) do |result, (key, value)|
218
+ result.merge(key => clean_unserializable_data(value, stack + [data.object_id]))
219
+ end
220
+ elsif data.respond_to?(:to_ary)
221
+ data.to_ary.collect do |value|
222
+ clean_unserializable_data(value, stack + [data.object_id])
223
+ end
224
+ else
225
+ data.to_s
226
+ end
227
+ end
228
+
229
+ # Private: Replaces the contents of params that match params_filters.
230
+ # TODO: extract this to a different class
231
+ def clean_params
232
+ clean_unserializable_data_from(:parameters)
233
+ filter(parameters)
234
+ if cgi_data
235
+ clean_unserializable_data_from(:cgi_data)
236
+ filter(cgi_data)
237
+ end
238
+ if session_data
239
+ clean_unserializable_data_from(:session_data)
240
+ filter(session_data)
241
+ end
242
+ end
243
+
244
+ def clean_rack_request_data
245
+ if cgi_data
246
+ cgi_data.delete("rack.request.form_vars")
247
+ end
248
+ end
249
+
250
+ def filter(hash)
251
+ if params_filters
252
+ hash.each do |key, value|
253
+ if filter_key?(key)
254
+ hash[key] = "[FILTERED]"
255
+ elsif value.respond_to?(:to_hash)
256
+ filter(hash[key])
257
+ end
258
+ end
259
+ end
260
+ end
261
+
262
+ def filter_key?(key)
263
+ params_filters.any? do |filter|
264
+ key.to_s.eql?(filter.to_s)
265
+ end
266
+ end
267
+
268
+ def find_session_data
269
+ self.session_data = args[:session_data] || args[:session] || rack_session || {}
270
+ self.session_data = session_data[:data] if session_data[:data]
271
+ end
272
+
273
+ # Private: Converts the mixed class instances and class names into just names
274
+ # TODO: move this into Configuration or another class
275
+ def ignored_class_names
276
+ ignore.collect do |string_or_class|
277
+ if string_or_class.respond_to?(:name)
278
+ string_or_class.name
279
+ else
280
+ string_or_class
281
+ end
282
+ end
283
+ end
284
+
285
+ def rack_env(method)
286
+ rack_request.send(method) if rack_request
287
+ end
288
+
289
+ def rack_request
290
+ @rack_request ||= if args[:rack_env]
291
+ ::Rack::Request.new(args[:rack_env])
292
+ end
293
+ end
294
+
295
+ def action_dispatch_params
296
+ args[:rack_env]['action_dispatch.request.parameters'] if args[:rack_env]
297
+ end
298
+
299
+ def rack_session
300
+ args[:rack_env]['rack.session'] if args[:rack_env]
301
+ end
302
+
303
+ def also_use_rack_params_filters
304
+ if args[:rack_env]
305
+ @params_filters ||= []
306
+ @params_filters += rack_request.env["action_dispatch.parameter_filter"] || []
307
+ end
308
+ end
309
+
310
+ def local_hostname
311
+ Socket.gethostname
312
+ end
313
+ end
314
+ end