validation_tracker_client 2.4.11

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,41 @@
1
+ /.idea/*
2
+ .rvmrc
3
+ app/views/**/.tmp_*
4
+ public/images/Thumbs.db
5
+ public/system
6
+ tmp
7
+ public/blank.html
8
+ /.project
9
+ /.loadpath
10
+ /db/sphinx/test
11
+ /db/sphinx/test2
12
+ /db/sphinx/test3
13
+ /db/sphinx/test4
14
+ /db/sphinx/cucumber
15
+ /db/sphinx/development
16
+ /tmp
17
+ /log
18
+ /config/development.sphinx.conf
19
+ /config/test.sphinx.conf
20
+ /config/test2.sphinx.conf
21
+ /config/test3.sphinx.conf
22
+ /config/test4.sphinx.conf
23
+ /config/cucumber.sphinx.conf
24
+ nbproject
25
+ db/development_structure.sql
26
+ db/test_structure.sql
27
+ /results
28
+ cities.txt
29
+ states.txt
30
+ countries.txt
31
+ GPATH
32
+ GRTAGS
33
+ GSYMS
34
+ GTAGS
35
+ webrat.log
36
+ test/fixtures
37
+ .rvmrc
38
+ .gemtags
39
+ .tags
40
+ .tags_sorted_by_file
41
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in validation_tracker_client.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 arun.kumar.arjunan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # ValidationTrackerClient
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'validation_tracker_client'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install validation_tracker_client
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,136 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'rubygems'
4
+ begin
5
+ require 'active_support'
6
+ rescue LoadError
7
+ require 'activesupport'
8
+ end
9
+ require 'validation_tracker_client/version'
10
+ require 'validation_tracker_client/configuration'
11
+ require 'validation_tracker_client/notice'
12
+ require 'validation_tracker_client/sender'
13
+
14
+ require 'validation_tracker_client/railtie' if defined?(Rails::Railtie)
15
+
16
+ # Gem for applications to automatically post errors to the Validation Tracker of their choice.
17
+ module ValidationTrackerClient
18
+
19
+ API_VERSION = "2.0"
20
+ LOG_PREFIX = "** [Validation Tracker] "
21
+
22
+ HEADERS = {
23
+ 'Content-type' => 'text/xml',
24
+ 'Accept' => 'text/xml, application/xml'
25
+ }
26
+
27
+ class << self
28
+ # The sender object is responsible for delivering formatted data to the Validation Tracker server.
29
+ # Must respond to #send_to_validation_tracker. See ValidationTrackerClient::Sender.
30
+ attr_accessor :sender
31
+
32
+ # A Validation Tracker configuration object. Must act like a hash and return sensible
33
+ # values for all Validation Tracker configuration options. See ValidationTrackerClient::Configuration.
34
+ attr_accessor :configuration
35
+
36
+ # Tell the log that the Notifier is good to go
37
+ def report_ready
38
+ write_verbose_log("Notifier #{VERSION} ready to catch errors")
39
+ end
40
+
41
+ # Prints out the environment info to the log for debugging help
42
+ def report_environment_info
43
+ write_verbose_log("Environment Info: #{environment_info}")
44
+ end
45
+
46
+ # Prints out the response body from Validation Tracker for debugging help
47
+ def report_response_body(response)
48
+ write_verbose_log("Response from Validation Tracker: \n#{response}")
49
+ end
50
+
51
+ # Returns the Ruby version, Rails version, and current Rails environment
52
+ def environment_info
53
+ info = "[Ruby: #{RUBY_VERSION}]"
54
+ info << " [#{configuration.framework}]"
55
+ info << " [Env: #{configuration.environment_name}]"
56
+ end
57
+
58
+ # Writes out the given message to the #logger
59
+ def write_verbose_log(message)
60
+ logger.info LOG_PREFIX + message if logger
61
+ end
62
+
63
+ # Look for the Rails logger currently defined
64
+ def logger
65
+ self.configuration.logger
66
+ end
67
+
68
+ # Call this method to modify defaults in your initializers.
69
+ #
70
+ # @example
71
+ # ValidationTrackerClient.configure do |config|
72
+ # config.api_key = '1234567890abcdef'
73
+ # config.secure = false
74
+ # end
75
+ def configure(silent = false)
76
+ self.configuration ||= Configuration.new
77
+ yield(configuration)
78
+ self.sender = Sender.new(configuration)
79
+ report_ready unless silent
80
+ end
81
+
82
+ # Sends an exception manually using this method, even when you are not in a controller.
83
+ #
84
+ # @param [Exception] exception The exception you want to notify Validation Tracker about.
85
+ # @param [Hash] opts Data that will be sent to Validation Tracker.
86
+ #
87
+ # @option opts [String] :api_key The API key for this project. The API key is a unique identifier that Validation Tracker uses for identification.
88
+ # @option opts [String] :error_message The error returned by the exception (or the message you want to log).
89
+ # @option opts [String] :backtrace A backtrace, usually obtained with +caller+.
90
+ # @option opts [String] :request The controller's request object.
91
+ # @option opts [String] :session The contents of the user's session.
92
+ # @option opts [String] :environment ENV merged with the contents of the request's environment.
93
+ def notify(error_message, opts = {})
94
+ send_notice(build_notice_for(error_message, opts))
95
+ end
96
+
97
+ # Sends the notice unless it is one of the default ignored exceptions
98
+ # @see ValidationTrackerClient.notify
99
+ def notify_or_ignore(exception, opts = {})
100
+ notice = build_notice_for(exception, opts)
101
+ send_notice(notice) unless notice.ignore?
102
+ end
103
+
104
+ def build_lookup_hash_for(exception, options = {})
105
+ notice = build_notice_for(exception, options)
106
+
107
+ result = {}
108
+ result[:action] = notice.action rescue nil
109
+ result[:component] = notice.component rescue nil
110
+ result[:error_class] = notice.error_class if notice.error_class
111
+ result[:environment_name] = 'production'
112
+
113
+ unless notice.backtrace.lines.empty?
114
+ result[:file] = notice.backtrace.lines.first.file
115
+ result[:line_number] = notice.backtrace.lines.first.number
116
+ end
117
+
118
+ result
119
+ end
120
+
121
+ private
122
+
123
+ def send_notice(notice)
124
+ if configuration.public?
125
+ sender.send_to_validation_tracker(notice.to_xml)
126
+ end
127
+ end
128
+
129
+ def build_notice_for(error_message, opts = {})
130
+ opts = opts.merge(:error_message => error_message)
131
+ Notice.new(configuration.merge(opts))
132
+ end
133
+
134
+ end
135
+ end
136
+
@@ -0,0 +1,175 @@
1
+ module ValidationTrackerClient
2
+ # Used to set up and modify settings for the notifier.
3
+ class Configuration
4
+
5
+ OPTIONS = [:api_key, :development_environments,
6
+ :development_lookup, :environment_name, :host,
7
+ :http_open_timeout, :http_read_timeout,
8
+ :notifier_name, :notifier_url, :notifier_version,
9
+ :params_filters, :project_root, :port, :protocol, :proxy_host,
10
+ :proxy_pass, :proxy_port, :proxy_user, :secure, :framework,
11
+ :user_information].freeze
12
+
13
+ # The API key for your project, found on the project edit form.
14
+ attr_accessor :api_key
15
+
16
+ # The host to connect to (defaults to validation-tracker.heroku.com).
17
+ attr_accessor :host
18
+
19
+ # The port on which your Validation Tracker server runs (defaults to 443 for secure
20
+ # connections, 80 for insecure connections).
21
+ attr_accessor :port
22
+
23
+ # +true+ for https connections, +false+ for http connections.
24
+ attr_accessor :secure
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 Validation Tracker.
45
+ # By default, all "password" attributes will have their contents replaced.
46
+ attr_reader :params_filters
47
+
48
+ # A list of environments in which notifications should not be sent.
49
+ attr_accessor :development_environments
50
+
51
+ # +true+ if you want to check for production errors matching development errors, +false+ otherwise.
52
+ attr_accessor :development_lookup
53
+
54
+ # The name of the environment the application is running in
55
+ attr_accessor :environment_name
56
+
57
+ # The path to the project in which the error occurred, such as the RAILS_ROOT
58
+ attr_accessor :project_root
59
+
60
+ # The name of the notifier library being used to send notifications (such as "Validation Tracker Notifier")
61
+ attr_accessor :notifier_name
62
+
63
+ # The version of the notifier library being used to send notifications (such as "1.0.2")
64
+ attr_accessor :notifier_version
65
+
66
+ # The url of the notifier library being used to send notifications
67
+ attr_accessor :notifier_url
68
+
69
+ # The logger used by ValidationTrackerClient
70
+ attr_accessor :logger
71
+
72
+ # The text that the placeholder is replaced with. {{error_id}} is the actual error number.
73
+ attr_accessor :user_information
74
+
75
+ # The framework ValidationTrackerClient is configured to use
76
+ attr_accessor :framework
77
+
78
+ DEFAULT_PARAMS_FILTERS = %w(password password_confirmation).freeze
79
+
80
+ DEFAULT_BACKTRACE_FILTERS = [
81
+ lambda { |line|
82
+ if defined?(ValidationTrackerClient.configuration.project_root) && ValidationTrackerClient.configuration.project_root.to_s != ''
83
+ line.gsub(/#{ValidationTrackerClient.configuration.project_root}/, "[PROJECT_ROOT]")
84
+ else
85
+ line
86
+ end
87
+ },
88
+ lambda { |line| line.gsub(/^\.\//, "") },
89
+ lambda { |line|
90
+ if defined?(Gem)
91
+ Gem.path.inject(line) do |line, path|
92
+ line.gsub(/#{path}/, "[GEM_ROOT]")
93
+ end
94
+ end
95
+ },
96
+ lambda { |line| line if line !~ %r{lib/validation_tracker_client} }
97
+ ].freeze
98
+
99
+
100
+ alias_method :secure?, :secure
101
+
102
+ def initialize
103
+ @secure = false
104
+ @host = 'validation-tracker.heroku.com'
105
+ @http_open_timeout = 2
106
+ @http_read_timeout = 5
107
+ @params_filters = DEFAULT_PARAMS_FILTERS.dup
108
+ @ignore_user_agent = []
109
+ @development_environments = %w(development test cucumber)
110
+ @development_lookup = true
111
+ @notifier_name = 'Validation Tracker Notifier'
112
+ @notifier_version = VERSION
113
+ @notifier_url = 'http://validation-tracker.heroku.com'
114
+ @framework = 'Standalone'
115
+ @user_information = 'Validation Tracker Error {{error_id}}'
116
+ end
117
+
118
+
119
+ # Allows config options to be read like a hash
120
+ #
121
+ # @param [Symbol] option Key for a given attribute
122
+ def [](option)
123
+ send(option)
124
+ end
125
+
126
+ # Returns a hash of all configurable options
127
+ def to_hash
128
+ OPTIONS.inject({}) do |hash, option|
129
+ hash.merge(option.to_sym => send(option))
130
+ end
131
+ end
132
+
133
+ # Returns a hash of all configurable options merged with +hash+
134
+ #
135
+ # @param [Hash] hash A set of configuration options that will take precedence over the defaults
136
+ def merge(hash)
137
+ to_hash.merge(hash)
138
+ end
139
+
140
+ # Determines if the notifier will send notices.
141
+ # @return [Boolean] Returns +false+ if in a development environment, +true+ otherwise.
142
+ def public?
143
+ !development_environments.include?(environment_name)
144
+ end
145
+
146
+ def port
147
+ @port || default_port
148
+ end
149
+
150
+ def protocol
151
+ if secure?
152
+ 'https'
153
+ else
154
+ 'http'
155
+ end
156
+ end
157
+
158
+ def environment_filters
159
+ warn 'config.environment_filters has been deprecated and has no effect.'
160
+ []
161
+ end
162
+
163
+ private
164
+
165
+ def default_port
166
+ if secure?
167
+ 443
168
+ else
169
+ 80
170
+ end
171
+ end
172
+
173
+ end
174
+
175
+ end
@@ -0,0 +1,329 @@
1
+ require 'builder'
2
+ require 'socket'
3
+
4
+ module ValidationTrackerClient
5
+ class Notice
6
+
7
+ # The API key for the project to which this notice should be sent
8
+ attr_reader :api_key
9
+
10
+
11
+ # The name of the server environment (such as "production")
12
+ attr_reader :environment_name
13
+
14
+ # CGI variables such as HTTP_METHOD
15
+ attr_reader :cgi_data
16
+
17
+ # The message from the exception, or a general description of the error
18
+ attr_reader :error_message
19
+
20
+ # See Configuration#backtrace_filters
21
+ attr_reader :backtrace_filters
22
+
23
+ # See Configuration#params_filters
24
+ attr_reader :params_filters
25
+
26
+ # A hash of parameters from the query string or post body.
27
+ attr_reader :parameters
28
+ alias_method :params, :parameters
29
+
30
+ # The component (if any) which was used in this request (usually the controller)
31
+ attr_reader :component
32
+ alias_method :controller, :component
33
+
34
+ # The action (if any) that was called in this request
35
+ attr_reader :action
36
+
37
+ # A hash of session data from the request
38
+ attr_reader :session_data
39
+
40
+ # The path to the project that caused the error (usually RAILS_ROOT)
41
+ attr_reader :project_root
42
+
43
+ # The URL at which the error occurred (if any)
44
+ attr_reader :url
45
+
46
+ # The name of the notifier library sending this notice, such as "Validation Tracker Notifier"
47
+ attr_reader :notifier_name
48
+
49
+ # The version number of the notifier library sending this notice, such as "2.1.3"
50
+ attr_reader :notifier_version
51
+
52
+ # A URL for more information about the notifier library sending this notice
53
+ attr_reader :notifier_url
54
+
55
+ # The host name where this error occurred (if any)
56
+ attr_reader :hostname
57
+
58
+ def initialize(args)
59
+ self.args = args
60
+ self.exception = args[:exception]
61
+ self.api_key = args[:api_key]
62
+ self.project_root = args[:project_root]
63
+ self.url = args[:url] || rack_env(:url)
64
+
65
+ self.notifier_name = args[:notifier_name]
66
+ self.notifier_version = args[:notifier_version]
67
+ self.notifier_url = args[:notifier_url]
68
+
69
+ self.params_filters = args[:params_filters] || []
70
+ self.parameters = args[:parameters] ||
71
+ action_dispatch_params ||
72
+ rack_env(:params) ||
73
+ {}
74
+ self.component = args[:component] || args[:controller] || parameters['controller']
75
+ self.action = args[:action] || parameters['action']
76
+
77
+ self.environment_name = args[:environment_name]
78
+ self.cgi_data = args[:cgi_data] || args[:rack_env]
79
+ self.error_message = exception_attribute(:error_message, 'Notification') do |exception|
80
+ "#{exception.class.name}: #{exception.message}"
81
+ end
82
+
83
+ self.hostname = local_hostname
84
+
85
+ also_use_rack_params_filters
86
+ find_session_data
87
+ clean_params
88
+ clean_rack_request_data
89
+ end
90
+
91
+ # Converts the given notice to XML
92
+ def to_xml
93
+ builder = Builder::XmlMarkup.new
94
+ builder.instruct!
95
+ xml = builder.notice(:version => ValidationTrackerClient::API_VERSION) do |notice|
96
+ notice.tag!("api-key", api_key)
97
+ notice.notifier do |notifier|
98
+ notifier.name(notifier_name)
99
+ notifier.version(notifier_version)
100
+ notifier.url(notifier_url)
101
+ end
102
+ notice.error do |error|
103
+ error.tag!('class', error_class)
104
+ error.message(error_message)
105
+ error.backtrace do |backtrace|
106
+ self.backtrace.lines.each do |line|
107
+ backtrace.line(:number => line.number,
108
+ :file => line.file,
109
+ :method => line.method)
110
+ end
111
+ end
112
+ end
113
+ if url ||
114
+ controller ||
115
+ action ||
116
+ !parameters.blank? ||
117
+ !cgi_data.blank? ||
118
+ !session_data.blank?
119
+ notice.request do |request|
120
+ request.url(url)
121
+ request.component(controller)
122
+ request.action(action)
123
+ unless parameters.nil? || parameters.empty?
124
+ request.params do |params|
125
+ xml_vars_for(params, parameters)
126
+ end
127
+ end
128
+ unless session_data.nil? || session_data.empty?
129
+ request.session do |session|
130
+ xml_vars_for(session, session_data)
131
+ end
132
+ end
133
+ unless cgi_data.nil? || cgi_data.empty?
134
+ request.tag!("cgi-data") do |cgi_datum|
135
+ xml_vars_for(cgi_datum, cgi_data)
136
+ end
137
+ end
138
+ end
139
+ end
140
+ notice.tag!("server-environment") do |env|
141
+ env.tag!("project-root", project_root)
142
+ env.tag!("environment-name", environment_name)
143
+ env.tag!("hostname", hostname)
144
+ end
145
+ end
146
+ xml.to_s
147
+ end
148
+
149
+ # Determines if this notice should be ignored
150
+ def ignore?
151
+ ignored_class_names.include?(error_class) ||
152
+ ignore_by_filters.any? {|filter| filter.call(self) }
153
+ end
154
+
155
+ # Allows properties to be accessed using a hash-like syntax
156
+ #
157
+ # @example
158
+ # notice[:error_message]
159
+ # @param [String] method The given key for an attribute
160
+ # @return The attribute value, or self if given +:request+
161
+ def [](method)
162
+ case method
163
+ when :request
164
+ self
165
+ else
166
+ send(method)
167
+ end
168
+ end
169
+
170
+ private
171
+
172
+ attr_writer :exception, :api_key, :backtrace, :error_class, :error_message,
173
+ :backtrace_filters, :parameters, :params_filters,
174
+ :environment_filters, :session_data, :project_root, :url, :ignore,
175
+ :ignore_by_filters, :notifier_name, :notifier_url, :notifier_version,
176
+ :component, :action, :cgi_data, :environment_name, :hostname
177
+
178
+ # Arguments given in the initializer
179
+ attr_accessor :args
180
+
181
+ # Gets a property named +attribute+ of an exception, either from an actual
182
+ # exception or a hash.
183
+ #
184
+ # If an exception is available, #from_exception will be used. Otherwise,
185
+ # a key named +attribute+ will be used from the #args.
186
+ #
187
+ # If no exception or hash key is available, +default+ will be used.
188
+ def exception_attribute(attribute, default = nil, &block)
189
+ (exception && from_exception(attribute, &block)) || args[attribute] || default
190
+ end
191
+
192
+ # Gets a property named +attribute+ from an exception.
193
+ #
194
+ # If a block is given, it will be used when getting the property from an
195
+ # exception. The block should accept and exception and return the value for
196
+ # the property.
197
+ #
198
+ # If no block is given, a method with the same name as +attribute+ will be
199
+ # invoked for the value.
200
+ def from_exception(attribute)
201
+ if block_given?
202
+ yield(exception)
203
+ else
204
+ exception.send(attribute)
205
+ end
206
+ end
207
+
208
+ # Removes non-serializable data from the given attribute.
209
+ # See #clean_unserializable_data
210
+ def clean_unserializable_data_from(attribute)
211
+ self.send(:"#{attribute}=", clean_unserializable_data(send(attribute)))
212
+ end
213
+
214
+ # Removes non-serializable data. Allowed data types are strings, arrays,
215
+ # and hashes. All other types are converted to strings.
216
+ # TODO: move this onto Hash
217
+ def clean_unserializable_data(data, stack = [])
218
+ return "[possible infinite recursion halted]" if stack.any?{|item| item == data.object_id }
219
+
220
+ if data.respond_to?(:to_hash)
221
+ data.to_hash.inject({}) do |result, (key, value)|
222
+ result.merge(key => clean_unserializable_data(value, stack + [data.object_id]))
223
+ end
224
+ elsif data.respond_to?(:to_ary)
225
+ data.collect do |value|
226
+ clean_unserializable_data(value, stack + [data.object_id])
227
+ end
228
+ else
229
+ data.to_s
230
+ end
231
+ end
232
+
233
+ # Replaces the contents of params that match params_filters.
234
+ # TODO: extract this to a different class
235
+ def clean_params
236
+ clean_unserializable_data_from(:parameters)
237
+ filter(parameters)
238
+ if cgi_data
239
+ clean_unserializable_data_from(:cgi_data)
240
+ filter(cgi_data)
241
+ end
242
+ if session_data
243
+ clean_unserializable_data_from(:session_data)
244
+ filter(session_data)
245
+ end
246
+ end
247
+
248
+ def clean_rack_request_data
249
+ if cgi_data
250
+ cgi_data.delete("rack.request.form_vars")
251
+ end
252
+ end
253
+
254
+ def filter(hash)
255
+ if params_filters
256
+ hash.each do |key, value|
257
+ if filter_key?(key)
258
+ hash[key] = "[FILTERED]"
259
+ elsif value.respond_to?(:to_hash)
260
+ filter(hash[key])
261
+ end
262
+ end
263
+ end
264
+ end
265
+
266
+ def filter_key?(key)
267
+ params_filters.any? do |filter|
268
+ key.to_s.include?(filter.to_s)
269
+ end
270
+ end
271
+
272
+ def find_session_data
273
+ self.session_data = args[:session_data] || args[:session] || rack_session || {}
274
+ self.session_data = session_data[:data] if session_data[:data]
275
+ end
276
+
277
+ # Converts the mixed class instances and class names into just names
278
+ # TODO: move this into Configuration or another class
279
+ def ignored_class_names
280
+ ignore.collect do |string_or_class|
281
+ if string_or_class.respond_to?(:name)
282
+ string_or_class.name
283
+ else
284
+ string_or_class
285
+ end
286
+ end
287
+ end
288
+
289
+ def xml_vars_for(builder, hash)
290
+ hash.each do |key, value|
291
+ if value.respond_to?(:to_hash)
292
+ builder.var(:key => key){|b| xml_vars_for(b, value.to_hash) }
293
+ else
294
+ builder.var(value.to_s, :key => key)
295
+ end
296
+ end
297
+ end
298
+
299
+ def rack_env(method)
300
+ rack_request.send(method) if rack_request
301
+ end
302
+
303
+ def rack_request
304
+ @rack_request ||= if args[:rack_env]
305
+ ::Rack::Request.new(args[:rack_env])
306
+ end
307
+ end
308
+
309
+ def action_dispatch_params
310
+ args[:rack_env]['action_dispatch.request.parameters'] if args[:rack_env]
311
+ end
312
+
313
+ def rack_session
314
+ args[:rack_env]['rack.session'] if args[:rack_env]
315
+ end
316
+
317
+ def also_use_rack_params_filters
318
+ if args[:rack_env]
319
+ @params_filters ||= []
320
+ @params_filters += rack_request.env["action_dispatch.parameter_filter"] || []
321
+ end
322
+ end
323
+
324
+ def local_hostname
325
+ Socket.gethostname
326
+ end
327
+
328
+ end
329
+ end
@@ -0,0 +1,34 @@
1
+ require 'validation_tracker_client'
2
+ require 'validation_tracker_client/rails/controller_methods'
3
+ require 'validation_tracker_client/rails/action_controller_catcher'
4
+ require 'validation_tracker_client/rails/error_lookup'
5
+ require 'validation_tracker_client/rails/javascript_notifier'
6
+
7
+ module ValidationTrackerClient
8
+ module Rails
9
+ def self.initialize
10
+ if defined?(ActionController::Base)
11
+ ActionController::Base.send(:include, ValidationTrackerClient::Rails::ActionControllerCatcher)
12
+ ActionController::Base.send(:include, ValidationTrackerClient::Rails::ErrorLookup)
13
+ ActionController::Base.send(:include, ValidationTrackerClient::Rails::ControllerMethods)
14
+ ActionController::Base.send(:include, ValidationTrackerClient::Rails::JavascriptNotifier)
15
+ end
16
+
17
+ rails_logger = if defined?(::Rails.logger)
18
+ ::Rails.logger
19
+ elsif defined?(RAILS_DEFAULT_LOGGER)
20
+ RAILS_DEFAULT_LOGGER
21
+ end
22
+
23
+ ValidationTrackerClient.configure(true) do |config|
24
+ config.logger = rails_logger
25
+ config.environment_name = RAILS_ENV if defined?(RAILS_ENV)
26
+ config.project_root = RAILS_ROOT if defined?(RAILS_ROOT)
27
+ config.framework = "Rails: #{::Rails::VERSION::STRING}" if defined?(::Rails::VERSION)
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ ValidationTrackerClient::Rails.initialize
34
+
@@ -0,0 +1,62 @@
1
+ module ValidationTrackerClient
2
+ module Rails
3
+ module ControllerMethods
4
+ private
5
+
6
+ # This method should be used for sending manual notifications while you are still
7
+ # inside the controller. Otherwise it works like ValidationTrackerClient.notify.
8
+ def notify_validation_message(hash_or_exception)
9
+ unless validation_tracker_local_request?
10
+ ValidationTrackerClient.notify(hash_or_exception, validation_tracker_request_data)
11
+ end
12
+ end
13
+
14
+ def validation_tracker_local_request?
15
+ if defined?(::Rails.application.config)
16
+ ::Rails.application.config.consider_all_requests_local || request.local?
17
+ else
18
+ consider_all_requests_local || local_request?
19
+ end
20
+ end
21
+
22
+ def validation_tracker_request_data
23
+ { :parameters => validation_tracker_filter_if_filtering(params.to_hash),
24
+ :session_data => validation_tracker_filter_if_filtering(validation_tracker_session_data),
25
+ :controller => params[:controller],
26
+ :action => params[:action],
27
+ :url => validation_tracker_request_url,
28
+ :cgi_data => validation_tracker_filter_if_filtering(request.env) }
29
+ end
30
+
31
+ def validation_tracker_filter_if_filtering(hash)
32
+ return hash if ! hash.is_a?(Hash)
33
+
34
+ if respond_to?(:filter_parameters)
35
+ filter_parameters(hash) rescue hash
36
+ else
37
+ hash
38
+ end
39
+ end
40
+
41
+ def validation_tracker_session_data
42
+ if session.respond_to?(:to_hash)
43
+ session.to_hash
44
+ else
45
+ session.data
46
+ end
47
+ end
48
+
49
+ def validation_tracker_request_url
50
+ url = "#{request.protocol}#{request.host}"
51
+
52
+ unless [80, 443].include?(request.port)
53
+ url << ":#{request.port}"
54
+ end
55
+
56
+ url << request.fullpath
57
+ url
58
+ end
59
+ end
60
+ end
61
+ end
62
+
@@ -0,0 +1,22 @@
1
+ require 'validation_tracker_client'
2
+ require 'rails'
3
+
4
+ module ValidationTrackerClient
5
+ class Railtie < Rails::Railtie
6
+
7
+ config.after_initialize do
8
+ ValidationTrackerClient.configure(true) do |config|
9
+ config.logger ||= Rails.logger
10
+ config.environment_name ||= Rails.env
11
+ config.project_root ||= Rails.root
12
+ config.framework = "Rails: #{::Rails::VERSION::STRING}"
13
+ end
14
+
15
+ if defined?(::ActionController::Base)
16
+ require 'validation_tracker_client/rails/controller_methods'
17
+
18
+ ::ActionController::Base.send(:include, ValidationTrackerClient::Rails::ControllerMethods)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,76 @@
1
+ module ValidationTrackerClient
2
+ # Sends out the notice to Validation Tracker
3
+ class Sender
4
+
5
+ NOTICES_URI = '/notifier_api/v2/notices/'.freeze
6
+ HTTP_ERRORS = [Timeout::Error,
7
+ Errno::EINVAL,
8
+ Errno::ECONNRESET,
9
+ EOFError,
10
+ Net::HTTPBadResponse,
11
+ Net::HTTPHeaderSyntaxError,
12
+ Net::ProtocolError,
13
+ Errno::ECONNREFUSED].freeze
14
+
15
+ def initialize(options = {})
16
+ [:proxy_host, :proxy_port, :proxy_user, :proxy_pass, :protocol,
17
+ :host, :port, :secure, :http_open_timeout, :http_read_timeout].each do |option|
18
+ instance_variable_set("@#{option}", options[option])
19
+ end
20
+ end
21
+
22
+ # Sends the notice data off to Validation Tracker for processing.
23
+ #
24
+ # @param [String] data The XML notice to be sent off
25
+ def send_to_hoptoad(data)
26
+ logger.debug { "Sending request to #{url.to_s}:\n#{data}" } if logger
27
+
28
+ http =
29
+ Net::HTTP::Proxy(proxy_host, proxy_port, proxy_user, proxy_pass).
30
+ new(url.host, url.port)
31
+
32
+ http.read_timeout = http_read_timeout
33
+ http.open_timeout = http_open_timeout
34
+ http.use_ssl = secure
35
+
36
+ response = begin
37
+ http.post(url.path, data, HEADERS)
38
+ rescue *HTTP_ERRORS => e
39
+ log :error, "Timeout while contacting the Validation Tracker server."
40
+ nil
41
+ end
42
+
43
+ case response
44
+ when Net::HTTPSuccess then
45
+ log :info, "Success: #{response.class}", response
46
+ else
47
+ log :error, "Failure: #{response.class}", response
48
+ end
49
+
50
+ if response && response.respond_to?(:body)
51
+ error_id = response.body.match(%r{<error-id[^>]*>(.*?)</error-id>})
52
+ error_id[1] if error_id
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ attr_reader :proxy_host, :proxy_port, :proxy_user, :proxy_pass, :protocol,
59
+ :host, :port, :secure, :http_open_timeout, :http_read_timeout
60
+
61
+ def url
62
+ URI.parse("#{protocol}://#{host}:#{port}").merge(NOTICES_URI)
63
+ end
64
+
65
+ def log(level, message, response = nil)
66
+ logger.send level, LOG_PREFIX + message if logger
67
+ ValidationTrackerClient.report_environment_info
68
+ ValidationTrackerClient.report_response_body(response.body) if response && response.respond_to?(:body)
69
+ end
70
+
71
+ def logger
72
+ ValidationTrackerClient.logger
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,3 @@
1
+ module ValidationTrackerClient
2
+ VERSION = "2.4.11"
3
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'validation_tracker_client/rails'
data/test.rb ADDED
@@ -0,0 +1,7 @@
1
+ system 'rake build --trace'
2
+ system 'rake install'
3
+ require 'rubygems'
4
+ require 'debugger'
5
+ gem 'validation_tracker_client'
6
+
7
+ ValidationTrackerClient.notify('COOL')
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/validation_tracker_client/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["arun.kumar.arjunan"]
6
+ gem.email = ["arun@chronus.com"]
7
+ gem.description = %q{Validation Tracker Client}
8
+ gem.summary = %q{Validation Tracker Summary}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "validation_tracker_client"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = ValidationTrackerClient::VERSION
17
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: validation_tracker_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.4.11
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - arun.kumar.arjunan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-08 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Validation Tracker Client
15
+ email:
16
+ - arun@chronus.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - LICENSE
24
+ - README.md
25
+ - Rakefile
26
+ - lib/validation_tracker_client.rb
27
+ - lib/validation_tracker_client/configuration.rb
28
+ - lib/validation_tracker_client/notice.rb
29
+ - lib/validation_tracker_client/rails.rb
30
+ - lib/validation_tracker_client/rails/controller_methods.rb
31
+ - lib/validation_tracker_client/railtie.rb
32
+ - lib/validation_tracker_client/sender.rb
33
+ - lib/validation_tracker_client/version.rb
34
+ - rails/init.rb
35
+ - test.rb
36
+ - validation_tracker_client.gemspec
37
+ homepage: ''
38
+ licenses: []
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 1.8.10
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: Validation Tracker Summary
61
+ test_files: []