class OneApm::Rack::DeveloperMode

Constants

OA_VIEW_PATH

Public Class Methods

profiled=(profiled) click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 43
def self.profiled=(profiled)
  @profiled = profiled
end
profiled?() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 39
def self.profiled?
  @profiled 
end

Public Instance Methods

traced_call(env) click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 26
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

Protected Instance Methods

_call(env) click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 49
def _call(env)
  OneApm::Manager.ignore_transaction

  @rendered = false
  case @req.path_info
  when /assets/
    ::Rack::File.new(OA_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 Instance Methods

content_tag(tag, contents, opts={}) click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 284
def content_tag(tag, contents, opts={}) 
  opt_values = opts.map {|k, v| "#{k}=\"#{v}\"" }.join(' ')
  "<#{tag} #{opt_values}>#{contents}</#{tag}>"
end
current_duration() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 345
def current_duration
  Time.now.to_f - OneApm::TransactionState.tl_get.transaction_sample_builder.sample_start
end
current_memory_used() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 349
def current_memory_used
  @memory_sampler ||= OneApm::Collector::Samplers::MemorySampler.new
  @shell_poller ||= OneApm::Collector::ShellPoller.new
  @memory_sampler.set_poller(@shell_poller) 
  @memory_sampler.get_sample
end
current_sample_guid() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 145
def current_sample_guid
  current_transaction = OneApm::TransactionState.tl_get.current_transaction
  current_transaction.guid
end
explain_sql() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 205
def explain_sql
  get_segment

  return render(:sample_not_found) unless @sample

  @sql = @segment[:sql]
  @trace = @segment[:backtrace]

  if OneApm::Manager.agent.record_sql == :obfuscated
    @obfuscated_sql = @segment.obfuscated_sql
  end

  _headers, explanations = @segment.explain_sql
  if explanations
    @explanation = explanations
    if !@explanation.blank?
      if @explanation.first.length < OneApm::OA_MYSQL_EXPLAIN_COLUMNS.length
        @row_headers = nil
      else
        @row_headers = OneApm::OA_MYSQL_EXPLAIN_COLUMNS
      end
    end
  end

  render(:explain_sql)
end
get_and_inject_profile(source) click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 105
def get_and_inject_profile source
  inject_page!(source, stylesheets, :postion => :head)
  inject_page!(source, javascripts(source))
  inject_page!(source, slide_templates)
  source
end
get_sample() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 332
def get_sample
  get_samples
  @sample = @samples.select{|sample| sample.sample_id == params['id'].to_i || sample.guid == params['guid']}.first       
end
get_samples() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 322
def get_samples
  @samples = OneApm::Manager.agent.transaction_sampler.dev_mode_sample_buffer.samples.select do |sample|
    sample.params[:path] != nil
  end

  return @samples = @samples.sort_by(&:duration).reverse                   if params['h']
  return @samples = @samples.sort{|x,y| x.params[:uri] <=> y.params[:uri]} if params['u']
  @samples = @samples.reverse
end
get_segment() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 337
def get_segment
  get_sample
  return unless @sample

  segment_id = params['segment'].to_i
  @segment = @sample.find_segment(segment_id)
end
get_transaction_samples() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 139
def get_transaction_samples
  return get_samples if last_sample_id <= 0
  index = get_samples.find_index{|sample|sample.sample_id == last_sample_id}
  index.nil? ? get_samples : get_samples[0...index]
end
index() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 194
def index
  get_samples
  render(:index)
end
inject!(fragment, script, options = {}) click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 167
def inject!(fragment, script, options = {})
  if options[:postion] == :head && fragment.match(/<\/head>/i)
    regex = /<\/head>/i
    close_tag = '</head>'
  elsif options[:postion] == :body && fragment.match(/<\/body>/i)
      regex = /<\/body>/i
      close_tag = '</body>'
  else
    return fragment
  end

  matches = fragment.scan(regex).length
  index = 1
  fragment.gsub!(regex) do
    if index < matches
      index += 1
      close_tag
    else
      if script.respond_to?(:encoding) && script.respond_to?(:force_encoding)
        (script + close_tag).force_encoding(fragment.encoding)
      else
        script + close_tag
      end
    end
  end
end
inject_page!(body, script, options = {:postion => :body}) click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 158
def inject_page! body, script, options = {:postion => :body}
  inject!(body, script, options)
end
inject_profiler(env, status, headers, body) click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 93
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
  source = gather_source(body)
  close_old_response(body)
  return nil unless source
  response_string = get_and_inject_profile(source)
  return nil unless response_string
  response = ::Rack::Response.new(response_string, status, headers)
  response.finish
end
javascripts(body) click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 112
def javascripts body
  script = ""
  script_files = ["javascript/jquery.min.js", "javascript/layer.js", "javascript/functions.js" ]
  script_files.shift if body =~ /jquery(.min)?/ rescue false
  script_files.each do |sf|
    script << "<script src=\"/oneapm/assets/#{sf}\"></script>\r\n"
  end
  script
end
last_sample_id() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 150
def last_sample_id
  Thread.current[:last_sample_id].to_i
end
last_sample_id=(sample_id) click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 154
def last_sample_id= sample_id
  Thread.current[:last_sample_id] = sample_id.to_i
end
params() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 293
def params
  @req.params
end
read_script_file(file_path) click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 162
def read_script_file file_path
  IO.read(::File.expand_path(file_path, ::File.dirname(__FILE__)))
end
render(view, layout=true) click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 236
def render(view, layout=true)
  add_rack_array = true
  if view.is_a? Hash
    layout = false
    if view[:object]
      # object *is* used here, as it is capture in the binding below
      object = view[:object]
    end

    if view[:collection]
      return view[:collection].map do |obj|
        render({:partial => view[:partial], :object => obj})
      end.join(' ')
    end

    if view[:partial]
      add_rack_array = false
      view = "_#{view[:partial]}"
    end
  end
  binding = Proc.new {}.binding
  if layout
    body = render_with_layout(view) do
      render_without_layout(view, binding)
    end
  else
    body = render_without_layout(view, binding)
  end
  if add_rack_array
    ::Rack::Response.new(body, 200, {'Content-Type' => 'text/html'}).finish
  else
    body
  end
end
render_with_layout(view) click to toggle source

You have to call this with a block - the contents returned from that block are interpolated into the layout

# File lib/one_apm/rack/developer_mode.rb, line 273
def render_with_layout(view)
  body = ERB.new(File.read(File.join(OA_VIEW_PATH, 'oneapm/layout.html.erb')))
  body.result(Proc.new {}.binding)
end
render_without_layout(view, binding) click to toggle source

you have to pass a binding to this (a proc) so that ERB can have access to helper functions and local variables

# File lib/one_apm/rack/developer_mode.rb, line 280
def render_without_layout(view, binding)
  ERB.new(File.read(File.join(OA_VIEW_PATH, 'oneapm', view.to_s + '.html.erb')), nil, nil, 'frobnitz').result(binding)
end
request_path() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 85
def request_path
  @request_path ||= begin
    path = @req.path.gsub('/', '-')
    path.slice!(0)
    path
  end
end
reset() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 199
def reset
  OneApm::Manager.agent.transaction_sampler.reset!
  OneApm::Manager.agent.sql_sampler.reset!
  ::Rack::Response.new{|r| r.redirect('/oneapm/')}.finish
end
sample() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 289
def sample
  @sample || @samples[0]
end
segment() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 297
def segment
  @segment
end
set_profiled() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 81
def set_profiled
  DeveloperMode.profiled = params['p'] == 'on'
end
show_sample_data() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 309
def show_sample_data
  get_sample
  return render(:sample_not_found) unless @sample
  controller_metric = @sample.transaction_name
  @sample_controller_name = controller_metric
  @sql_segments = @sample.sql_segments
  if params['d']
    @sql_segments.sort!{|a,b| b.duration <=> a.duration }
  end

  render(:show_sample)
end
show_sample_profile() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 301
def show_sample_profile
  get_sample
  return render(:sample_not_found) unless @sample
  sort_method = params['sort'] || :total_time
  @profile_options = {:min_percent => 0.5, :sort_method => sort_method.to_sym}
  render(:show_sample_profile, false)
end
slide_templates() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 129
def slide_templates
  template = read_script_file "#{OA_VIEW_PATH}/oneapm/slide.tmpl"
  samples  = ""

  duration = current_duration
  memory_used = current_memory_used - @start_memory_used
  samples = "<a href=\"#\" data-guid=\"#{current_sample_guid}\" data-uri=\"#{@req.path_info}\" data-duration=\"#{(duration * 1000).round(2)}\" data-memory=\"#{memory_used.round(2)}\"><li>#{(duration * 1000).round(2)} ms</li></a>"
  template.gsub(/\{samples\}/, samples)
end
stylesheets() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 122
def stylesheets
  stylesheets = []
  stylesheets << "<link rel=\"stylesheet\" media=\"all\" href=\"/oneapm/assets/stylesheets/menus.css\" />"
  stylesheets << "<link rel=\"stylesheet\" media=\"all\" href=\"/oneapm/assets/stylesheets/layer.css\" />"
  stylesheets.join("\r\n")
end
threads() click to toggle source
# File lib/one_apm/rack/developer_mode.rb, line 232
def threads
  render(:threads)
end