# encoding: utf-8
require 'rack'
require 'rack/request'
require 'rack/response'
require 'rack/file'
require 'one_apm/support/collection_helper'
require 'one_apm/rack/middleware_base'
require 'one_apm/rack/middleware_wrapper'
require 'one_apm/transaction/transaction_sample'
require 'one_apm/transaction/transaction_analysis'
require 'one_apm/rack/developer_mode/helper'
require 'one_apm/collector/support/shell_poller'
module OneApm
module Rack
class DeveloperMode < MiddlewareBase
VIEW_PATH = File.expand_path('../developer_mode/views/', __FILE__)
include OneApm::DeveloperModeHelper
def traced_call(env)
@req = ::Rack::Request.new(env)
@start_memory_used = current_memory_used
return dup._call(env) if /^\/oneapm/ =~ @req.path_info
set_profiled
status, headers, body = @app.call(env)
if status == 200 && headers['Content-Type'] =~ /text\/html/
result = inject_profiler(env, status, headers, body)
return result if result
end
return [status,headers,body]
end
def self.profiled?
@profiled
end
def self.profiled=(profiled)
@profiled = profiled
end
protected
def _call(env)
OneApm::Manager.ignore_transaction
@rendered = false
case @req.path_info
when /assets/
::Rack::File.new(VIEW_PATH).call(env)
when /index/
index
when /threads/
threads
when /reset/
reset
when /show_sample_summary/
show_sample_data
when /show_sample_detail/
show_sample_data
when /show_sample_sql/
show_sample_data
when /show_sample_profile/
show_sample_profile
when /explain_sql/
explain_sql
when /^\/oneapm\/?$/
index
else
@app.call(env)
end
end
private
def set_profiled
DeveloperMode.profiled = params['p'] == 'on'
end
def request_path
@request_path ||= begin
path = @req.path.gsub('/', '-')
path.slice!(0)
path
end
end
def inject_profiler(env, status, headers, body)
# mini profiler is meddling with stuff, we can not cache cause we will get incorrect data
# Rack::ETag has already inserted some nonesense in the chain
content_type = headers['Content-Type']
if content_type =~ /text\/html/
body = get_and_inject_profile(body)
response = ::Rack::Response.new([], status, headers)
if String === body
response.write body
else
body.each { |fragment| response.write fragment }
end
body.close if body.respond_to? :close
response.finish
else
nil
end
end
def get_and_inject_profile body
inject_page!(body, stylesheets, :postion => :head)
inject_page!(body, javascripts(body))
inject_page!(body, slide_templates)
body
end
def javascripts body
script = ""
script_files = ["javascript/jquery.min.js", "javascript/layer.js", "javascript/functions.js" ]
script_files.shift if body.body[0] =~ /jquery(.min)?/ rescue false
script_files.each do |sf|
script << "\r\n"
end
script
end
def stylesheets
stylesheets = []
stylesheets << ""
stylesheets << ""
stylesheets.join("\r\n")
end
def slide_templates
template = read_script_file "#{VIEW_PATH}/oneapm/slide.tmpl"
samples = ""
duration = current_duration
memory_used = current_memory_used - @start_memory_used
samples = "