# frozen_string_literal: true module Rack class MiniProfiler module Views def resources_root @resources_root ||= ::File.expand_path("../../html", __FILE__) end def share_template @share_template ||= ERB.new(::File.read(::File.expand_path("../html/share.html", ::File.dirname(__FILE__)))) end def generate_html(page_struct, env, result_json = page_struct.to_json) # double-assigning to suppress "assigned but unused variable" warnings path = path = "#{env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME']}#{@config.base_url_path}" version = version = MiniProfiler::ASSET_VERSION json = json = result_json includes = includes = get_profile_script(env) name = name = page_struct[:name] duration = duration = page_struct.duration_ms.round(1).to_s share_template.result(binding) end # get_profile_script returns script to be injected inside current html page # By default, profile_script is appended to the end of all html requests automatically. # Calling get_profile_script cancels automatic append for the current page # Use it when: # * you have disabled auto append behaviour throught :auto_inject => false flag # * you do not want script to be automatically appended for the current page. You can also call cancel_auto_inject def get_profile_script(env) path = public_base_path(env) version = MiniProfiler::ASSET_VERSION if @config.assets_url url = @config.assets_url.call('rack-mini-profiler.js', version, env) css_url = @config.assets_url.call('rack-mini-profiler.css', version, env) end url = "#{path}includes.js?v=#{version}" if !url css_url = "#{path}includes.css?v=#{version}" if !css_url content_security_policy_nonce = @config.content_security_policy_nonce || env["action_dispatch.content_security_policy_nonce"] || env["secure_headers_content_security_policy_nonce"] settings = { path: path, url: url, cssUrl: css_url, version: version, verticalPosition: @config.vertical_position, horizontalPosition: @config.horizontal_position, showTrivial: @config.show_trivial, showChildren: @config.show_children, maxTracesToShow: @config.max_traces_to_show, showControls: @config.show_controls, showTotalSqlCount: @config.show_total_sql_count, authorized: true, toggleShortcut: @config.toggle_shortcut, startHidden: @config.start_hidden, collapseResults: @config.collapse_results, htmlContainer: @config.html_container, hiddenCustomFields: @config.snapshot_hidden_custom_fields.join(','), cspNonce: content_security_policy_nonce, hotwireTurboDriveSupport: @config.enable_hotwire_turbo_drive_support, } if current && current.page_struct settings[:ids] = ids_comma_separated(env) settings[:currentId] = current.page_struct[:id] else settings[:ids] = [] settings[:currentId] = "" end # TODO : cache this snippet script = ::File.read(::File.expand_path('../html/profile_handler.js', ::File.dirname(__FILE__))) # replace the variables settings.each do |k, v| regex = Regexp.new("\\{#{k.to_s}\\}") script.gsub!(regex, v.to_s) end current.inject_js = false if current script end BLANK_PAGE = <<~HTML
This is the help menu of the rack-mini-profiler gem, append the following to your query string for more options: #{make_link "help", env} : display this screen #{make_link "env", env} : display the rack environment #{make_link "skip", env} : skip mini profiler for this request #{make_link "no-backtrace", env} #{"(*) " if client_settings.backtrace_none?}: don't collect stack traces from all the SQL executed (sticky, use #{@config.profile_parameter}=normal-backtrace to enable) #{make_link "normal-backtrace", env} #{"(*) " if client_settings.backtrace_default?}: collect stack traces from all the SQL executed and filter normally #{make_link "full-backtrace", env} #{"(*) " if client_settings.backtrace_full?}: enable full backtraces for SQL executed (use #{@config.profile_parameter}=normal-backtrace to disable) #{make_link "disable", env} : disable profiling for this session #{make_link "enable", env} : enable profiling for this session (if previously disabled) #{make_link "profile-gc", env} : perform gc profiling on this request, analyzes ObjectSpace generated by request #{make_link "profile-memory", env} : requires the memory_profiler gem, new location based report #{make_link "flamegraph", env} : a graph representing sampled activity (requires the stackprof gem). #{make_link "async-flamegraph", env} : store flamegraph data for this page and all its AJAX requests. Flamegraph links will be available in the mini-profiler UI (requires the stackprof gem). #{make_link "flamegraph&flamegraph_sample_rate=1", env}: creates a flamegraph with the specified sample rate (in ms). Overrides value set in config #{make_link "flamegraph&flamegraph_mode=cpu", env}: creates a flamegraph with the specified mode (one of cpu, wall, object, or custom). Overrides value set in config #{make_link "flamegraph&flamegraph_ignore_gc=true", env}: ignore garbage collection frames in flamegraphs. Overrides value set in config #{make_link "flamegraph_embed", env} : a graph representing sampled activity (requires the stackprof gem), embedded resources for use on an intranet. #{make_link "trace-exceptions", env} : will return all the spots where your application raises exceptions #{make_link "analyze-memory", env} : will perform basic memory analysis of heap All features can also be accessed by adding the X-Rack-Mini-Profiler header to the request, with any of the values above (e.g. 'X-Rack-Mini-Profiler: flamegraph')HTML [200, headers, [html]] end def url_for_snapshots_group(group_name) qs = Rack::Utils.build_query({ group_name: group_name }) "/#{@config.base_url_path.gsub('/', '')}/snapshots?#{qs}" end def url_for_snapshot(id, group_name) qs = Rack::Utils.build_query({ id: id, group: group_name }) "/#{@config.base_url_path.gsub('/', '')}/results?#{qs}" end def public_base_path(env) "#{env['RACK_MINI_PROFILER_ORIGINAL_SCRIPT_NAME']}#{@config.base_url_path}" end end end end