File: controller_helpers.rb

package info (click to toggle)
ruby-peek-rblineprof 0.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 124 kB
  • sloc: ruby: 139; javascript: 5; makefile: 4
file content (136 lines) | stat: -rw-r--r-- 4,275 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
begin
  require 'pygments.rb'
rescue LoadError
  # Doesn't have pygments.rb installed
end

require 'rack/utils'

module Peek
  module Rblineprof
    module ControllerHelpers
      extend ActiveSupport::Concern

      included do
        around_action :inject_rblineprof, :if => [:peek_enabled?, :rblineprof_enabled?]
      end

      protected

      def pygmentize?
        defined?(Pygments)
      end

      def pygmentize(file_name, code, lexer = nil)
        if pygmentize? && lexer.present?
          Pygments.highlight(code, :lexer => lexer_for_filename(file_name))
        else
          "<pre>#{Rack::Utils.escape_html(code)}</pre>"
        end
      end

      def rblineprof_enabled?
        params[:lineprofiler].present?
      end

      def lexer_for_filename(file_name)
        case file_name
        when /\.rb$/ then 'ruby'
        when /\.erb$/ then 'erb'
        end
      end

      def rblineprof_profiler_regex
        escaped_rails_root = Regexp.escape(Rails.root.to_s)
        case params[:lineprofiler]
        when 'app'
          %r{^#{escaped_rails_root}/(app|lib)}
        when 'views'
          %r{^#{escaped_rails_root}/app/view}
        when 'gems'
          %r|^#{escaped_rails_root}/vendor/gems|
        when 'all'
          %r|^#{escaped_rails_root}|
        when 'stdlib'
          %r|^#{Regexp.escape RbConfig::CONFIG['rubylibdir']}|
        else
          %r{^#{escaped_rails_root}/(app|config|lib|vendor/plugin)}
        end
      end

      def inject_rblineprof
        ret = nil
        profile = lineprof(rblineprof_profiler_regex) do
          ret = yield
        end

        if response.content_type =~ %r|text/html|
          sort = params[:lineprofiler_sort]
          mode = params[:lineprofiler_mode] || 'cpu'
          min  = (params[:lineprofiler_min] || 5).to_i * 1000
          summary = params[:lineprofiler_summary]

          # Sort each file by the longest calculated time
          per_file = profile.map do |file, lines|
            total, child, excl, total_cpu, child_cpu, excl_cpu = lines[0]

            wall = summary == 'exclusive' ? excl : total
            cpu  = summary == 'exclusive' ? excl_cpu : total_cpu
            idle = summary == 'exclusive' ? (excl - excl_cpu) : (total - total_cpu)

            [
              file, lines,
              wall, cpu, idle,
              sort == 'idle' ? idle : sort == 'cpu' ? cpu : wall
            ]
          end.sort_by{ |a,b,c,d,e,f| -f }

          output = ''
          per_file.each do |file_name, lines, file_wall, file_cpu, file_idle, file_sort|

            output << "<div class='peek-rblineprof-file'><div class='heading'>"

            show_src = file_sort > min
            tmpl = show_src ? "<a href='#' class='js-lineprof-file'>%s</a>" : "%s"

            if mode == 'cpu'
              output << sprintf("<span class='duration'>% 8.1fms + % 8.1fms</span> #{tmpl}", file_cpu / 1000.0, file_idle / 1000.0, file_name.sub(Rails.root.to_s + '/', ''))
            else
              output << sprintf("<span class='duration'>% 8.1fms</span> #{tmpl}", file_wall/1000.0, file_name.sub(Rails.root.to_s + '/', ''))
            end

            output << "</div>" # .heading

            next unless show_src

            output << "<div class='data'>"
            code = []
            times = []
            File.readlines(file_name).each_with_index do |line, i|
              code << line
              wall, cpu, calls = lines[i + 1]

              if calls && calls > 0
                if mode == 'cpu'
                  idle = wall - cpu
                  times << sprintf("% 8.1fms + % 8.1fms (% 5d)", cpu / 1000.0, idle / 1000.0, calls)
                else
                  times << sprintf("% 8.1fms (% 5d)", wall / 1000.0, calls)
                end
              else
                times << ' '
              end
            end
            output << "<pre class='duration'>#{times.join("\n")}</pre>"
            output << "<div class='code'>#{pygmentize(file_name, code.join, 'ruby')}</div>"
            output << "</div></div>" # .data then .peek-rblineprof-file
          end

          response.body += "<div class='peek-rblineprof-modal' id='line-profile'>#{output}</div>".html_safe
        end

        ret
      end
    end
  end
end