lib/rorvswild.rb in rorvswild-0.0.1 vs lib/rorvswild.rb in rorvswild-0.0.2
- old
+ new
@@ -1,139 +1,145 @@
require "rorvswild/version"
-class RorVsWild
- def self.default_config
- {
- api_url: "http://www.rorvswild.com/api",
- sql_threshold: 500
- }
+module RorVsWild
+ def self.new(*args)
+ Client.new(*args) # Compatibility with 0.0.1
end
- attr_reader :api_url, :api_key, :app_id, :sql_threshold, :error, :request
+ class Client
+ def self.default_config
+ {
+ api_url: "http://www.rorvswild.com/api",
+ sql_threshold: 500
+ }
+ end
- def initialize(config)
- config = RorVsWild.default_config.merge(config)
- @sql_threshold = config[:sql_threshold]
- @api_url = config[:api_url]
- @api_key = config[:api_key]
- @app_id = config[:app_id]
- setup_callbacks
- end
+ attr_reader :api_url, :api_key, :app_id, :sql_threshold, :error, :request
- def setup_callbacks
- ApplicationController.rescue_from(StandardError, &method(:after_exception))
- ActiveSupport::Notifications.subscribe("sql.active_record", &method(:after_sql_query))
- ActiveSupport::Notifications.subscribe("render_template.action_view", &method(:after_view_rendering))
- ActiveSupport::Notifications.subscribe("process_action.action_controller", &method(:after_http_request))
- ActiveSupport::Notifications.subscribe("start_processing.action_controller", &method(:before_http_request))
- end
+ def initialize(config)
+ config = self.class.default_config.merge(config)
+ @sql_threshold = config[:sql_threshold]
+ @api_url = config[:api_url]
+ @api_key = config[:api_key]
+ @app_id = config[:app_id]
+ setup_callbacks
+ end
- def before_http_request(name, start, finish, id, payload)
- @request = {controller: payload[:controller], action: payload[:action], path: payload[:path]}
- @queries = []
- @views = []
- @error = nil
- end
+ def setup_callbacks
+ ApplicationController.rescue_from(StandardError, &method(:after_exception))
+ ActiveSupport::Notifications.subscribe("sql.active_record", &method(:after_sql_query))
+ ActiveSupport::Notifications.subscribe("render_template.action_view", &method(:after_view_rendering))
+ ActiveSupport::Notifications.subscribe("process_action.action_controller", &method(:after_http_request))
+ ActiveSupport::Notifications.subscribe("start_processing.action_controller", &method(:before_http_request))
+ end
- def after_http_request(name, start, finish, id, payload)
- request[:db_runtime] = (payload[:db_runtime] || 0).round
- request[:view_runtime] = (payload[:view_runtime] || 0).round
- request[:other_runtime] = compute_duration(start, finish) - request[:db_runtime] - request[:view_runtime]
- request[:params] = params_filter.filter(payload[:params]) if error
- Thread.new { post_request }
- rescue => ex
- Rails.logger.error("[RorVsWild] " + ex.inspect)
- Rails.logger.error("[RorVsWild] " + ex.backtrace.join("\n[RorVsWild] "))
- end
+ def before_http_request(name, start, finish, id, payload)
+ @request = {controller: payload[:controller], action: payload[:action], path: payload[:path]}
+ @queries = []
+ @views = []
+ @error = nil
+ end
- def after_sql_query(name, start, finish, id, payload)
- return if !queries || payload[:name] == "EXPLAIN".freeze
- runtime, sql, plan = compute_duration(start, finish), nil, nil
- file, line, method = extract_file_and_line_from_call_stack(caller)
- plan = explain(sql = payload[:sql], payload[:binds]) if runtime > sql_threshold
- queries << {file: file, line: line, sql: sql, plan: plan, runtime: runtime}
- rescue => ex
- Rails.logger.error("[RorVsWild] " + ex.inspect)
- Rails.logger.error("[RorVsWild] " + ex.backtrace.join("\n[RorVsWild] "))
- end
+ def after_http_request(name, start, finish, id, payload)
+ request[:db_runtime] = (payload[:db_runtime] || 0).round
+ request[:view_runtime] = (payload[:view_runtime] || 0).round
+ request[:other_runtime] = compute_duration(start, finish) - request[:db_runtime] - request[:view_runtime]
+ request[:params] = params_filter.filter(payload[:params]) if error
+ Thread.new { post_request }
+ rescue => ex
+ Rails.logger.error("[RorVsWild] " + ex.inspect)
+ Rails.logger.error("[RorVsWild] " + ex.backtrace.join("\n[RorVsWild] "))
+ end
- def after_view_rendering(name, start, finish, id, payload)
- views << {file: relative_path(payload[:identifier]), runtime: compute_duration(start, finish)} if views
- end
+ def after_sql_query(name, start, finish, id, payload)
+ return if !queries || payload[:name] == "EXPLAIN".freeze
+ runtime, sql, plan = compute_duration(start, finish), nil, nil
+ file, line, method = extract_file_and_line_from_call_stack(caller)
+ plan = explain(sql = payload[:sql], payload[:binds]) if runtime > sql_threshold
+ queries << {file: file, line: line, sql: sql, plan: plan, runtime: runtime}
+ rescue => ex
+ Rails.logger.error("[RorVsWild] " + ex.inspect)
+ Rails.logger.error("[RorVsWild] " + ex.backtrace.join("\n[RorVsWild] "))
+ end
- def after_exception(exception)
- file, line = exception.backtrace.first.split(":")
- @error = {
- exception: exception.class.to_s,
- backtrace: exception.backtrace,
- message: exception.message,
- file: relative_path(file),
- line: line.to_i
- }
- raise exception
- end
+ def after_view_rendering(name, start, finish, id, payload)
+ views << {file: relative_path(payload[:identifier]), runtime: compute_duration(start, finish)} if views
+ end
- #######################
- ### Private methods ###
- #######################
+ def after_exception(exception)
+ file, line = exception.backtrace.first.split(":")
+ @error = {
+ exception: exception.class.to_s,
+ backtrace: exception.backtrace,
+ message: exception.message,
+ file: relative_path(file),
+ line: line.to_i
+ }
+ raise exception
+ end
- private
+ #######################
+ ### Private methods ###
+ #######################
- def queries
- @queries
- end
+ private
- def views
- @views
- end
+ def queries
+ @queries
+ end
- def slowest_views
- views.sort { |h1, h2| h2[:runtime] <=> h1[:runtime] }[0, 25]
- end
+ def views
+ @views
+ end
- def slowest_queries
- queries.sort { |h1, h2| h2[:runtime] <=> h1[:runtime] }[0, 25]
- end
+ def slowest_views
+ views.sort { |h1, h2| h2[:runtime] <=> h1[:runtime] }[0, 25]
+ end
- def explain(sql, binds)
- rows = ActiveRecord::Base.connection.exec_query("EXPLAIN " + sql, "EXPLAIN", binds)
- rows.map { |row| row["QUERY PLAN"] }.join("\n")
- rescue => ex
- end
+ def slowest_queries
+ queries.sort { |h1, h2| h2[:runtime] <=> h1[:runtime] }[0, 25]
+ end
- def post_request
- post("/requests", request: request.merge(queries: slowest_queries, views: slowest_views, error: error))
- end
+ def explain(sql, binds)
+ rows = ActiveRecord::Base.connection.exec_query("EXPLAIN " + sql, "EXPLAIN", binds)
+ rows.map { |row| row["QUERY PLAN"] }.join("\n")
+ rescue => ex
+ end
- def extract_file_and_line_from_call_stack(stack)
- file, line, method = (stack.find { |str| str.include?(Rails.root.to_s) } ||
- stack.find { |str| str.include?("(irb):") }).split(":")
- file.sub!(Rails.root.to_s, "")
- method.sub!("block in ", "")
- method.sub!("in `", "")
- method.sub!("'", "")
- [file, line, method]
- end
+ def post_request
+ post("/requests", request: request.merge(queries: slowest_queries, views: slowest_views, error: error))
+ end
- def compute_duration(start, finish)
- ((finish - start) * 1000).round
- end
+ def extract_file_and_line_from_call_stack(stack)
+ file, line, method = (stack.find { |str| str.include?(Rails.root.to_s) } ||
+ stack.find { |str| str.include?("(irb):") }).split(":")
+ file.sub!(Rails.root.to_s, "")
+ method.sub!("block in ", "")
+ method.sub!("in `", "")
+ method.sub!("'", "")
+ [file, line, method]
+ end
- def relative_path(path)
- path.sub(Rails.root.to_s, "")
- end
+ def compute_duration(start, finish)
+ ((finish - start) * 1000).round
+ end
- def post(path, data)
- uri = URI(api_url + path)
- Net::HTTP.start(uri.host, uri.port) do |http|
- post = Net::HTTP::Post.new(uri)
- post.content_type = "application/json"
- post.basic_auth(app_id, api_key)
- post.body = data.to_json
- http.request(post)
+ def relative_path(path)
+ path.sub(Rails.root.to_s, "")
end
- end
- def params_filter
- @params_filter ||= ActionDispatch::Http::ParameterFilter.new(Rails.application.config.filter_parameters)
+ def post(path, data)
+ uri = URI(api_url + path)
+ Net::HTTP.start(uri.host, uri.port) do |http|
+ post = Net::HTTP::Post.new(uri)
+ post.content_type = "application/json"
+ post.basic_auth(app_id, api_key)
+ post.body = data.to_json
+ http.request(post)
+ end
+ end
+
+ def params_filter
+ @params_filter ||= ActionDispatch::Http::ParameterFilter.new(Rails.application.config.filter_parameters)
+ end
end
end