rails_performance 1.2.3 → 1.3.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -13
  3. data/Rakefile +14 -14
  4. data/app/assets/images/download.svg +3 -0
  5. data/app/controllers/rails_performance/base_controller.rb +21 -21
  6. data/app/controllers/rails_performance/concerns/csv_exportable.rb +29 -0
  7. data/app/controllers/rails_performance/rails_performance_controller.rb +96 -49
  8. data/app/helpers/rails_performance/rails_performance_helper.rb +152 -156
  9. data/app/views/rails_performance/javascripts/app.js +2 -2
  10. data/app/views/rails_performance/rails_performance/_export.html.erb +3 -0
  11. data/app/views/rails_performance/rails_performance/crashes.html.erb +8 -1
  12. data/app/views/rails_performance/rails_performance/index.html.erb +29 -0
  13. data/app/views/rails_performance/rails_performance/recent.html.erb +8 -6
  14. data/app/views/rails_performance/rails_performance/requests.html.erb +15 -1
  15. data/app/views/rails_performance/rails_performance/slow.html.erb +3 -0
  16. data/app/views/rails_performance/shared/_header.html.erb +0 -1
  17. data/app/views/rails_performance/stylesheets/style.css +10 -0
  18. data/config/routes.rb +16 -18
  19. data/lib/generators/rails_performance/install/install_generator.rb +1 -1
  20. data/lib/generators/rails_performance/install/templates/initializer.rb +56 -42
  21. data/lib/rails_performance/data_source.rb +120 -121
  22. data/lib/rails_performance/engine.rb +8 -8
  23. data/lib/rails_performance/extensions/trace.rb +32 -33
  24. data/lib/rails_performance/gems/custom_ext.rb +31 -34
  25. data/lib/rails_performance/gems/delayed_job_ext.rb +50 -54
  26. data/lib/rails_performance/gems/grape_ext.rb +33 -35
  27. data/lib/rails_performance/gems/rake_ext.rb +41 -44
  28. data/lib/rails_performance/gems/sidekiq_ext.rb +34 -37
  29. data/lib/rails_performance/instrument/metrics_collector.rb +50 -50
  30. data/lib/rails_performance/models/base_record.rb +33 -36
  31. data/lib/rails_performance/models/collection.rb +35 -36
  32. data/lib/rails_performance/models/custom_record.rb +47 -48
  33. data/lib/rails_performance/models/delayed_job_record.rb +61 -62
  34. data/lib/rails_performance/models/grape_record.rb +60 -61
  35. data/lib/rails_performance/models/rake_record.rb +48 -49
  36. data/lib/rails_performance/models/request_record.rb +128 -120
  37. data/lib/rails_performance/models/sidekiq_record.rb +65 -66
  38. data/lib/rails_performance/models/trace_record.rb +18 -19
  39. data/lib/rails_performance/rails/middleware.rb +75 -76
  40. data/lib/rails_performance/rails/query_builder.rb +18 -20
  41. data/lib/rails_performance/reports/base_report.rb +60 -60
  42. data/lib/rails_performance/reports/breakdown_report.rb +15 -18
  43. data/lib/rails_performance/reports/crash_report.rb +15 -17
  44. data/lib/rails_performance/reports/percentile_report.rb +14 -0
  45. data/lib/rails_performance/reports/recent_requests_report.rb +24 -24
  46. data/lib/rails_performance/reports/requests_report.rb +30 -27
  47. data/lib/rails_performance/reports/response_time_report.rb +17 -17
  48. data/lib/rails_performance/reports/slow_requests_report.rb +4 -4
  49. data/lib/rails_performance/reports/throughput_report.rb +15 -17
  50. data/lib/rails_performance/reports/trace_report.rb +16 -18
  51. data/lib/rails_performance/thread/current_request.rb +33 -34
  52. data/lib/rails_performance/utils.rb +64 -54
  53. data/lib/rails_performance/version.rb +2 -2
  54. data/lib/rails_performance.rb +35 -36
  55. metadata +21 -17
@@ -1,62 +1,61 @@
1
- module RailsPerformance
2
- module Models
3
- class DelayedJobRecord < BaseRecord
4
- attr_accessor :jid, :duration, :datetime, :datetimei, :source_type, :class_name, :method_name, :status, :json
5
-
6
- # delayed_job
7
- #|jid|22
8
- #|datetime|20210415T0616
9
- #|datetimei|1618492591
10
- #|source_type|instance_method
11
- #|class_name|User
12
- #|method_name|say_hello_without_delay
13
- #|status|success|END|1.0.0
14
- def DelayedJobRecord.from_db(key, value)
15
- items = key.split("|")
16
-
17
- DelayedJobRecord.new(
18
- jid: items[2],
19
- datetime: items[4],
20
- datetimei: items[6],
21
- source_type: items[8],
22
- class_name: items[10],
23
- method_name: items[12],
24
- status: items[14],
25
- json: value
26
- )
27
- end
28
-
29
- def initialize(jid:, duration: nil, datetime:, datetimei:, source_type:, class_name:, method_name:, status:, json: '{}')
30
- @jid = jid
31
- @duration = duration
32
- @datetime = datetime
33
- @datetimei = datetimei.to_i
34
- @source_type = source_type
35
- @class_name = class_name
36
- @method_name = method_name
37
- @status = status
38
- @json = json
39
- end
40
-
41
- def record_hash
42
- {
43
- jid: jid,
44
- datetime: Time.at(datetimei),
45
- datetimei: datetimei,
46
- duration: value['duration'],
47
- status: status,
48
- source_type: source_type,
49
- class_name: class_name,
50
- method_name: method_name,
51
- }
52
- end
53
-
54
- def save
55
- key = "delayed_job|jid|#{jid}|datetime|#{datetime}|datetimei|#{datetimei}|source_type|#{source_type}|class_name|#{class_name}|method_name|#{method_name}|status|#{status}|END|#{RailsPerformance::SCHEMA}"
56
- value = { duration: duration }
57
- Utils.save_to_redis(key, value)
58
- end
59
-
60
- end
61
- end
62
- end
1
+ module RailsPerformance
2
+ module Models
3
+ class DelayedJobRecord < BaseRecord
4
+ attr_accessor :jid, :duration, :datetime, :datetimei, :source_type, :class_name, :method_name, :status, :json
5
+
6
+ # delayed_job
7
+ # |jid|22
8
+ # |datetime|20210415T0616
9
+ # |datetimei|1618492591
10
+ # |source_type|instance_method
11
+ # |class_name|User
12
+ # |method_name|say_hello_without_delay
13
+ # |status|success|END|1.0.0
14
+ def self.from_db(key, value)
15
+ items = key.split("|")
16
+
17
+ DelayedJobRecord.new(
18
+ jid: items[2],
19
+ datetime: items[4],
20
+ datetimei: items[6],
21
+ source_type: items[8],
22
+ class_name: items[10],
23
+ method_name: items[12],
24
+ status: items[14],
25
+ json: value
26
+ )
27
+ end
28
+
29
+ def initialize(jid:, datetime:, datetimei:, source_type:, class_name:, method_name:, status:, duration: nil, json: "{}")
30
+ @jid = jid
31
+ @duration = duration
32
+ @datetime = datetime
33
+ @datetimei = datetimei.to_i
34
+ @source_type = source_type
35
+ @class_name = class_name
36
+ @method_name = method_name
37
+ @status = status
38
+ @json = json
39
+ end
40
+
41
+ def record_hash
42
+ {
43
+ jid: jid,
44
+ datetime: Time.at(datetimei),
45
+ datetimei: datetimei,
46
+ duration: value["duration"],
47
+ status: status,
48
+ source_type: source_type,
49
+ class_name: class_name,
50
+ method_name: method_name
51
+ }
52
+ end
53
+
54
+ def save
55
+ key = "delayed_job|jid|#{jid}|datetime|#{datetime}|datetimei|#{datetimei}|source_type|#{source_type}|class_name|#{class_name}|method_name|#{method_name}|status|#{status}|END|#{RailsPerformance::SCHEMA}"
56
+ value = {duration: duration}
57
+ Utils.save_to_redis(key, value)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,61 +1,60 @@
1
- module RailsPerformance
2
- module Models
3
- class GrapeRecord < BaseRecord
4
- attr_accessor :datetime, :datetimei, :format, :status, :path, :method, :request_id, :json
5
- attr_accessor :endpoint_render_grape, :endpoint_run_grape, :format_response_grape
6
-
7
- # key = grape|datetime|20210409T1115|datetimei|1617992134|format|json|path|/api/users|status|200|method|GET|request_id|1122|END|1.0.0
8
- # value = {"endpoint_render.grape"=>0.000643989, "endpoint_run.grape"=>0.002000907, "format_response.grape"=>0.0348967}
9
- def GrapeRecord.from_db(key, value)
10
- items = key.split("|")
11
-
12
- GrapeRecord.new(
13
- datetime: items[2],
14
- datetimei: items[4],
15
- format: items[6],
16
- path: items[8],
17
- status: items[10],
18
- method: items[12],
19
- request_id: items[14],
20
- json: value
21
- )
22
- end
23
-
24
- def initialize(datetime: nil, datetimei: nil, format: nil, path: nil, status: nil, method: nil, request_id:, endpoint_render_grape: nil, endpoint_run_grape: nil, format_response_grape: nil, json: '{}')
25
- @datetime = datetime
26
- @datetimei = datetimei.to_i unless datetimei.nil?
27
- @format = format
28
- @path = path
29
- @status = status
30
- @method = method
31
- @request_id = request_id
32
-
33
- @endpoint_render_grape = endpoint_render_grape
34
- @endpoint_run_grape = endpoint_run_grape
35
- @format_response_grape = format_response_grape
36
-
37
- @json = json
38
- end
39
-
40
- def record_hash
41
- {
42
- format: self.format,
43
- status: self.status,
44
- method: self.method,
45
- path: self.path,
46
- datetime: Time.at(self.datetimei.to_i),
47
- datetimei: datetimei.to_i,
48
- request_id: self.request_id,
49
- }.merge(self.value)
50
- end
51
-
52
- def save
53
- key = "grape|datetime|#{datetime}|datetimei|#{datetimei}|format|#{format}|path|#{path}|status|#{status}|method|#{method}|request_id|#{request_id}|END|#{RailsPerformance::SCHEMA}"
54
- value = { "endpoint_render.grape" => endpoint_render_grape, "endpoint_run.grape" => endpoint_run_grape, "format_response.grape" => format_response_grape }
55
-
56
- Utils.save_to_redis(key, value)
57
- end
58
-
59
- end
60
- end
61
- end
1
+ module RailsPerformance
2
+ module Models
3
+ class GrapeRecord < BaseRecord
4
+ attr_accessor :datetime, :datetimei, :format, :status, :path, :method, :request_id, :json
5
+ attr_accessor :endpoint_render_grape, :endpoint_run_grape, :format_response_grape
6
+
7
+ # key = grape|datetime|20210409T1115|datetimei|1617992134|format|json|path|/api/users|status|200|method|GET|request_id|1122|END|1.0.0
8
+ # value = {"endpoint_render.grape"=>0.000643989, "endpoint_run.grape"=>0.002000907, "format_response.grape"=>0.0348967}
9
+ def self.from_db(key, value)
10
+ items = key.split("|")
11
+
12
+ GrapeRecord.new(
13
+ datetime: items[2],
14
+ datetimei: items[4],
15
+ format: items[6],
16
+ path: items[8],
17
+ status: items[10],
18
+ method: items[12],
19
+ request_id: items[14],
20
+ json: value
21
+ )
22
+ end
23
+
24
+ def initialize(request_id:, datetime: nil, datetimei: nil, format: nil, path: nil, status: nil, method: nil, endpoint_render_grape: nil, endpoint_run_grape: nil, format_response_grape: nil, json: "{}")
25
+ @datetime = datetime
26
+ @datetimei = datetimei.to_i unless datetimei.nil?
27
+ @format = format
28
+ @path = path
29
+ @status = status
30
+ @method = method
31
+ @request_id = request_id
32
+
33
+ @endpoint_render_grape = endpoint_render_grape
34
+ @endpoint_run_grape = endpoint_run_grape
35
+ @format_response_grape = format_response_grape
36
+
37
+ @json = json
38
+ end
39
+
40
+ def record_hash
41
+ {
42
+ format: self.format,
43
+ status: status,
44
+ method: method,
45
+ path: path,
46
+ datetime: Time.at(datetimei.to_i),
47
+ datetimei: datetimei.to_i,
48
+ request_id: request_id
49
+ }.merge(value)
50
+ end
51
+
52
+ def save
53
+ key = "grape|datetime|#{datetime}|datetimei|#{datetimei}|format|#{format}|path|#{path}|status|#{status}|method|#{method}|request_id|#{request_id}|END|#{RailsPerformance::SCHEMA}"
54
+ value = {"endpoint_render.grape" => endpoint_render_grape, "endpoint_run.grape" => endpoint_run_grape, "format_response.grape" => format_response_grape}
55
+
56
+ Utils.save_to_redis(key, value)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,49 +1,48 @@
1
- module RailsPerformance
2
- module Models
3
- class RakeRecord < BaseRecord
4
- attr_accessor :task, :duration, :datetime, :datetimei, :status
5
-
6
- # rake|task|["task3"]|datetime|20210416T1254|datetimei|1618602843|status|error|END|1.0.0
7
- # {"duration":0.00012442}
8
- def RakeRecord.from_db(key, value)
9
- items = key.split("|")
10
-
11
- RakeRecord.new(
12
- task: JSON.parse(items[2]),
13
- datetime: items[4],
14
- datetimei: items[6],
15
- status: items[8],
16
- json: value
17
- )
18
- end
19
-
20
- def initialize(task:, duration: nil, datetime:, datetimei:, status:, json: '{}')
21
- @task = Array.wrap(task)
22
- @datetime = datetime
23
- @datetimei = datetimei.to_i
24
- @status = status
25
- @duration = duration
26
- @json = json
27
-
28
- @duration ||= value['duration']
29
- end
30
-
31
- def record_hash
32
- {
33
- task: task,
34
- datetime: Time.at(datetimei),
35
- datetimei: datetimei,
36
- duration: duration,
37
- status: status,
38
- }
39
- end
40
-
41
- def save
42
- key = "rake|task|#{task.to_json}|datetime|#{datetime}|datetimei|#{datetimei}|status|#{status}|END|#{RailsPerformance::SCHEMA}"
43
- value = { duration: duration }
44
- Utils.save_to_redis(key, value)
45
- end
46
-
47
- end
48
- end
49
- end
1
+ module RailsPerformance
2
+ module Models
3
+ class RakeRecord < BaseRecord
4
+ attr_accessor :task, :duration, :datetime, :datetimei, :status
5
+
6
+ # rake|task|["task3"]|datetime|20210416T1254|datetimei|1618602843|status|error|END|1.0.0
7
+ # {"duration":0.00012442}
8
+ def self.from_db(key, value)
9
+ items = key.split("|")
10
+
11
+ RakeRecord.new(
12
+ task: JSON.parse(items[2]),
13
+ datetime: items[4],
14
+ datetimei: items[6],
15
+ status: items[8],
16
+ json: value
17
+ )
18
+ end
19
+
20
+ def initialize(task:, datetime:, datetimei:, status:, duration: nil, json: "{}")
21
+ @task = Array.wrap(task)
22
+ @datetime = datetime
23
+ @datetimei = datetimei.to_i
24
+ @status = status
25
+ @duration = duration
26
+ @json = json
27
+
28
+ @duration ||= value["duration"]
29
+ end
30
+
31
+ def record_hash
32
+ {
33
+ task: task,
34
+ datetime: Time.at(datetimei),
35
+ datetimei: datetimei,
36
+ duration: duration,
37
+ status: status
38
+ }
39
+ end
40
+
41
+ def save
42
+ key = "rake|task|#{task.to_json}|datetime|#{datetime}|datetimei|#{datetimei}|status|#{status}|END|#{RailsPerformance::SCHEMA}"
43
+ value = {duration: duration}
44
+ Utils.save_to_redis(key, value)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,120 +1,128 @@
1
- module RailsPerformance
2
- module Models
3
- class RequestRecord < BaseRecord
4
- attr_accessor :controller, :action, :format, :status, :datetime, :datetimei, :method, :path, :request_id, :json
5
- attr_accessor :view_runtime, :db_runtime, :duration, :http_referer, :custom_data
6
- attr_accessor :exception, :exception_object
7
-
8
- def RequestRecord.find_by(request_id:)
9
- keys, values = RailsPerformance::Utils.fetch_from_redis("performance|*|request_id|#{request_id}|*")
10
-
11
- return nil if keys.blank?
12
- return nil if values.blank?
13
-
14
- RailsPerformance::Models::RequestRecord.from_db(keys[0], values[0])
15
- end
16
-
17
- # key = performance|
18
- # controller|HomeController|
19
- # action|index|
20
- # format|html|
21
- # status|200|
22
- # datetime|20200124T0523|
23
- # datetimei|1579861423|
24
- # method|GET|
25
- # path|/|
26
- # request_id|454545454545454545|
27
- # END|1.0.0
28
- # = {"view_runtime":null,"db_runtime":0,"duration":27.329741000000002,"http_referer":null,"custom_data":null,"exception":"ZeroDivisionError divided by 0","backtrace":["/root/projects/rails_performance/test/dummy/app/controllers/account/site_controller.rb:17:in `/'","/root/projects/rails_performance/test/dummy/app/controllers/account/site_controller.rb:17:in `crash'","/usr/local/rvm/gems/ruby-2.6.3/gems/actionpack-6.1.3.1/lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'"]}
29
- # value = JSON
30
- def RequestRecord.from_db(key, value)
31
- items = key.split("|")
32
-
33
- RequestRecord.new(
34
- controller: items[2],
35
- action: items[4],
36
- format: items[6],
37
- status: items[8],
38
- datetime: items[10],
39
- datetimei: items[12],
40
- method: items[14],
41
- path: items[16],
42
- request_id: items[18],
43
- json: value
44
- )
45
- end
46
-
47
- def initialize(controller:, action:, format:, status:, datetime:, datetimei:, method:, path:, request_id:, view_runtime: nil, db_runtime: nil, duration: nil, http_referer: nil, custom_data: nil, exception: nil, exception_object: nil, json: '{}')
48
- @controller = controller
49
- @action = action
50
- @format = format
51
- @status = status
52
- @datetime = datetime
53
- @datetimei = datetimei.to_i
54
- @method = method
55
- @path = path
56
- @request_id = request_id
57
-
58
- @view_runtime = view_runtime
59
- @db_runtime = db_runtime
60
- @duration = duration
61
- @http_referer = http_referer
62
- @custom_data = custom_data
63
-
64
- @exception = Array.wrap(exception).compact.join(" ")
65
- @exception_object = exception_object
66
-
67
- @json = json
68
- end
69
-
70
- def controller_action
71
- "#{controller}##{action}"
72
- end
73
-
74
- def controller_action_format
75
- "#{controller}##{action}|#{format}"
76
- end
77
-
78
- # show on UI in the right panel
79
- def record_hash
80
- {
81
- controller: self.controller,
82
- action: self.action,
83
- format: self.format,
84
- status: self.status,
85
- method: self.method,
86
- path: self.path,
87
- request_id: self.request_id,
88
- datetime: Time.at(self.datetimei.to_i),
89
- datetimei: datetimei,
90
- duration: self.value['duration'],
91
- db_runtime: self.value['db_runtime'],
92
- view_runtime: self.value['view_runtime'],
93
- exception: self.value['exception'],
94
- backtrace: self.value['backtrace'],
95
- http_referer: self.value['http_referer']
96
- }.tap do |h|
97
- custom_data = JSON.parse(self.value['custom_data']) rescue nil
98
- if custom_data.is_a?(Hash)
99
- h.merge!(custom_data)
100
- end
101
- end
102
- end
103
-
104
- def save
105
- key = "performance|controller|#{controller}|action|#{action}|format|#{format}|status|#{status}|datetime|#{datetime}|datetimei|#{datetimei}|method|#{method}|path|#{path}|request_id|#{request_id}|END|#{RailsPerformance::SCHEMA}"
106
- value = {
107
- view_runtime: view_runtime,
108
- db_runtime: db_runtime,
109
- duration: duration,
110
- http_referer: http_referer,
111
- custom_data: custom_data.to_json
112
- }
113
- value[:exception] = exception if exception.present?
114
- value[:backtrace] = exception_object.backtrace.take(3) if exception_object
115
- Utils.save_to_redis(key, value)
116
- end
117
-
118
- end
119
- end
120
- end
1
+ module RailsPerformance
2
+ module Models
3
+ class RequestRecord < BaseRecord
4
+ attr_accessor :controller, :action, :format, :status, :datetime, :datetimei, :method, :path, :request_id, :json
5
+ attr_accessor :view_runtime, :db_runtime, :duration, :http_referer, :custom_data
6
+ attr_accessor :exception, :exception_object
7
+
8
+ def self.find_by(request_id:)
9
+ keys, values = RailsPerformance::Utils.fetch_from_redis("performance|*|request_id|#{request_id}|*")
10
+
11
+ return nil if keys.blank?
12
+ return nil if values.blank?
13
+
14
+ RailsPerformance::Models::RequestRecord.from_db(keys[0], values[0])
15
+ end
16
+
17
+ # key = performance|
18
+ # controller|HomeController|
19
+ # action|index|
20
+ # format|html|
21
+ # status|200|
22
+ # datetime|20200124T0523|
23
+ # datetimei|1579861423|
24
+ # method|GET|
25
+ # path|/|
26
+ # request_id|454545454545454545|
27
+ # END|1.0.0
28
+ # = {"view_runtime":null,"db_runtime":0,"duration":27.329741000000002,"http_referer":null,"custom_data":null,"exception":"ZeroDivisionError divided by 0","backtrace":["/root/projects/rails_performance/test/dummy/app/controllers/account/site_controller.rb:17:in `/'","/root/projects/rails_performance/test/dummy/app/controllers/account/site_controller.rb:17:in `crash'","/usr/local/rvm/gems/ruby-2.6.3/gems/actionpack-6.1.3.1/lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'"]}
29
+ # value = JSON
30
+ def self.from_db(key, value)
31
+ items = key.split("|")
32
+
33
+ parsed_value = JSON.parse(value) rescue {}
34
+
35
+ RequestRecord.new(
36
+ controller: items[2],
37
+ action: items[4],
38
+ format: items[6],
39
+ status: items[8],
40
+ datetime: items[10],
41
+ datetimei: items[12],
42
+ method: items[14],
43
+ path: items[16],
44
+ request_id: items[18],
45
+ json: value,
46
+ duration: parsed_value["duration"],
47
+ view_runtime: parsed_value["view_runtime"],
48
+ db_runtime: parsed_value["db_runtime"],
49
+ )
50
+ end
51
+
52
+ def initialize(controller:, action:, format:, status:, datetime:, datetimei:, method:, path:, request_id:, view_runtime: nil, db_runtime: nil, duration: nil, http_referer: nil, custom_data: nil, exception: nil, exception_object: nil, json: "{}")
53
+ @controller = controller
54
+ @action = action
55
+ @format = format
56
+ @status = status
57
+ @datetime = datetime
58
+ @datetimei = datetimei.to_i
59
+ @method = method
60
+ @path = path
61
+ @request_id = request_id
62
+
63
+ @view_runtime = view_runtime
64
+ @db_runtime = db_runtime
65
+ @duration = duration
66
+ @http_referer = http_referer
67
+ @custom_data = custom_data
68
+
69
+ @exception = Array.wrap(exception).compact.join(" ")
70
+ @exception_object = exception_object
71
+
72
+ @json = json
73
+ end
74
+
75
+ def controller_action
76
+ "#{controller}##{action}"
77
+ end
78
+
79
+ def controller_action_format
80
+ "#{controller}##{action}|#{format}"
81
+ end
82
+
83
+ # show on UI in the right panel
84
+ def record_hash
85
+ {
86
+ controller: controller,
87
+ action: action,
88
+ format: self.format,
89
+ status: status,
90
+ method: method,
91
+ path: path,
92
+ request_id: request_id,
93
+ datetime: Time.at(datetimei.to_i),
94
+ datetimei: datetimei,
95
+ duration: value["duration"],
96
+ db_runtime: value["db_runtime"],
97
+ view_runtime: value["view_runtime"],
98
+ exception: value["exception"],
99
+ backtrace: value["backtrace"],
100
+ http_referer: value["http_referer"]
101
+ }.tap do |h|
102
+ custom_data = begin
103
+ JSON.parse(value["custom_data"])
104
+ rescue
105
+ nil
106
+ end
107
+ if custom_data.is_a?(Hash)
108
+ h.merge!(custom_data)
109
+ end
110
+ end
111
+ end
112
+
113
+ def save
114
+ key = "performance|controller|#{controller}|action|#{action}|format|#{format}|status|#{status}|datetime|#{datetime}|datetimei|#{datetimei}|method|#{method}|path|#{path}|request_id|#{request_id}|END|#{RailsPerformance::SCHEMA}"
115
+ value = {
116
+ view_runtime: view_runtime,
117
+ db_runtime: db_runtime,
118
+ duration: duration,
119
+ http_referer: http_referer,
120
+ custom_data: custom_data.to_json
121
+ }
122
+ value[:exception] = exception if exception.present?
123
+ value[:backtrace] = exception_object.backtrace.take(3) if exception_object
124
+ Utils.save_to_redis(key, value)
125
+ end
126
+ end
127
+ end
128
+ end