lib/stackprof-webnav/server.rb in stackprof-webnav-0.1.0 vs lib/stackprof-webnav/server.rb in stackprof-webnav-1.0.0

- old
+ new

@@ -1,98 +1,147 @@ require 'sinatra' require 'haml' require "stackprof" -require 'net/http' require_relative 'presenter' +require_relative 'dump' +require 'pry' +require "sinatra/reloader" if development? +require 'ruby-graphviz' module StackProf module Webnav class Server < Sinatra::Application class << self - attr_accessor :cmd_options, :report_dump_path, :report_dump_uri, :report_dump_listing + attr_accessor :cmd_options + end - def presenter regenerate=false - return @presenter unless regenerate || @presenter.nil? - process_options - if self.report_dump_path || self.report_dump_uri - report_contents = if report_dump_path.nil? - Net::HTTP.get(URI.parse(report_dump_uri)) - else - File.open(report_dump_path).read - end - report = StackProf::Report.new(Marshal.load(report_contents)) - end - @presenter = Presenter.new(report) - end + configure :development do + register Sinatra::Reloader + end - private - def process_options - if cmd_options[:filepath] - self.report_dump_path = cmd_options[:filepath] - elsif cmd_options[:uri] - self.report_dump_uri = cmd_options[:uri] - elsif cmd_options[:bucket] - self.report_dump_listing = cmd_options[:bucket] + configure :production do + set :show_exceptions, false + end + + error do + @error = env['sinatra.error'] + haml :error + end + + before do + unless request.path_info == '/' + if params[:dump] != current_dump.path + current_dump.path = params[:dump] end end - end helpers do - def presenter - Server.presenter + def current_dump + Thread.current[:cache] = {} + Thread.current[params[:dump]] ||= Dump.new(params[:dump]) end - def method_url name - "/method?name=#{URI.escape(name)}" + def current_report + StackProf::Report.new( + Marshal.load(current_dump.content) + ) end - def file_url path - "/file?path=#{URI.escape(path)}" + def presenter + Presenter.new(current_report) end - def overview_url path - "/overview?path=#{URI.escape(path)}" + def ensure_file_generated(path, &block) + return if File.exist?(path) + File.open(path, 'wb', &block) end + + def url_for(path, options={}) + query = URI.encode_www_form({dump: params[:dump]}.merge(options)) + path + "?" + query + end end get '/' do - presenter - if Server.report_dump_listing - redirect '/listing' - else - redirect '/overview' + if Server.cmd_options[:filepath] + query = URI.encode_www_form(dump: Server.cmd_options[:filepath]) + next redirect to("/overview?#{query}") end + + @directory = File.expand_path(Server.cmd_options[:directory] || '.') + @files = Dir.entries(@directory).sort.map do |file| + path = File.expand_path(file, @directory) + + OpenStruct.new( + name: file, + path: path, + modified: File.mtime(path) + ) + end.select do |file| + File.file?(file.path) + end + + haml :index end get '/overview' do - if params[:path] - Server.report_dump_uri = params[:path] - Server.presenter(true) - end - @file = Server.report_dump_path || Server.report_dump_uri @action = "overview" - @frames = presenter.overview_frames - haml :overview + + begin + @frames = presenter.overview_frames + haml :overview + rescue => error + haml :invalid_dump + end end - get '/listing' do - @file = Server.report_dump_listing - @action = "listing" - @dumps = presenter.listing_dumps - haml :listing + get '/flames.json' do + ensure_file_generated(current_dump.flame_graph_path) do |file| + current_report.print_flamegraph(file, true, true) + end + + send_file(current_dump.flame_graph_path, type: 'text/javascript') end + get '/graph.png' do + ensure_file_generated(current_dump.graph_path) do |file| + current_report.print_graphviz({}, file) + end + + ensure_file_generated(current_dump.graph_image_path) do |file| + GraphViz + .parse(current_dump.graph_path) + .output(png: current_dump.graph_image_path) + end + + send_file(current_dump.graph_image_path, type: 'image/png') + end + + get '/graph' do + haml :graph + end + + get '/flamegraph' do + haml :flamegraph + end + get '/method' do @action = params[:name] @frames = presenter.method_info(params[:name]) haml :method end get '/file' do path = params[:path] - @path = path - @data = presenter.file_overview(path) + + if File.exist?(path) + @path = path + @data = presenter.file_overview(path) + else + @data = nil + end + haml :file end end end end