lib/rorvswild.rb in rorvswild-0.2.0 vs lib/rorvswild.rb in rorvswild-0.2.1

- old
+ new

@@ -41,19 +41,20 @@ explain_sql_threshold: 500, log_sql_threshold: 100, } end - attr_reader :api_url, :api_key, :app_id, :error, :request, :explain_sql_threshold, :log_sql_threshold + attr_reader :api_url, :api_key, :app_id, :explain_sql_threshold, :log_sql_threshold def initialize(config) config = self.class.default_config.merge(config) @explain_sql_threshold = config[:explain_sql_threshold] @log_sql_threshold = config[:log_sql_threshold] @api_url = config[:api_url] @api_key = config[:api_key] @app_id = config[:app_id] + @data = {} setup_callbacks RorVsWild.register_default_client(self) end def setup_callbacks @@ -68,23 +69,19 @@ Delayed::Worker.lifecycle.around(:invoke_job, &method(:around_delayed_job)) if defined?(Delayed::Worker) Sidekiq.configure_server { |config| config.server_middleware { |chain| chain.add(SidekiqPlugin) } } if defined?(Sidekiq) end def before_http_request(name, start, finish, id, payload) - @request = {controller: payload[:controller], action: payload[:action], path: payload[:path]} - @queries = [] - @views = {} - @error = nil + request.merge!(controller: payload[:controller], action: payload[:action], path: payload[:path]) 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] - error[:parameters] = filter_sensitive_data(payload[:params]) if error - attributes = request.merge(queries: slowest_queries, views: slowest_views, error: error) - Thread.new { post_request(attributes) } + request[:error][:parameters] = filter_sensitive_data(payload[:params]) if request[:error] + post_request rescue => exception log_error(exception) end def after_sql_query(name, start, finish, id, payload) @@ -112,11 +109,11 @@ end def after_exception(exception, controller) if !exception.is_a?(ActionController::RoutingError) file, line = exception.backtrace.first.split(":") - @error = exception_to_hash(exception).merge( + request[:error] = exception_to_hash(exception).merge( session: controller.session.to_hash, environment_variables: filter_sensitive_data(filter_environment_variables(controller.request.env)) ) end raise exception @@ -134,12 +131,11 @@ def measure_code(code) measure_block(code) { eval(code) } end def measure_block(name, &block) - @queries = [] - @job = {name: name} + job[:name] = name started_at = Time.now cpu_time_offset = cpu_time block.call rescue => exception job[:error] = exception_to_hash(exception) @@ -173,21 +169,33 @@ ####################### private def queries - @queries + data[:queries] ||= [] end def views - @views + data[:views] ||= {} end def job - @job + data end + def request + data + end + + def data + @data[Thread.current.object_id] ||= {} + end + + def cleanup_data + @data.delete(Thread.current.object_id) + end + def push_query(query) if query[:sql] || query[:plan] queries << query else if hash = queries.find { |hash| hash[:line] == query[:line] && hash[:file] == query[:file] } @@ -211,24 +219,27 @@ def explain(sql, binds) ActiveRecord::Base.connection.explain(sql, binds) if (sql =~ SELECT_REGEX) == 0 end - def post_request(attributes) - post("/requests", request: attributes) - rescue => exception - log_error(exception) + def post_request + attributes = request.merge(queries: slowest_queries, views: slowest_views) + Thread.new { post("/requests".freeze, request: attributes) } + ensure + cleanup_data end def post_job - post("/jobs", job: job.merge(queries: slowest_queries)) + post("/jobs".freeze, job: job.merge(queries: slowest_queries)) rescue => exception log_error(exception) + ensure + cleanup_data end def post_error(hash) - post("/errors", error: hash) + post("/errors".freeze, error: hash) end def extract_query_location(stack) if location = stack.find { |str| str.include?(Rails.root.to_s) } split_file_location(location.sub(Rails.root.to_s, "".freeze)) @@ -239,27 +250,27 @@ extract_query_location(stack) || split_file_location(stack.first) end def split_file_location(location) file, line, method = location.split(":") - method = cleanup_method_name(method) + method = cleanup_method_name(method) if method [file, line, method] end def cleanup_method_name(method) - method.sub!("block in ", "") - method.sub!("in `", "") - method.sub!("'", "") - method.index("_app_views_") == 0 ? nil : method + method.sub!("block in ".freeze, "".freeze) + method.sub!("in `".freeze, "".freeze) + method.sub!("'".freeze, "".freeze) + method.index("_app_views_".freeze) == 0 ? nil : method end def compute_duration(start, finish) ((finish - start) * 1000) end def relative_path(path) - path.sub(Rails.root.to_s, "") + path.sub(Rails.root.to_s, "".freeze) end def exception_to_hash(exception, extra_details = nil) file, line, method = extract_error_location(exception.backtrace) { @@ -275,11 +286,11 @@ def post(path, data) uri = URI(api_url + path) Net::HTTP.start(uri.host, uri.port) do |http| post = Net::HTTP::Post.new(uri.path) - post.content_type = "application/json" + post.content_type = "application/json".freeze post.basic_auth(app_id, api_key) post.body = data.to_json http.request(post) end end @@ -301,17 +312,19 @@ logger.error("[RorVsWild] " + exception.inspect) logger.error("[RorVsWild] " + exception.backtrace.join("\n[RorVsWild] ")) end end + DASH_PERFORM = "#perform".freeze + module ResquePlugin def around_perform_rorvswild(*args, &block) - RorVsWild.measure_block(to_s + "#perform", &block) + RorVsWild.measure_block(to_s + DASH_PERFORM, &block) end end class SidekiqPlugin def call(worker, item, queue, &block) - RorVsWild.measure_block(item["class"] + "#perform", &block) + RorVsWild.measure_block(item["class".freeze] + DASH_PERFORM, &block) end end end