mini-sharp-hub 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/mini-sharp-hub.gemspec +12 -0
  3. data/rack-mini-profiler-4.0.1/CHANGELOG.md +424 -0
  4. data/rack-mini-profiler-4.0.1/README.md +542 -0
  5. data/rack-mini-profiler-4.0.1/lib/enable_rails_patches.rb +5 -0
  6. data/rack-mini-profiler-4.0.1/lib/generators/rack_mini_profiler/USAGE +9 -0
  7. data/rack-mini-profiler-4.0.1/lib/generators/rack_mini_profiler/install_generator.rb +13 -0
  8. data/rack-mini-profiler-4.0.1/lib/generators/rack_mini_profiler/templates/rack_mini_profiler.rb +8 -0
  9. data/rack-mini-profiler-4.0.1/lib/generators/rack_profiler/USAGE +2 -0
  10. data/rack-mini-profiler-4.0.1/lib/generators/rack_profiler/install_generator.rb +16 -0
  11. data/rack-mini-profiler-4.0.1/lib/html/dot.1.1.2.min.js +2 -0
  12. data/rack-mini-profiler-4.0.1/lib/html/includes.css +474 -0
  13. data/rack-mini-profiler-4.0.1/lib/html/includes.js +1520 -0
  14. data/rack-mini-profiler-4.0.1/lib/html/includes.scss +698 -0
  15. data/rack-mini-profiler-4.0.1/lib/html/includes.tmpl +333 -0
  16. data/rack-mini-profiler-4.0.1/lib/html/pretty-print.js +810 -0
  17. data/rack-mini-profiler-4.0.1/lib/html/profile_handler.js +1 -0
  18. data/rack-mini-profiler-4.0.1/lib/html/rack-mini-profiler.css +3 -0
  19. data/rack-mini-profiler-4.0.1/lib/html/rack-mini-profiler.js +2 -0
  20. data/rack-mini-profiler-4.0.1/lib/html/share.html +10 -0
  21. data/rack-mini-profiler-4.0.1/lib/html/speedscope/LICENSE +21 -0
  22. data/rack-mini-profiler-4.0.1/lib/html/speedscope/README.md +3 -0
  23. data/rack-mini-profiler-4.0.1/lib/html/speedscope/demangle-cpp.1768f4cc.js +4 -0
  24. data/rack-mini-profiler-4.0.1/lib/html/speedscope/favicon-16x16.f74b3187.png +0 -0
  25. data/rack-mini-profiler-4.0.1/lib/html/speedscope/favicon-32x32.bc503437.png +0 -0
  26. data/rack-mini-profiler-4.0.1/lib/html/speedscope/file-format-schema.json +324 -0
  27. data/rack-mini-profiler-4.0.1/lib/html/speedscope/fonts/source-code-pro-regular.css +8 -0
  28. data/rack-mini-profiler-4.0.1/lib/html/speedscope/fonts/source-code-pro-v13-regular.woff +0 -0
  29. data/rack-mini-profiler-4.0.1/lib/html/speedscope/fonts/source-code-pro-v13-regular.woff2 +0 -0
  30. data/rack-mini-profiler-4.0.1/lib/html/speedscope/import.8ae8aa3d.js +123 -0
  31. data/rack-mini-profiler-4.0.1/lib/html/speedscope/index.html +2 -0
  32. data/rack-mini-profiler-4.0.1/lib/html/speedscope/release.txt +3 -0
  33. data/rack-mini-profiler-4.0.1/lib/html/speedscope/reset.8c46b7a1.css +2 -0
  34. data/rack-mini-profiler-4.0.1/lib/html/speedscope/source-map.438fa06b.js +24 -0
  35. data/rack-mini-profiler-4.0.1/lib/html/speedscope/speedscope.f27db165.js +193 -0
  36. data/rack-mini-profiler-4.0.1/lib/html/vendor.js +848 -0
  37. data/rack-mini-profiler-4.0.1/lib/mini_profiler/actions.rb +157 -0
  38. data/rack-mini-profiler-4.0.1/lib/mini_profiler/asset_version.rb +6 -0
  39. data/rack-mini-profiler-4.0.1/lib/mini_profiler/client_settings.rb +127 -0
  40. data/rack-mini-profiler-4.0.1/lib/mini_profiler/config.rb +146 -0
  41. data/rack-mini-profiler-4.0.1/lib/mini_profiler/context.rb +14 -0
  42. data/rack-mini-profiler-4.0.1/lib/mini_profiler/gc_profiler.rb +158 -0
  43. data/rack-mini-profiler-4.0.1/lib/mini_profiler/profiling_methods.rb +167 -0
  44. data/rack-mini-profiler-4.0.1/lib/mini_profiler/snapshots_transporter.rb +111 -0
  45. data/rack-mini-profiler-4.0.1/lib/mini_profiler/storage/abstract_store.rb +97 -0
  46. data/rack-mini-profiler-4.0.1/lib/mini_profiler/storage/file_store.rb +179 -0
  47. data/rack-mini-profiler-4.0.1/lib/mini_profiler/storage/memcache_store.rb +105 -0
  48. data/rack-mini-profiler-4.0.1/lib/mini_profiler/storage/memory_store.rb +233 -0
  49. data/rack-mini-profiler-4.0.1/lib/mini_profiler/storage/redis_store.rb +353 -0
  50. data/rack-mini-profiler-4.0.1/lib/mini_profiler/storage.rb +7 -0
  51. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct/base.rb +39 -0
  52. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct/client.rb +90 -0
  53. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct/custom.rb +25 -0
  54. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct/page.rb +146 -0
  55. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct/request.rb +186 -0
  56. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct/sql.rb +89 -0
  57. data/rack-mini-profiler-4.0.1/lib/mini_profiler/timer_struct.rb +8 -0
  58. data/rack-mini-profiler-4.0.1/lib/mini_profiler/version.rb +8 -0
  59. data/rack-mini-profiler-4.0.1/lib/mini_profiler/views.rb +198 -0
  60. data/rack-mini-profiler-4.0.1/lib/mini_profiler.rb +670 -0
  61. data/rack-mini-profiler-4.0.1/lib/mini_profiler_rails/railtie.rb +234 -0
  62. data/rack-mini-profiler-4.0.1/lib/mini_profiler_rails/railtie_methods.rb +61 -0
  63. data/rack-mini-profiler-4.0.1/lib/patches/db/activerecord.rb +44 -0
  64. data/rack-mini-profiler-4.0.1/lib/patches/db/mongo.rb +18 -0
  65. data/rack-mini-profiler-4.0.1/lib/patches/db/moped.rb +14 -0
  66. data/rack-mini-profiler-4.0.1/lib/patches/db/mysql2/alias_method.rb +30 -0
  67. data/rack-mini-profiler-4.0.1/lib/patches/db/mysql2/prepend.rb +34 -0
  68. data/rack-mini-profiler-4.0.1/lib/patches/db/mysql2.rb +7 -0
  69. data/rack-mini-profiler-4.0.1/lib/patches/db/neo4j.rb +16 -0
  70. data/rack-mini-profiler-4.0.1/lib/patches/db/nobrainer.rb +31 -0
  71. data/rack-mini-profiler-4.0.1/lib/patches/db/oracle_enhanced.rb +70 -0
  72. data/rack-mini-profiler-4.0.1/lib/patches/db/pg/alias_method.rb +121 -0
  73. data/rack-mini-profiler-4.0.1/lib/patches/db/pg/prepend.rb +115 -0
  74. data/rack-mini-profiler-4.0.1/lib/patches/db/pg.rb +7 -0
  75. data/rack-mini-profiler-4.0.1/lib/patches/db/plucky.rb +49 -0
  76. data/rack-mini-profiler-4.0.1/lib/patches/db/riak.rb +105 -0
  77. data/rack-mini-profiler-4.0.1/lib/patches/db/rsolr.rb +26 -0
  78. data/rack-mini-profiler-4.0.1/lib/patches/db/sequel.rb +12 -0
  79. data/rack-mini-profiler-4.0.1/lib/patches/net_patches.rb +27 -0
  80. data/rack-mini-profiler-4.0.1/lib/patches/sql_patches.rb +74 -0
  81. data/rack-mini-profiler-4.0.1/lib/prepend_mysql2_patch.rb +5 -0
  82. data/rack-mini-profiler-4.0.1/lib/prepend_net_http_patch.rb +5 -0
  83. data/rack-mini-profiler-4.0.1/lib/prepend_pg_patch.rb +5 -0
  84. data/rack-mini-profiler-4.0.1/lib/rack-mini-profiler.rb +13 -0
  85. data/rack-mini-profiler-4.0.1/rack-mini-profiler.gemspec +49 -0
  86. metadata +125 -0
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class MiniProfiler
5
+ module TimerStruct
6
+
7
+ # This class holds the client timings
8
+ class Client < TimerStruct::Base
9
+
10
+ def self.init_instrumentation
11
+ %Q{
12
+ <script type="text/javascript">
13
+ mPt=function(){var t=[];return{t:t,probe:function(n){t.push({d:new Date(),n:n})}}}()
14
+ </script>
15
+ }
16
+ end
17
+
18
+ # used by Railtie to instrument asset_tag for JS / CSS
19
+ def self.instrument(name, orig)
20
+ probe = "<script>mPt.probe('#{name}')</script>".dup
21
+ wrapped = probe
22
+ wrapped << orig
23
+ wrapped << probe
24
+ wrapped
25
+ end
26
+
27
+ def initialize(env = {})
28
+ super
29
+ end
30
+
31
+ def redirect_count
32
+ self[:redirect_count]
33
+ end
34
+
35
+ def timings
36
+ self[:timings]
37
+ end
38
+
39
+ def self.init_from_form_data(env, page_struct)
40
+ timings = []
41
+ clientTimes, clientPerf, baseTime = nil
42
+ form = env['rack.request.form_hash']
43
+
44
+ clientPerf = form['clientPerformance'] if form
45
+ clientTimes = clientPerf['timing'] if clientPerf
46
+ baseTime = clientTimes['navigationStart'].to_i if clientTimes
47
+ return unless clientTimes && baseTime
48
+
49
+ probes = form['clientProbes']
50
+ translated = {}
51
+ if probes && !["null", ""].include?(probes)
52
+ probes.each do |id, val|
53
+ name = val["n"]
54
+ translated[name] ||= {}
55
+ if translated[name][:start]
56
+ translated[name][:finish] = val["d"]
57
+ else
58
+ translated[name][:start] = val["d"]
59
+ end
60
+ end
61
+ end
62
+
63
+ translated.each do |name, data|
64
+ h = { "Name" => name, "Start" => data[:start].to_i - baseTime }
65
+ h["Duration"] = data[:finish].to_i - data[:start].to_i if data[:finish]
66
+ timings.push(h)
67
+ end
68
+
69
+ clientTimes.keys.find_all { |k| k =~ /Start$/ }.each do |k|
70
+ start = clientTimes[k].to_i - baseTime
71
+ finish = clientTimes[k.sub(/Start$/, "End")].to_i - baseTime
72
+ duration = 0
73
+ duration = finish - start if finish > start
74
+ name = k.sub(/Start$/, "").split(/(?=[A-Z])/).map { |s| s.capitalize }.join(' ')
75
+ timings.push("Name" => name, "Start" => start, "Duration" => duration) if start >= 0
76
+ end
77
+
78
+ clientTimes.keys.find_all { |k| !(k =~ /(End|Start)$/) }.each do |k|
79
+ timings.push("Name" => k, "Start" => clientTimes[k].to_i - baseTime, "Duration" => -1)
80
+ end
81
+
82
+ TimerStruct::Client.new.tap do |rval|
83
+ rval[:redirect_count] = env['rack.request.form_hash']['clientPerformance']['navigation']['redirect_count']
84
+ rval[:timings] = timings
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class MiniProfiler
5
+ module TimerStruct
6
+ # Timing system for a custom timers such as cache, redis, RPC, external API
7
+ # calls, etc.
8
+ class Custom < TimerStruct::Base
9
+ attr_accessor :parent
10
+ def initialize(type, duration_ms, page, parent)
11
+ @parent = parent
12
+ @page = page
13
+ @type = type
14
+ start_millis = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1000).to_i - page[:started]) - duration_ms
15
+ super(
16
+ type: type,
17
+ start_milliseconds: start_millis,
18
+ duration_milliseconds: duration_ms,
19
+ parent_timing_id: nil
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class MiniProfiler
5
+ module TimerStruct
6
+
7
+ # TimerStruct::Page
8
+ # Root: TimerStruct::Request
9
+ # :has_many TimerStruct::Request children
10
+ # :has_many TimerStruct::Sql children
11
+ # :has_many TimerStruct::Custom children
12
+ class Page < TimerStruct::Base
13
+ class << self
14
+ def from_hash(hash)
15
+ hash = symbolize_hash(hash)
16
+ if hash.key?(:custom_timing_names)
17
+ hash[:custom_timing_names] = []
18
+ end
19
+ hash.delete(:started_formatted)
20
+ if hash.key?(:duration_milliseconds)
21
+ hash[:duration_milliseconds] = 0
22
+ end
23
+ page = self.allocate
24
+ page.instance_variable_set(:@attributes, hash)
25
+ page
26
+ end
27
+
28
+ private
29
+
30
+ def symbolize_hash(hash)
31
+ new_hash = {}
32
+ hash.each do |k, v|
33
+ sym_k = String === k ? k.to_sym : k
34
+ if Hash === v
35
+ new_hash[sym_k] = symbolize_hash(v)
36
+ elsif Array === v
37
+ new_hash[sym_k] = symbolize_array(v)
38
+ else
39
+ new_hash[sym_k] = v
40
+ end
41
+ end
42
+ new_hash
43
+ end
44
+
45
+ def symbolize_array(array)
46
+ array.map do |item|
47
+ if Array === item
48
+ symbolize_array(item)
49
+ elsif Hash === item
50
+ symbolize_hash(item)
51
+ else
52
+ item
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ attr_reader :attributes
59
+
60
+ def initialize(env)
61
+ timer_id = MiniProfiler.generate_id
62
+ started_at = (Time.now.to_f * 1000).to_i
63
+ started = (Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1000).to_i
64
+ machine_name = env['SERVER_NAME']
65
+ super(
66
+ id: timer_id,
67
+ name: page_name(env),
68
+ started: started,
69
+ started_at: started_at,
70
+ machine_name: machine_name,
71
+ level: 0,
72
+ user: "unknown user",
73
+ has_user_viewed: false,
74
+ client_timings: nil,
75
+ duration_milliseconds: 0,
76
+ has_trivial_timings: true,
77
+ has_all_trivial_timings: false,
78
+ trivial_duration_threshold_milliseconds: 2,
79
+ head: nil,
80
+ sql_count: 0,
81
+ cached_sql_count: 0,
82
+ duration_milliseconds_in_sql: 0,
83
+ has_sql_timings: true,
84
+ has_duplicate_sql_timings: false,
85
+ executed_readers: 0,
86
+ executed_scalars: 0,
87
+ executed_non_queries: 0,
88
+ custom_timing_names: [],
89
+ custom_timing_stats: {},
90
+ custom_fields: {},
91
+ has_flamegraph: false,
92
+ flamegraph: nil
93
+ )
94
+ self[:request_method] = env['REQUEST_METHOD']
95
+ self[:request_path] = env['PATH_INFO']
96
+ name = "#{env['REQUEST_METHOD']} http://#{env['SERVER_NAME']}:#{env['SERVER_PORT']}#{env['SCRIPT_NAME']}#{page_name(env)}"
97
+ self[:root] = TimerStruct::Request.createRoot(name, self)
98
+ end
99
+
100
+ def name
101
+ @attributes[:name]
102
+ end
103
+
104
+ def page_name(env)
105
+ if env['QUERY_STRING'] && env['QUERY_STRING'] != ""
106
+ env['PATH_INFO'] + "?" + env['QUERY_STRING']
107
+ else
108
+ env['PATH_INFO']
109
+ end
110
+ end
111
+
112
+ def duration_ms
113
+ @attributes[:root][:duration_milliseconds]
114
+ end
115
+
116
+ def duration_ms_in_sql
117
+ @attributes[:duration_milliseconds_in_sql]
118
+ end
119
+
120
+ def root
121
+ @attributes[:root]
122
+ end
123
+
124
+ def attributes_to_serialize
125
+ @attributes.keys - [:flamegraph]
126
+ end
127
+
128
+ def to_json(*a)
129
+ ::JSON.generate(@attributes.slice(*attributes_to_serialize).merge(extra_json))
130
+ end
131
+
132
+ def as_json(options = nil)
133
+ super(options).slice(*attributes_to_serialize.map(&:to_s)).merge!(extra_json)
134
+ end
135
+
136
+ def extra_json
137
+ {
138
+ started_formatted: '/Date(%d)/' % @attributes[:started_at],
139
+ duration_milliseconds: @attributes[:root][:duration_milliseconds],
140
+ custom_timing_names: @attributes[:custom_timing_stats].keys.sort
141
+ }
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class MiniProfiler
5
+ module TimerStruct
6
+ class Request < TimerStruct::Base
7
+
8
+ def self.createRoot(name, page)
9
+ TimerStruct::Request.new(name, page, nil).tap do |timer|
10
+ timer[:is_root] = true
11
+ end
12
+ end
13
+
14
+ attr_accessor :children_duration, :start, :parent
15
+
16
+ def initialize(name, page, parent)
17
+ start_millis = (Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1000).to_i - page[:started]
18
+ depth = parent ? parent.depth + 1 : 0
19
+ super(
20
+ id: MiniProfiler.generate_id,
21
+ name: name,
22
+ duration_milliseconds: 0,
23
+ duration_without_children_milliseconds: 0,
24
+ start_milliseconds: start_millis,
25
+ parent_timing_id: nil,
26
+ children: [],
27
+ has_children: false,
28
+ key_values: nil,
29
+ has_sql_timings: false,
30
+ has_duplicate_sql_timings: false,
31
+ trivial_duration_threshold_milliseconds: 2,
32
+ sql_timings: [],
33
+ sql_timings_duration_milliseconds: 0,
34
+ is_trivial: false,
35
+ is_root: false,
36
+ depth: depth,
37
+ executed_readers: 0,
38
+ executed_scalars: 0,
39
+ executed_non_queries: 0,
40
+ custom_timing_stats: {},
41
+ custom_timings: {}
42
+ )
43
+ @children_duration = 0
44
+ @start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
45
+ @parent = parent
46
+ @page = page
47
+ end
48
+
49
+ def name
50
+ @attributes[:name]
51
+ end
52
+
53
+ def duration_ms
54
+ self[:duration_milliseconds]
55
+ end
56
+
57
+ def duration_ms_in_sql
58
+ @attributes[:duration_milliseconds_in_sql]
59
+ end
60
+
61
+ def start_ms
62
+ self[:start_milliseconds]
63
+ end
64
+
65
+ def depth
66
+ self[:depth]
67
+ end
68
+
69
+ def children
70
+ self[:children]
71
+ end
72
+
73
+ def custom_timings
74
+ self[:custom_timings]
75
+ end
76
+
77
+ def sql_timings
78
+ self[:sql_timings]
79
+ end
80
+
81
+ def add_child(name)
82
+ TimerStruct::Request.new(name, @page, self).tap do |timer|
83
+ self[:children].push(timer)
84
+ self[:has_children] = true
85
+ timer[:parent_timing_id] = self[:id]
86
+ timer[:depth] = self[:depth] + 1
87
+ end
88
+ end
89
+
90
+ def move_child(child, destination)
91
+ if index = self[:children].index(child)
92
+ self[:children].slice!(index)
93
+ self[:has_children] = self[:children].size > 0
94
+
95
+ destination[:children].push(child)
96
+ destination[:has_children] = true
97
+
98
+ child[:parent_timing_id] = destination[:id]
99
+ child.parent = destination
100
+ child.adjust_depth
101
+ end
102
+ end
103
+
104
+ def add_sql(query, elapsed_ms, page, params = nil, skip_backtrace = false, full_backtrace = false, cached = false)
105
+ TimerStruct::Sql.new(query, elapsed_ms, page, self, params, skip_backtrace, full_backtrace, cached).tap do |timer|
106
+ self[:sql_timings].push(timer)
107
+ timer[:parent_timing_id] = self[:id]
108
+ self[:has_sql_timings] = true
109
+ self[:sql_timings_duration_milliseconds] += elapsed_ms
110
+ page[:duration_milliseconds_in_sql] += elapsed_ms
111
+ page[:sql_count] += 1
112
+ page[:cached_sql_count] += 1 if cached
113
+ end
114
+ end
115
+
116
+ def move_sql(sql, destination)
117
+ if index = self[:sql_timings].index(sql)
118
+ self[:sql_timings].slice!(index)
119
+ self[:has_sql_timings] = self[:sql_timings].size > 0
120
+ self[:sql_timings_duration_milliseconds] -= sql[:duration_milliseconds]
121
+ destination[:sql_timings].push(sql)
122
+ destination[:has_sql_timings] = true
123
+ destination[:sql_timings_duration_milliseconds] += sql[:duration_milliseconds]
124
+ sql[:parent_timing_id] = destination[:id]
125
+ sql.parent = destination
126
+ end
127
+ end
128
+
129
+ # please call SqlTiming#report_reader_duration instead
130
+ def report_reader_duration(elapsed_ms, row_count = nil, class_name = nil)
131
+ last_time = self[:sql_timings]&.last
132
+ last_time&.report_reader_duration(elapsed_ms, row_count, class_name)
133
+ end
134
+
135
+ def add_custom(type, elapsed_ms, page)
136
+ TimerStruct::Custom.new(type, elapsed_ms, page, self).tap do |timer|
137
+ timer[:parent_timing_id] = self[:id]
138
+
139
+ self[:custom_timings][type] ||= []
140
+ self[:custom_timings][type].push(timer)
141
+
142
+ self[:custom_timing_stats][type] ||= { count: 0, duration: 0.0 }
143
+ self[:custom_timing_stats][type][:count] += 1
144
+ self[:custom_timing_stats][type][:duration] += elapsed_ms
145
+
146
+ page[:custom_timing_stats][type] ||= { count: 0, duration: 0.0 }
147
+ page[:custom_timing_stats][type][:count] += 1
148
+ page[:custom_timing_stats][type][:duration] += elapsed_ms
149
+ end
150
+ end
151
+
152
+ def move_custom(type, custom, destination)
153
+ if index = self[:custom_timings][type]&.index(custom)
154
+ custom[:parent_timing_id] = destination[:id]
155
+ custom.parent = destination
156
+ self[:custom_timings][type].slice!(index)
157
+ if self[:custom_timings][type].size == 0
158
+ self[:custom_timings].delete(type)
159
+ self[:custom_timing_stats].delete(type)
160
+ else
161
+ self[:custom_timing_stats][type][:count] -= 1
162
+ self[:custom_timing_stats][type][:duration] -= custom[:duration_milliseconds]
163
+ end
164
+ destination[:custom_timings][type] ||= []
165
+ destination[:custom_timings][type].push(custom)
166
+ destination[:custom_timing_stats][type] ||= { count: 0, duration: 0.0 }
167
+ destination[:custom_timing_stats][type][:count] += 1
168
+ destination[:custom_timing_stats][type][:duration] += custom[:duration_milliseconds]
169
+ end
170
+ end
171
+
172
+ def record_time(milliseconds = nil)
173
+ milliseconds ||= (Process.clock_gettime(Process::CLOCK_MONOTONIC) - @start) * 1000
174
+ self[:duration_milliseconds] = milliseconds
175
+ self[:is_trivial] = true if milliseconds < self[:trivial_duration_threshold_milliseconds]
176
+ self[:duration_without_children_milliseconds] = milliseconds - self[:children].sum(&:duration_ms)
177
+ end
178
+
179
+ def adjust_depth
180
+ self[:depth] = self.parent ? self.parent[:depth] + 1 : 0
181
+ self[:children].each(&:adjust_depth)
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+
5
+ module Rack
6
+ class MiniProfiler
7
+
8
+ # Timing system for a SQL query
9
+ module TimerStruct
10
+ class Sql < TimerStruct::Base
11
+ attr_accessor :parent
12
+
13
+ def initialize(query, duration_ms, page, parent, params = nil, skip_backtrace = false, full_backtrace = false, cached = false)
14
+
15
+ stack_trace = nil
16
+ unless skip_backtrace || duration_ms < Rack::MiniProfiler.config.backtrace_threshold_ms
17
+ # Allow us to filter the stack trace
18
+ stack_trace = "".dup
19
+ # Clean up the stack trace if there are options to do so
20
+ Kernel.caller.each do |ln|
21
+ ln.gsub!(Rack::MiniProfiler.config.backtrace_remove, '') if Rack::MiniProfiler.config.backtrace_remove && !full_backtrace
22
+ if full_backtrace ||
23
+ (
24
+ (
25
+ Rack::MiniProfiler.config.backtrace_includes.nil? ||
26
+ Rack::MiniProfiler.config.backtrace_includes.any? { |regex| ln =~ regex }
27
+ ) &&
28
+ (
29
+ Rack::MiniProfiler.config.backtrace_ignores.nil? ||
30
+ Rack::MiniProfiler.config.backtrace_ignores.none? { |regex| ln =~ regex }
31
+ )
32
+ )
33
+ stack_trace << ln << "\n"
34
+ end
35
+ end
36
+ end
37
+
38
+ @parent = parent
39
+ @page = page
40
+ start_millis = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1000).to_i - page[:started]) - duration_ms
41
+ super(
42
+ execute_type: 3, # TODO
43
+ formatted_command_string: query ? ERB::Util.html_escape(query) : nil,
44
+ stack_trace_snippet: stack_trace,
45
+ start_milliseconds: start_millis,
46
+ duration_milliseconds: duration_ms,
47
+ first_fetch_duration_milliseconds: duration_ms,
48
+ parameters: query ? trim_binds(params) : nil,
49
+ row_count: 0,
50
+ class_name: nil,
51
+ parent_timing_id: nil,
52
+ cached: cached,
53
+ is_duplicate: false
54
+ )
55
+ end
56
+
57
+ def report_reader_duration(elapsed_ms, row_count = nil, class_name = nil)
58
+ return if @reported
59
+ @reported = true
60
+ self[:duration_milliseconds] += elapsed_ms
61
+ @parent[:sql_timings_duration_milliseconds] += elapsed_ms
62
+ @page[:duration_milliseconds_in_sql] += elapsed_ms
63
+ self[:row_count] = self[:row_count].to_i + row_count if row_count
64
+ self[:class_name] = class_name if class_name
65
+ end
66
+
67
+ def trim_binds(binds)
68
+ max_len = Rack::MiniProfiler.config.max_sql_param_length
69
+ return if binds.nil? || max_len == 0
70
+ return binds.map { |(name, val)| [name, val] } if max_len.nil?
71
+ binds.map do |(name, val)|
72
+ val ||= name
73
+ if val.nil? || val == true || val == false || val.kind_of?(Numeric)
74
+ # keep these parameters as is
75
+ elsif val.kind_of?(String)
76
+ val = val[0...max_len] + (max_len < val.length ? '...' : '') if max_len
77
+ else
78
+ val = val.class.name
79
+ end
80
+ if name.kind_of?(String)
81
+ name = name[0...max_len] + (max_len < name.length ? '...' : '') if max_len
82
+ end
83
+ [name, val]
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mini_profiler/timer_struct/base'
4
+ require 'mini_profiler/timer_struct/page'
5
+ require 'mini_profiler/timer_struct/sql'
6
+ require 'mini_profiler/timer_struct/custom'
7
+ require 'mini_profiler/timer_struct/client'
8
+ require 'mini_profiler/timer_struct/request'
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class MiniProfiler
5
+ VERSION = "4.0.1"
6
+ SOURCE_CODE_URI = "https://github.com/MiniProfiler/rack-mini-profiler"
7
+ end
8
+ end