rack-mini-profiler 0.1.31 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rack-mini-profiler might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +149 -0
- data/README.md +285 -0
- data/{Ruby/lib → lib}/html/includes.css +15 -4
- data/{Ruby/lib → lib}/html/includes.js +95 -59
- data/{Ruby/lib → lib}/html/includes.less +21 -5
- data/{Ruby/lib → lib}/html/includes.tmpl +50 -50
- data/{Ruby/lib → lib}/html/jquery.1.7.1.js +0 -0
- data/{Ruby/lib → lib}/html/jquery.tmpl.js +0 -0
- data/{Ruby/lib → lib}/html/list.css +2 -2
- data/{Ruby/lib → lib}/html/list.js +1 -1
- data/lib/html/list.tmpl +34 -0
- data/lib/html/profile_handler.js +1 -0
- data/{Ruby/lib → lib}/html/share.html +2 -2
- data/lib/mini_profiler/asset_version.rb +5 -0
- data/{Ruby/lib → lib}/mini_profiler/client_settings.rb +3 -3
- data/lib/mini_profiler/config.rb +65 -0
- data/{Ruby/lib → lib}/mini_profiler/context.rb +0 -0
- data/lib/mini_profiler/gc_profiler.rb +181 -0
- data/{Ruby/lib → lib}/mini_profiler/profiler.rb +120 -96
- data/{Ruby/lib → lib}/mini_profiler/profiling_methods.rb +15 -17
- data/{Ruby/lib → lib}/mini_profiler/storage/abstract_store.rb +0 -0
- data/{Ruby/lib → lib}/mini_profiler/storage/file_store.rb +30 -8
- data/{Ruby/lib → lib}/mini_profiler/storage/memcache_store.rb +5 -7
- data/lib/mini_profiler/storage/memory_store.rb +115 -0
- data/{Ruby/lib → lib}/mini_profiler/storage/redis_store.rb +19 -11
- data/lib/mini_profiler/timer_struct/base.rb +33 -0
- data/lib/mini_profiler/timer_struct/client.rb +89 -0
- data/lib/mini_profiler/timer_struct/custom.rb +22 -0
- data/lib/mini_profiler/timer_struct/page.rb +62 -0
- data/lib/mini_profiler/timer_struct/request.rb +126 -0
- data/lib/mini_profiler/timer_struct/sql.rb +59 -0
- data/lib/mini_profiler/version.rb +5 -0
- data/{Ruby/lib → lib}/mini_profiler_rails/railtie.rb +23 -6
- data/lib/patches/db/activerecord.rb +42 -0
- data/lib/patches/db/moped.rb +12 -0
- data/lib/patches/db/mysql2.rb +30 -0
- data/lib/patches/db/pg.rb +104 -0
- data/lib/patches/db/plucky.rb +47 -0
- data/lib/patches/db/rsolr.rb +24 -0
- data/lib/patches/db/sequel.rb +10 -0
- data/{Ruby/lib → lib}/patches/net_patches.rb +0 -0
- data/lib/patches/sql_patches.rb +46 -0
- data/lib/rack-mini-profiler.rb +35 -0
- data/rack-mini-profiler.gemspec +28 -16
- metadata +171 -52
- data/Ruby/CHANGELOG +0 -161
- data/Ruby/README.md +0 -172
- data/Ruby/lib/html/list.tmpl +0 -34
- data/Ruby/lib/html/profile_handler.js +0 -1
- data/Ruby/lib/mini_profiler/client_timer_struct.rb +0 -78
- data/Ruby/lib/mini_profiler/config.rb +0 -58
- data/Ruby/lib/mini_profiler/custom_timer_struct.rb +0 -22
- data/Ruby/lib/mini_profiler/gc_profiler.rb +0 -107
- data/Ruby/lib/mini_profiler/gc_profiler_ruby_head.rb +0 -40
- data/Ruby/lib/mini_profiler/page_timer_struct.rb +0 -58
- data/Ruby/lib/mini_profiler/request_timer_struct.rb +0 -115
- data/Ruby/lib/mini_profiler/sql_timer_struct.rb +0 -58
- data/Ruby/lib/mini_profiler/storage/memory_store.rb +0 -65
- data/Ruby/lib/mini_profiler/timer_struct.rb +0 -33
- data/Ruby/lib/mini_profiler/version.rb +0 -5
- data/Ruby/lib/patches/sql_patches.rb +0 -277
- data/Ruby/lib/rack-mini-profiler.rb +0 -7
@@ -1,58 +0,0 @@
|
|
1
|
-
module Rack
|
2
|
-
class MiniProfiler
|
3
|
-
class Config
|
4
|
-
|
5
|
-
def self.attr_accessor(*vars)
|
6
|
-
@attributes ||= []
|
7
|
-
@attributes.concat vars
|
8
|
-
super(*vars)
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.attributes
|
12
|
-
@attributes
|
13
|
-
end
|
14
|
-
|
15
|
-
attr_accessor :auto_inject, :base_url_path, :pre_authorize_cb, :position,
|
16
|
-
:backtrace_remove, :backtrace_includes, :backtrace_ignores, :skip_schema_queries,
|
17
|
-
:storage, :user_provider, :storage_instance, :storage_options, :skip_paths, :authorization_mode,
|
18
|
-
:toggle_shortcut, :start_hidden, :backtrace_threshold_ms
|
19
|
-
|
20
|
-
# Deprecated options
|
21
|
-
attr_accessor :use_existing_jquery
|
22
|
-
|
23
|
-
def self.default
|
24
|
-
new.instance_eval {
|
25
|
-
@auto_inject = true # automatically inject on every html page
|
26
|
-
@base_url_path = "/mini-profiler-resources/"
|
27
|
-
|
28
|
-
# called prior to rack chain, to ensure we are allowed to profile
|
29
|
-
@pre_authorize_cb = lambda {|env| true}
|
30
|
-
|
31
|
-
# called after rack chain, to ensure we are REALLY allowed to profile
|
32
|
-
@position = 'left' # Where it is displayed
|
33
|
-
@skip_schema_queries = false
|
34
|
-
@storage = MiniProfiler::MemoryStore
|
35
|
-
@user_provider = Proc.new{|env| Rack::Request.new(env).ip}
|
36
|
-
@authorization_mode = :allow_all
|
37
|
-
@toggle_shortcut = 'Alt+P'
|
38
|
-
@start_hidden = false
|
39
|
-
@backtrace_threshold_ms = 0
|
40
|
-
self
|
41
|
-
}
|
42
|
-
end
|
43
|
-
|
44
|
-
def merge!(config)
|
45
|
-
return unless config
|
46
|
-
if Hash === config
|
47
|
-
config.each{|k,v| instance_variable_set "@#{k}",v}
|
48
|
-
else
|
49
|
-
self.class.attributes.each{ |k|
|
50
|
-
v = config.send k
|
51
|
-
instance_variable_set "@#{k}", v if v
|
52
|
-
}
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'mini_profiler/timer_struct'
|
2
|
-
|
3
|
-
module Rack
|
4
|
-
class MiniProfiler
|
5
|
-
|
6
|
-
# Timing system for a custom timers such as cache, redis, RPC, external API
|
7
|
-
# calls, etc.
|
8
|
-
class CustomTimerStruct < TimerStruct
|
9
|
-
def initialize(type, duration_ms, page, parent)
|
10
|
-
@parent = parent
|
11
|
-
@page = page
|
12
|
-
@type = type
|
13
|
-
|
14
|
-
super("Type" => type,
|
15
|
-
"StartMilliseconds" => ((Time.now.to_f * 1000).to_i - page['Started']) - duration_ms,
|
16
|
-
"DurationMilliseconds" => duration_ms,
|
17
|
-
"ParentTimingId" => nil)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
end
|
@@ -1,107 +0,0 @@
|
|
1
|
-
class Rack::MiniProfiler::GCProfiler
|
2
|
-
|
3
|
-
def object_space_stats
|
4
|
-
stats = {}
|
5
|
-
ids = Set.new
|
6
|
-
i=0
|
7
|
-
ObjectSpace.each_object { |o|
|
8
|
-
begin
|
9
|
-
i = stats[o.class] || 0
|
10
|
-
i += 1
|
11
|
-
stats[o.class] = i
|
12
|
-
ids << o.object_id if Integer === o.object_id
|
13
|
-
rescue NoMethodError
|
14
|
-
# Redis::Future undefines .class and .object_id super weird
|
15
|
-
end
|
16
|
-
}
|
17
|
-
{:stats => stats, :ids => ids}
|
18
|
-
end
|
19
|
-
|
20
|
-
def diff_object_stats(before,after)
|
21
|
-
diff = {}
|
22
|
-
after.each do |k,v|
|
23
|
-
diff[k] = v - (before[k] || 0)
|
24
|
-
end
|
25
|
-
before.each do |k,v|
|
26
|
-
diff[k] = 0 - v unless after[k]
|
27
|
-
end
|
28
|
-
|
29
|
-
diff
|
30
|
-
end
|
31
|
-
|
32
|
-
def analyze_strings(ids_before,ids_after)
|
33
|
-
result = {}
|
34
|
-
ids_after.each do |id|
|
35
|
-
obj = ObjectSpace._id2ref(id)
|
36
|
-
if String === obj && !ids_before.include?(obj.object_id)
|
37
|
-
result[obj] ||= 0
|
38
|
-
result[obj] += 1
|
39
|
-
end
|
40
|
-
end
|
41
|
-
result
|
42
|
-
end
|
43
|
-
|
44
|
-
def profile_gc_time(app,env)
|
45
|
-
body = []
|
46
|
-
|
47
|
-
begin
|
48
|
-
GC::Profiler.clear
|
49
|
-
GC::Profiler.enable
|
50
|
-
b = app.call(env)[2]
|
51
|
-
b.close if b.respond_to? :close
|
52
|
-
body << "GC Profiler ran during this request, if it fired you will see the cost below:\n\n"
|
53
|
-
body << GC::Profiler.result
|
54
|
-
ensure
|
55
|
-
GC.enable
|
56
|
-
GC::Profiler.disable
|
57
|
-
end
|
58
|
-
|
59
|
-
return [200, {'Content-Type' => 'text/plain'}, body]
|
60
|
-
end
|
61
|
-
|
62
|
-
def profile_gc(app,env)
|
63
|
-
|
64
|
-
body = [];
|
65
|
-
|
66
|
-
stat_before,stat_after,diff,string_analysis = nil
|
67
|
-
begin
|
68
|
-
GC.disable
|
69
|
-
stat_before = object_space_stats
|
70
|
-
b = app.call(env)[2]
|
71
|
-
b.close if b.respond_to? :close
|
72
|
-
stat_after = object_space_stats
|
73
|
-
|
74
|
-
diff = diff_object_stats(stat_before[:stats],stat_after[:stats])
|
75
|
-
string_analysis = analyze_strings(stat_before[:ids], stat_after[:ids])
|
76
|
-
ensure
|
77
|
-
GC.enable
|
78
|
-
end
|
79
|
-
|
80
|
-
|
81
|
-
body << "
|
82
|
-
ObjectSpace delta caused by request:
|
83
|
-
--------------------------------------------\n"
|
84
|
-
diff.to_a.reject{|k,v| v == 0}.sort{|x,y| y[1] <=> x[1]}.each do |k,v|
|
85
|
-
body << "#{k} : #{v}\n" if v != 0
|
86
|
-
end
|
87
|
-
|
88
|
-
body << "\n
|
89
|
-
ObjectSpace stats:
|
90
|
-
-----------------\n"
|
91
|
-
|
92
|
-
stat_after[:stats].to_a.sort{|x,y| y[1] <=> x[1]}.each do |k,v|
|
93
|
-
body << "#{k} : #{v}\n"
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
|
-
body << "\n
|
98
|
-
String stats:
|
99
|
-
------------\n"
|
100
|
-
|
101
|
-
string_analysis.to_a.sort{|x,y| y[1] <=> x[1] }.take(1000).each do |string,count|
|
102
|
-
body << "#{count} : #{string}\n"
|
103
|
-
end
|
104
|
-
|
105
|
-
return [200, {'Content-Type' => 'text/plain'}, body]
|
106
|
-
end
|
107
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
require 'objspace'
|
2
|
-
|
3
|
-
class Rack::MiniProfiler::GCProfilerRubyHead
|
4
|
-
def profile_rack(app,env)
|
5
|
-
end
|
6
|
-
|
7
|
-
def profile(&block)
|
8
|
-
GC.start
|
9
|
-
GC.disable
|
10
|
-
|
11
|
-
items = []
|
12
|
-
objs = []
|
13
|
-
|
14
|
-
ObjectSpace.trace_object_allocations do
|
15
|
-
block.call
|
16
|
-
|
17
|
-
ObjectSpace.each_object do |o|
|
18
|
-
objs << o
|
19
|
-
end
|
20
|
-
|
21
|
-
objs.each do |o|
|
22
|
-
g = ObjectSpace.allocation_generation(o)
|
23
|
-
if g
|
24
|
-
l = ObjectSpace.allocation_sourceline(o)
|
25
|
-
f = ObjectSpace.allocation_sourcefile(o)
|
26
|
-
c = ObjectSpace.allocation_class_path(o)
|
27
|
-
m = ObjectSpace.allocation_method_id(o)
|
28
|
-
items << "Allocated #{c} in #{m} #{f}:#{l}"
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
items.group_by{|x| x}.sort{|a,b| b[1].length <=> a[1].length}.each do |row, group|
|
34
|
-
puts "#{row} x #{group.length}"
|
35
|
-
end
|
36
|
-
|
37
|
-
GC.enable
|
38
|
-
profile_allocations(name, &block)
|
39
|
-
end
|
40
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
require 'mini_profiler/timer_struct'
|
2
|
-
|
3
|
-
module Rack
|
4
|
-
class MiniProfiler
|
5
|
-
|
6
|
-
# PageTimerStruct
|
7
|
-
# Root: RequestTimer
|
8
|
-
# :has_many RequestTimer children
|
9
|
-
# :has_many SqlTimer children
|
10
|
-
# :has_many CustomTimer children
|
11
|
-
class PageTimerStruct < TimerStruct
|
12
|
-
def initialize(env)
|
13
|
-
super("Id" => MiniProfiler.generate_id,
|
14
|
-
"Name" => env['PATH_INFO'],
|
15
|
-
"Started" => (Time.now.to_f * 1000).to_i,
|
16
|
-
"MachineName" => env['SERVER_NAME'],
|
17
|
-
"Level" => 0,
|
18
|
-
"User" => "unknown user",
|
19
|
-
"HasUserViewed" => false,
|
20
|
-
"ClientTimings" => nil,
|
21
|
-
"DurationMilliseconds" => 0,
|
22
|
-
"HasTrivialTimings" => true,
|
23
|
-
"HasAllTrivialTimigs" => false,
|
24
|
-
"TrivialDurationThresholdMilliseconds" => 2,
|
25
|
-
"Head" => nil,
|
26
|
-
"DurationMillisecondsInSql" => 0,
|
27
|
-
"HasSqlTimings" => true,
|
28
|
-
"HasDuplicateSqlTimings" => false,
|
29
|
-
"ExecutedReaders" => 0,
|
30
|
-
"ExecutedScalars" => 0,
|
31
|
-
"ExecutedNonQueries" => 0,
|
32
|
-
"CustomTimingNames" => [],
|
33
|
-
"CustomTimingStats" => {}
|
34
|
-
)
|
35
|
-
name = "#{env['REQUEST_METHOD']} http://#{env['SERVER_NAME']}:#{env['SERVER_PORT']}#{env['SCRIPT_NAME']}#{env['PATH_INFO']}"
|
36
|
-
self['Root'] = RequestTimerStruct.createRoot(name, self)
|
37
|
-
end
|
38
|
-
|
39
|
-
def duration_ms
|
40
|
-
@attributes['Root']['DurationMilliseconds']
|
41
|
-
end
|
42
|
-
|
43
|
-
def root
|
44
|
-
@attributes['Root']
|
45
|
-
end
|
46
|
-
|
47
|
-
def to_json(*a)
|
48
|
-
attribs = @attributes.merge(
|
49
|
-
"Started" => '/Date(%d)/' % @attributes['Started'],
|
50
|
-
"DurationMilliseconds" => @attributes['Root']['DurationMilliseconds'],
|
51
|
-
"CustomTimingNames" => @attributes['CustomTimingStats'].keys.sort
|
52
|
-
)
|
53
|
-
::JSON.generate(attribs, :max_nesting => 100)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|
@@ -1,115 +0,0 @@
|
|
1
|
-
require 'mini_profiler/timer_struct'
|
2
|
-
|
3
|
-
module Rack
|
4
|
-
class MiniProfiler
|
5
|
-
|
6
|
-
class RequestTimerStruct < TimerStruct
|
7
|
-
|
8
|
-
def self.createRoot(name, page)
|
9
|
-
rt = RequestTimerStruct.new(name, page, nil)
|
10
|
-
rt["IsRoot"]= true
|
11
|
-
rt
|
12
|
-
end
|
13
|
-
|
14
|
-
attr_accessor :children_duration
|
15
|
-
|
16
|
-
def initialize(name, page, parent)
|
17
|
-
super("Id" => MiniProfiler.generate_id,
|
18
|
-
"Name" => name,
|
19
|
-
"DurationMilliseconds" => 0,
|
20
|
-
"DurationWithoutChildrenMilliseconds"=> 0,
|
21
|
-
"StartMilliseconds" => (Time.now.to_f * 1000).to_i - page['Started'],
|
22
|
-
"ParentTimingId" => nil,
|
23
|
-
"Children" => [],
|
24
|
-
"HasChildren"=> false,
|
25
|
-
"KeyValues" => nil,
|
26
|
-
"HasSqlTimings"=> false,
|
27
|
-
"HasDuplicateSqlTimings"=> false,
|
28
|
-
"TrivialDurationThresholdMilliseconds" => 2,
|
29
|
-
"SqlTimings" => [],
|
30
|
-
"SqlTimingsDurationMilliseconds"=> 0,
|
31
|
-
"IsTrivial"=> false,
|
32
|
-
"IsRoot"=> false,
|
33
|
-
"Depth"=> parent ? parent.depth + 1 : 0,
|
34
|
-
"ExecutedReaders"=> 0,
|
35
|
-
"ExecutedScalars"=> 0,
|
36
|
-
"ExecutedNonQueries"=> 0,
|
37
|
-
"CustomTimingStats" => {},
|
38
|
-
"CustomTimings" => {})
|
39
|
-
@children_duration = 0
|
40
|
-
@start = Time.now
|
41
|
-
@parent = parent
|
42
|
-
@page = page
|
43
|
-
end
|
44
|
-
|
45
|
-
def duration_ms
|
46
|
-
self['DurationMilliseconds']
|
47
|
-
end
|
48
|
-
|
49
|
-
def start_ms
|
50
|
-
self['StartMilliseconds']
|
51
|
-
end
|
52
|
-
|
53
|
-
def start
|
54
|
-
@start
|
55
|
-
end
|
56
|
-
|
57
|
-
def depth
|
58
|
-
self['Depth']
|
59
|
-
end
|
60
|
-
|
61
|
-
def children
|
62
|
-
self['Children']
|
63
|
-
end
|
64
|
-
|
65
|
-
def add_child(name)
|
66
|
-
request_timer = RequestTimerStruct.new(name, @page, self)
|
67
|
-
self['Children'].push(request_timer)
|
68
|
-
self['HasChildren'] = true
|
69
|
-
request_timer['ParentTimingId'] = self['Id']
|
70
|
-
request_timer['Depth'] = self['Depth'] + 1
|
71
|
-
request_timer
|
72
|
-
end
|
73
|
-
|
74
|
-
def add_sql(query, elapsed_ms, page, skip_backtrace = false, full_backtrace = false)
|
75
|
-
timer = SqlTimerStruct.new(query, elapsed_ms, page, self , skip_backtrace, full_backtrace)
|
76
|
-
timer['ParentTimingId'] = self['Id']
|
77
|
-
self['SqlTimings'].push(timer)
|
78
|
-
self['HasSqlTimings'] = true
|
79
|
-
self['SqlTimingsDurationMilliseconds'] += elapsed_ms
|
80
|
-
page['DurationMillisecondsInSql'] += elapsed_ms
|
81
|
-
timer
|
82
|
-
end
|
83
|
-
|
84
|
-
def add_custom(type, elapsed_ms, page)
|
85
|
-
timer = CustomTimerStruct.new(type, elapsed_ms, page, self)
|
86
|
-
timer['ParentTimingId'] = self['Id']
|
87
|
-
self['CustomTimings'][type] ||= []
|
88
|
-
self['CustomTimings'][type].push(timer)
|
89
|
-
|
90
|
-
self['CustomTimingStats'][type] ||= {"Count" => 0, "Duration" => 0.0}
|
91
|
-
self['CustomTimingStats'][type]['Count'] += 1
|
92
|
-
self['CustomTimingStats'][type]['Duration'] += elapsed_ms
|
93
|
-
|
94
|
-
page['CustomTimingStats'][type] ||= {"Count" => 0, "Duration" => 0.0}
|
95
|
-
page['CustomTimingStats'][type]['Count'] += 1
|
96
|
-
page['CustomTimingStats'][type]['Duration'] += elapsed_ms
|
97
|
-
|
98
|
-
timer
|
99
|
-
end
|
100
|
-
|
101
|
-
def record_time(milliseconds = nil)
|
102
|
-
milliseconds ||= (Time.now - @start) * 1000
|
103
|
-
self['DurationMilliseconds'] = milliseconds
|
104
|
-
self['IsTrivial'] = true if milliseconds < self["TrivialDurationThresholdMilliseconds"]
|
105
|
-
self['DurationWithoutChildrenMilliseconds'] = milliseconds - @children_duration
|
106
|
-
|
107
|
-
if @parent
|
108
|
-
@parent.children_duration += milliseconds
|
109
|
-
end
|
110
|
-
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
require 'mini_profiler/timer_struct'
|
2
|
-
|
3
|
-
module Rack
|
4
|
-
class MiniProfiler
|
5
|
-
|
6
|
-
# Timing system for a SQL query
|
7
|
-
class SqlTimerStruct < TimerStruct
|
8
|
-
def initialize(query, duration_ms, page, parent, skip_backtrace = false, full_backtrace = false)
|
9
|
-
|
10
|
-
stack_trace = nil
|
11
|
-
unless skip_backtrace || duration_ms < Rack::MiniProfiler.config.backtrace_threshold_ms
|
12
|
-
# Allow us to filter the stack trace
|
13
|
-
stack_trace = ""
|
14
|
-
# Clean up the stack trace if there are options to do so
|
15
|
-
Kernel.caller.each do |ln|
|
16
|
-
ln.gsub!(Rack::MiniProfiler.config.backtrace_remove, '') if Rack::MiniProfiler.config.backtrace_remove and !full_backtrace
|
17
|
-
if full_backtrace or
|
18
|
-
(
|
19
|
-
(
|
20
|
-
Rack::MiniProfiler.config.backtrace_includes.nil? or
|
21
|
-
Rack::MiniProfiler.config.backtrace_includes.all?{|regex| ln =~ regex}
|
22
|
-
) and
|
23
|
-
(
|
24
|
-
Rack::MiniProfiler.config.backtrace_ignores.nil? or
|
25
|
-
Rack::MiniProfiler.config.backtrace_ignores.all?{|regex| !(ln =~ regex)}
|
26
|
-
)
|
27
|
-
)
|
28
|
-
stack_trace << ln << "\n"
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
@parent = parent
|
34
|
-
@page = page
|
35
|
-
|
36
|
-
super("ExecuteType" => 3, # TODO
|
37
|
-
"FormattedCommandString" => query,
|
38
|
-
"StackTraceSnippet" => stack_trace,
|
39
|
-
"StartMilliseconds" => ((Time.now.to_f * 1000).to_i - page['Started']) - duration_ms,
|
40
|
-
"DurationMilliseconds" => duration_ms,
|
41
|
-
"FirstFetchDurationMilliseconds" => duration_ms,
|
42
|
-
"Parameters" => nil,
|
43
|
-
"ParentTimingId" => nil,
|
44
|
-
"IsDuplicate" => false)
|
45
|
-
end
|
46
|
-
|
47
|
-
def report_reader_duration(elapsed_ms)
|
48
|
-
return if @reported
|
49
|
-
@reported = true
|
50
|
-
self["DurationMilliseconds"] += elapsed_ms
|
51
|
-
@parent["SqlTimingsDurationMilliseconds"] += elapsed_ms
|
52
|
-
@page["DurationMillisecondsInSql"] += elapsed_ms
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|