debugbar 0.0.1 → 0.1.0

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 (84) hide show
  1. checksums.yaml +7 -0
  2. data/.prettierrc +6 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +5 -0
  5. data/Rakefile +4 -0
  6. data/app/channels/debugbar/debugbar_channel.rb +26 -0
  7. data/app/controllers/debugbar/application_controller.rb +4 -0
  8. data/app/controllers/debugbar/assets_controller.rb +15 -0
  9. data/app/helpers/debugbar/tag_helpers.rb +19 -0
  10. data/app/models/debugbar/application_record.rb +5 -0
  11. data/client/.gitignore +25 -0
  12. data/client/README.md +0 -0
  13. data/client/dist/.vite/manifest.json +14 -0
  14. data/client/dist/assets/debugbar-u5mP-5-z.js +34 -0
  15. data/client/dist/assets/ruby-logo-kn_8RniZ.svg +946 -0
  16. data/client/index.html +78 -0
  17. data/client/package-lock.json +2393 -0
  18. data/client/package.json +32 -0
  19. data/client/postcss.config.js +6 -0
  20. data/client/src/App.vue +17 -0
  21. data/client/src/AppDemo.vue +29 -0
  22. data/client/src/AppDev.vue +20 -0
  23. data/client/src/Debugbar.vue +276 -0
  24. data/client/src/assets/rails-logo.svg +1 -0
  25. data/client/src/assets/ruby-logo.svg +946 -0
  26. data/client/src/components/TabButton.vue +32 -0
  27. data/client/src/components/panels/CachePanel.vue +41 -0
  28. data/client/src/components/panels/JobsPanel.vue +52 -0
  29. data/client/src/components/panels/JsonPanel.vue +15 -0
  30. data/client/src/components/panels/LogsPanel.vue +43 -0
  31. data/client/src/components/panels/MessagesPanel.vue +25 -0
  32. data/client/src/components/panels/ModelsPanel.vue +37 -0
  33. data/client/src/components/panels/Panel.vue +7 -0
  34. data/client/src/components/panels/RequestPanel.vue +98 -0
  35. data/client/src/components/queries/QueriesPanel.vue +17 -0
  36. data/client/src/components/queries/QueryItem.vue +65 -0
  37. data/client/src/components/ui/Foldable.vue +39 -0
  38. data/client/src/components/ui/KeyValueTable.vue +16 -0
  39. data/client/src/components/ui/Row.vue +14 -0
  40. data/client/src/components/ui/logo-ruby.vue +547 -0
  41. data/client/src/demo.ts +17 -0
  42. data/client/src/dev.ts +20 -0
  43. data/client/src/main.ts +17 -0
  44. data/client/src/models/Config.ts +27 -0
  45. data/client/src/models/Request.ts +183 -0
  46. data/client/src/stores/RequestsStore.ts +36 -0
  47. data/client/src/stores/configStore.ts +8 -0
  48. data/client/src/style.css +23 -0
  49. data/client/src/types.d.ts +9 -0
  50. data/client/src/vite-env.d.ts +1 -0
  51. data/client/tailwind.config.js +16 -0
  52. data/client/tsconfig.json +29 -0
  53. data/client/tsconfig.node.json +10 -0
  54. data/client/vite.config.ts +44 -0
  55. data/config/routes.rb +7 -0
  56. data/debugbar.gemspec +38 -0
  57. data/fixtures/requests/1706607114--demo_post_list.json +499 -0
  58. data/fixtures/requests/1706607120--api_jobs.json +176 -0
  59. data/fixtures/requests/1706607123--api_jobs.json +119 -0
  60. data/fixtures/requests/1706607133--demo_slow_page.json +130 -0
  61. data/fixtures/requests/1706607136--demo_post.json +164 -0
  62. data/fixtures/requests/1706607136--demo_random_post.json +106 -0
  63. data/fixtures/requests/1706607141--api_errors.json +73 -0
  64. data/lib/debugbar/buffers/memory_buffer.rb +34 -0
  65. data/lib/debugbar/buffers/null_buffer.rb +18 -0
  66. data/lib/debugbar/buffers/request_buffer.rb +31 -0
  67. data/lib/debugbar/config.rb +50 -0
  68. data/lib/debugbar/current.rb +18 -0
  69. data/lib/debugbar/engine.rb +96 -5
  70. data/lib/debugbar/loggers/simple_logger.rb +34 -0
  71. data/lib/debugbar/middlewares/track_current_request.rb +35 -0
  72. data/lib/debugbar/request.rb +98 -0
  73. data/lib/debugbar/subscribers/action_controller.rb +33 -0
  74. data/lib/debugbar/subscribers/active_job.rb +158 -0
  75. data/lib/debugbar/subscribers/active_record.rb +65 -0
  76. data/lib/debugbar/subscribers/active_support.rb +30 -0
  77. data/lib/debugbar/version.rb +5 -0
  78. data/lib/debugbar.rb +86 -5
  79. data/package-lock.json +50 -0
  80. data/package.json +5 -0
  81. data/sig/debugbar.rbs +4 -0
  82. metadata +143 -47
  83. data/README.textile +0 -18
  84. data/lib/debugbar/railties/tasks.rake +0 -1
@@ -0,0 +1,106 @@
1
+ {
2
+ "id": "05237876-ee86-4ffd-95de-deff834a2e35",
3
+ "meta": {
4
+ "controller": "DemoController",
5
+ "action": "random_post",
6
+ "params": {
7
+ "controller": "demo",
8
+ "action": "random_post"
9
+ },
10
+ "format": "html",
11
+ "method": "GET",
12
+ "path": "/random",
13
+ "status": 302,
14
+ "view_runtime": null,
15
+ "db_runtime": 13.151000021025538,
16
+ "duration": 16.539000034332275,
17
+ "cpu_time": 3.4336249999999993,
18
+ "idle_time": 13.105375034332276,
19
+ "allocations": 1573
20
+ },
21
+ "request": {
22
+ "method": "GET",
23
+ "path": "/random",
24
+ "format": "html",
25
+ "params": {
26
+ "controller": "demo",
27
+ "action": "random_post"
28
+ },
29
+ "headers": {
30
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
31
+ "Accept-Encoding": "gzip, deflate, br",
32
+ "Accept-Language": "fr,en;q=0.9",
33
+ "Connection": "keep-alive",
34
+ "Cookie": "_demo_app_session=BQrfrqwaDxQLlcrCZCSwiiJrCVN6pWaGEmTUMl5s%2BWP2xDdT5GgSbZ1GjUxNevxh9zy%2FCWIXiCSkpd1bAMAEefyD7BUi4cgt%2BQ4xclmmUfebk8Hnl1sw0fhO0uGUk%2BsR6rZdEHZf%2FOQcUtzhuvk%2BNO4JdOoqLPqD6Z9A%2FuvUroWg3NHedrkYIx5yESdgdL7vYseAorT%2B2BtUH%2BRCftEXrEWRWdWyBHDgAanAcwu96zfwLBURN9h%2FAUBPn8wtvCc%2BoZPQXJlDGXSVEUxLd%2FiZ4INeR707T7HyCw%3D%3D--xI%2FllNiOtCHGENRn--%2Bh1H%2FRmTDAzWYcvTavhbTQ%3D%3D",
35
+ "Dnt": "1",
36
+ "Host": "127.0.0.1:3000",
37
+ "Referer": "http://127.0.0.1:3000/slow-page",
38
+ "Sec-Ch-Ua": "\"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\", \"Google Chrome\";v=\"120\"",
39
+ "Sec-Ch-Ua-Mobile": "?0",
40
+ "Sec-Ch-Ua-Platform": "\"macOS\"",
41
+ "Sec-Fetch-Dest": "document",
42
+ "Sec-Fetch-Mode": "navigate",
43
+ "Sec-Fetch-Site": "same-origin",
44
+ "Sec-Fetch-User": "?1",
45
+ "Upgrade-Insecure-Requests": "1",
46
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
47
+ "Version": "HTTP/1.1"
48
+ }
49
+ },
50
+ "response": {
51
+ "status": 302,
52
+ "headers": {
53
+ "X-Frame-Options": "SAMEORIGIN",
54
+ "X-Xss-Protection": "0",
55
+ "X-Content-Type-Options": "nosniff",
56
+ "X-Permitted-Cross-Domain-Policies": "none",
57
+ "Referrer-Policy": "strict-origin-when-cross-origin",
58
+ "Location": "http://127.0.0.1:3000/post/930",
59
+ "Content-Type": "text/html; charset=utf-8",
60
+ "Cache-Control": "no-cache"
61
+ },
62
+ "body": ""
63
+ },
64
+ "models": {
65
+ "Post": 1
66
+ },
67
+ "queries": [
68
+ {
69
+ "id": "a49beead96b5a5e5ec7b",
70
+ "title": "Post Load (13.2ms)",
71
+ "name": "Post Load",
72
+ "sql": "SELECT `posts`.* FROM `posts` ORDER BY RAND() LIMIT 1 ",
73
+ "cached": false,
74
+ "async": false,
75
+ "duration": 13.2,
76
+ "lock_wait": null,
77
+ "binds": null,
78
+ "source": [
79
+ "/Users/julien.bourdeau/Personal/rails/demo_app/app/controllers/demo_controller.rb:20",
80
+ " `random_post'"
81
+ ]
82
+ }
83
+ ],
84
+ "jobs": [
85
+
86
+ ],
87
+ "messages": [
88
+ {
89
+ "msg": "before_action",
90
+ "extra": [
91
+ {
92
+ "params": {
93
+ "controller": "demo",
94
+ "action": "random_post"
95
+ }
96
+ }
97
+ ]
98
+ }
99
+ ],
100
+ "cache": [
101
+
102
+ ],
103
+ "logs": [
104
+
105
+ ]
106
+ }
@@ -0,0 +1,73 @@
1
+ {
2
+ "id": "c38fed3f-4600-4ab4-96b2-1f03510db13a",
3
+ "meta": {
4
+ "controller": "ApiController",
5
+ "action": "errors",
6
+ "params": {
7
+ "code": "500",
8
+ "controller": "api",
9
+ "action": "errors"
10
+ },
11
+ "format": "*/*",
12
+ "method": "GET",
13
+ "path": "/api/errors?code=500",
14
+ "status": 500,
15
+ "view_runtime": null,
16
+ "db_runtime": 0.0,
17
+ "exception": [
18
+ "RuntimeError",
19
+ "This is a test error"
20
+ ],
21
+ "exception_object": "This is a test error",
22
+ "duration": 1.061000108718872,
23
+ "cpu_time": 0.649708000000004,
24
+ "idle_time": 0.4112921087188681,
25
+ "allocations": 551
26
+ },
27
+ "request": {
28
+ "method": "GET",
29
+ "path": "/api/errors",
30
+ "format": "*/*",
31
+ "params": {
32
+ "code": "500",
33
+ "controller": "api",
34
+ "action": "errors"
35
+ },
36
+ "headers": {
37
+ "Accept": "*/*",
38
+ "Accept-Encoding": "gzip, deflate, br",
39
+ "Accept-Language": "fr,en;q=0.9",
40
+ "Connection": "keep-alive",
41
+ "Cookie": "_demo_app_session=TXrvUIFrjCCzEF5STOJH4y3LxjezAtOH0LvuLn8ubvx5%2F7Ki2y%2FGB5zO%2Bb%2BWPhvEeyJXbGRn5WtG2EQUK7cfWlXDQ69Pl35stBJZD2RfAFgzJeVYiqNnRttqmN6caQzfqKMJoGlGL%2B%2BUdlJPWFw7r24FZ960BsHrem6dXmf%2Fc3ulZUMwAq13%2BvRavwYOEvBv%2BzfdMUEuwXXDL0rArzZpmbrPYWevNasPSTrZXcyn4pY9qV1d%2BVINEYhiDTgaHv%2BveYMf5jXTjoVDA3lUDBMYPHU5EMMmce24hw%3D%3D--y7dDFZ0aVSPS0S2f--til504PhC6CQcoMmYKj2YQ%3D%3D",
42
+ "Dnt": "1",
43
+ "Host": "127.0.0.1:3000",
44
+ "Referer": "http://127.0.0.1:3000/post/930",
45
+ "Sec-Ch-Ua": "\"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\", \"Google Chrome\";v=\"120\"",
46
+ "Sec-Ch-Ua-Mobile": "?0",
47
+ "Sec-Ch-Ua-Platform": "\"macOS\"",
48
+ "Sec-Fetch-Dest": "empty",
49
+ "Sec-Fetch-Mode": "cors",
50
+ "Sec-Fetch-Site": "same-origin",
51
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
52
+ "Version": "HTTP/1.1"
53
+ }
54
+ },
55
+ "response": null,
56
+ "models": {
57
+ },
58
+ "queries": [
59
+
60
+ ],
61
+ "jobs": [
62
+
63
+ ],
64
+ "messages": [
65
+
66
+ ],
67
+ "cache": [
68
+
69
+ ],
70
+ "logs": [
71
+
72
+ ]
73
+ }
@@ -0,0 +1,34 @@
1
+ module Debugbar
2
+ class MemoryBuffer
3
+ def initialize
4
+ @collection = {}
5
+ end
6
+
7
+ def push(request)
8
+ @collection[request.id] = request
9
+ nil
10
+ end
11
+
12
+ def remove(ids)
13
+ ids = Array.wrap(ids)
14
+ ids.each do |id|
15
+ @collection.delete(id)
16
+ end
17
+ :self
18
+ end
19
+
20
+ def all
21
+ @collection.values
22
+ end
23
+
24
+ def each(&block)
25
+ @collection.each(&block)
26
+ :self
27
+ end
28
+
29
+ def clear!
30
+ @collection = {}
31
+ :self
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,18 @@
1
+ module Debugbar
2
+ class NullBuffer
3
+ def push(_request)
4
+ end
5
+
6
+ def remove(_ids)
7
+ end
8
+
9
+ def all
10
+ end
11
+
12
+ def each
13
+ end
14
+
15
+ def clear!
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ module Debugbar
2
+ class RequestBuffer
3
+ class << self
4
+ def init(adapter)
5
+ @enabled = false
6
+ @adapter = adapter
7
+ end
8
+
9
+ def enable!
10
+ @enabled = true
11
+ send_all
12
+ end
13
+
14
+ def disable!
15
+ @enabled = false
16
+ end
17
+
18
+ def send_all
19
+ data = @collection.values.map(&:to_h)
20
+ ActionCable.server.broadcast("debugbar_channel", data)
21
+ end
22
+
23
+ %w(push each all remove clear!).each do |name|
24
+ define_method(name) do |*args, &block|
25
+ ret = @adapter.send(name, *args, &block)
26
+ ret == :self ? self : ret
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,50 @@
1
+ module Debugbar
2
+ class Config
3
+ attr_accessor :enabled, :prefix, :buffer_adapter, :ignore_request,
4
+ :active_record, :action_controller, :active_job,
5
+ :min_log_level
6
+
7
+ alias_method :enabled?, :enabled
8
+
9
+ def initialize(options = {})
10
+ opt = defaults.merge options
11
+ @enabled = opt[:enabled] && !defined?(Rails::Console)
12
+ @prefix = opt[:prefix]
13
+ @active_record = opt[:active_record]
14
+ @action_controller = opt[:action_controller]
15
+ @active_job = opt[:active_job]
16
+ @min_log_level = opt[:min_log_level]
17
+ @buffer_adapter = opt[:buffer_adapter]
18
+ end
19
+
20
+ def defaults
21
+ {
22
+ enabled: Rails.env.development?,
23
+ prefix: "/_debugbar",
24
+ active_record: true,
25
+ action_controller: true,
26
+ active_job: true,
27
+ min_log_level: -1,
28
+ buffer_adapter: :memory,
29
+ }
30
+ end
31
+
32
+ def ignore_request?(env)
33
+ if ignore_request.is_a? Proc
34
+ ignore_request.call(env)
35
+ else
36
+ [Debugbar.config.prefix, "/assets"].any? { |s| env['PATH_INFO'].start_with? s }
37
+ end
38
+ end
39
+
40
+ def use_logger?
41
+ @enabled && @min_log_level >= 0
42
+ end
43
+
44
+ %w(active_record action_controller active_job).each do |name|
45
+ define_method("#{name}?") do
46
+ @enabled && instance_variable_get("@#{name}")
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Debugbar
4
+ class Current < ActiveSupport::CurrentAttributes
5
+ attribute :request
6
+ attribute :ignore
7
+
8
+ alias_method :ignore?, :ignore
9
+
10
+ def new_request!(request_id)
11
+ self.request = Request.new(request_id)
12
+ end
13
+
14
+ def pop_request!
15
+ request.tap { self.request = nil }
16
+ end
17
+ end
18
+ end
@@ -1,10 +1,101 @@
1
+ require_relative 'config'
2
+ require_relative 'middlewares/track_current_request'
3
+
1
4
  module Debugbar
2
- class Engine < Rails::Engine
3
- # This should fix rails3 rc, and also work with beta
4
- config.autoload_paths << File.expand_path(File.join(File.dirname(__FILE__), "..", "..")) if config.respond_to? :autoload_paths
5
+ class Engine < ::Rails::Engine
6
+ isolate_namespace Debugbar
7
+
8
+ initializer 'debugbar.config' do |app|
9
+ app.config.debugbar = ::Debugbar.config
10
+ end
11
+
12
+ initializer 'debugbar.init' do |app|
13
+ adapter = case(app.config.debugbar.buffer_adapter)
14
+ when :memory
15
+ require_relative 'buffers/memory_buffer'
16
+ MemoryBuffer.new
17
+ when :null
18
+ require_relative 'buffers/null_buffer'
19
+ NullBuffer.new
20
+ else
21
+ throw "Invalid RequestBuffer adapter"
22
+ end
23
+
24
+ Debugbar::RequestBuffer.init(adapter)
25
+ end
26
+
27
+ initializer 'debugbar.helper' do
28
+ ActiveSupport.on_load(:action_controller) do
29
+ ActionController::Base.helper(Debugbar::TagHelpers)
30
+ end
31
+
32
+ ActiveSupport.on_load(:action_view) do
33
+ include Debugbar::TagHelpers
34
+ end
35
+ end
36
+
37
+ initializer 'debugbar.assets' do
38
+ dist = File.join(Gem.loaded_specs['debugbar'].full_gem_path, 'client', 'dist')
39
+ manifest_file = File.join(dist, '.vite', 'manifest.json')
40
+ manifest = JSON.parse(File.read(manifest_file))
41
+
42
+ Debugbar.js_file = File.join(dist, manifest['src/main.ts']['file'])
43
+ end
44
+
45
+ initializer 'debugbar.inject_middlewares' do |app|
46
+ next unless Debugbar.config.enabled?
47
+ app.middleware.insert_after ActionDispatch::RequestId, Debugbar::TrackCurrentRequest
48
+ end
49
+
50
+ initializer 'debugbar.subscribe' do
51
+ if Debugbar.config.active_record?
52
+ require_relative 'subscribers/active_record'
53
+ subscribe "Debugbar::ActiveRecordEventSubscriber" => "sql.active_record"
54
+ end
55
+
56
+ if Debugbar.config.action_controller?
57
+ require_relative 'subscribers/action_controller'
58
+ subscribe "Debugbar::ActionControllerEventSubscriber" => %w[
59
+ start_processing.action_controller process_action.action_controller
60
+ ]
61
+ end
62
+
63
+ if Debugbar.config.active_job?
64
+ require_relative 'subscribers/active_job'
65
+ subscribe "Debugbar::ActiveJobEventSubscriber" => ["enqueue.active_job", "enqueue_at.active_job"]
66
+ end
67
+
68
+ require_relative 'subscribers/active_support'
69
+ subscribe "Debugbar::ActiveSupportEventSubscriber.cache" => %w(
70
+ cache_read.active_support
71
+ cache_generate.active_support
72
+ cache_fetch_hit.active_support
73
+ cache_write.active_support
74
+ cache_delete.active_support
75
+ cache_exist?.active_support
76
+ )
77
+ end
78
+
79
+ initializer 'debugbar.track_models' do
80
+ next unless Debugbar.config.active_record?
81
+ ActiveSupport.on_load(:active_record) do
82
+ after_initialize do |model|
83
+ Debugbar::Tracker.inc_model(model.class.name)
84
+ end
85
+ end
86
+ end
5
87
 
6
- rake_tasks do
7
- load "debugbar/railties/tasks.rake"
88
+ def subscribe(config)
89
+ config.each do |subscriber, event_names|
90
+ event_names = Array.wrap(event_names)
91
+ class_name, class_method_name = subscriber.split('.')
92
+ event_names.each do |name|
93
+ method_name = class_method_name || name.split('.').first
94
+ ActiveSupport::Notifications.subscribe name do |event|
95
+ class_name.constantize.send method_name, event
96
+ end
97
+ end
98
+ end
8
99
  end
9
100
  end
10
101
  end
@@ -0,0 +1,34 @@
1
+ module Debugbar
2
+ class SimpleLogger < ::Logger
3
+ def initialize(min_level= 2)
4
+ @min_level = min_level
5
+ end
6
+
7
+ def add(severity, message = nil, progname = nil)
8
+ # We normally rely on the Tracker to know if the current request is set or nil and log an error to STDOUT,
9
+ # but in this case, it happens so often that the logs are annoying.
10
+ # In ActiveCable, only the first call goes through the Rake middleware, so every following communication
11
+ # doesn't go through TrackCurrentRequest, which initializes the request.
12
+ return if ::Debugbar::Current.request.nil?
13
+
14
+ return if severity < @min_level
15
+
16
+ if message.nil?
17
+ if block_given?
18
+ message = yield
19
+ else
20
+ message = progname
21
+ progname = nil
22
+ end
23
+ end
24
+
25
+ Debugbar::Tracker.add_log({
26
+ time: Time.now.strftime(Debugbar::TIME_FORMAT),
27
+ severity: severity,
28
+ severity_label: SEV_LABEL[severity],
29
+ message: message,
30
+ progname: progname,
31
+ })
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,35 @@
1
+ module Debugbar
2
+ class TrackCurrentRequest
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ Debugbar::Current.ignore = Debugbar.config.ignore_request?(env)
9
+
10
+ return @app.call(env) if Debugbar::Current.ignore?
11
+
12
+ Debugbar::Current.new_request!(env['action_dispatch.request_id'])
13
+
14
+ res = @app.call(env)
15
+
16
+ # TODO: Remove this if statement?
17
+ if Debugbar::Current.request&.id
18
+ # filename = "#{Time.now.to_i}--#{Debugbar::Current.request.meta.dig(:params, :controller)}_#{Debugbar::Current.request.meta.dig(:params, :action).gsub('/', '_')}.json"
19
+ # File.open(Rails.root.join('_requests', filename), "w") do |f|
20
+ # f.write(Debugbar::Current.request.to_json)
21
+ # end
22
+
23
+ RequestBuffer.push(Debugbar::Current.pop_request!)
24
+
25
+ if Debugbar.connected?
26
+ data = RequestBuffer.all.map(&:to_h)
27
+ ActionCable.server.broadcast("debugbar_channel", data)
28
+ end
29
+ end
30
+
31
+ res
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,98 @@
1
+ module Debugbar
2
+ class Request
3
+ attr_reader :request_id, :meta,
4
+ :models, :queries, :jobs,
5
+ :messages, :cache, :logs
6
+ attr_accessor :request, :response, :headers
7
+
8
+ def initialize(request_id)
9
+ @request_id = request_id
10
+ @models = {}
11
+ @queries = []
12
+ @jobs = []
13
+ @messages = []
14
+ @cache = []
15
+ @logs = []
16
+ end
17
+
18
+ alias_method :id, :request_id
19
+
20
+ def meta=(meta)
21
+ meta.delete(:headers)
22
+ meta.delete(:request)
23
+ meta.delete(:response)
24
+ @meta = meta
25
+ end
26
+
27
+ def inc_model(name)
28
+ if @models[name]
29
+ @models[name] += 1
30
+ else
31
+ @models[name] = 1
32
+ end
33
+ end
34
+
35
+ def add_query(query)
36
+ @queries << query
37
+ end
38
+
39
+ def add_job(job)
40
+ @jobs << job
41
+ end
42
+
43
+ def add_msg(msg, extra)
44
+ @messages << {msg: msg, extra: extra}
45
+ end
46
+
47
+ def add_cache(c)
48
+ @cache << c
49
+ end
50
+
51
+ def add_log(l)
52
+ @logs << l
53
+ end
54
+
55
+ def to_h
56
+ {
57
+ id: request_id,
58
+ meta: meta,
59
+ request: request_hash,
60
+ response: response_hash,
61
+ models: models,
62
+ queries: queries,
63
+ jobs: jobs,
64
+ messages: messages,
65
+ cache: cache,
66
+ logs: logs,
67
+ }
68
+ end
69
+
70
+ def to_json
71
+ JSON.pretty_generate(to_h)
72
+ end
73
+
74
+ private
75
+
76
+ def request_hash
77
+ {
78
+ method: request.method,
79
+ path: request.path,
80
+ format: meta.dig(:format),
81
+ params: meta.dig(:params),
82
+ headers: request.env.select { |k,v| k.start_with? 'HTTP_'} # https://stackoverflow.com/a/55406700/1001125
83
+ .transform_keys { |k| k.sub(/^HTTP_/, '').split('_').map(&:capitalize).join('-') }
84
+ .sort.to_h
85
+ }
86
+ end
87
+
88
+ def response_hash
89
+ return nil if response.nil?
90
+
91
+ {
92
+ status: response.status,
93
+ headers: response.headers.to_h.transform_keys { |s| s.split('-').map(&:capitalize).join('-') },
94
+ body: response.body,
95
+ }
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,33 @@
1
+ module Debugbar
2
+ class ActionControllerEventSubscriber
3
+ class << self
4
+ def start_processing(event)
5
+ return if Debugbar::Current.ignore?
6
+
7
+ Debugbar::Tracker.request = event.payload[:request]
8
+ end
9
+
10
+ def process_action(event)
11
+ return if Debugbar::Current.ignore?
12
+
13
+ meta = event.payload
14
+
15
+ meta.delete :headers
16
+ request = meta.delete :request
17
+ response = meta.delete :response
18
+
19
+ meta.merge!({
20
+ duration: event.duration,
21
+ cpu_time: event.cpu_time,
22
+ idle_time: event.idle_time,
23
+ allocations: event.allocations,
24
+ })
25
+
26
+ Debugbar::Tracker.request = request
27
+ Debugbar::Tracker.response = response
28
+ Debugbar::Tracker.meta = meta
29
+
30
+ end
31
+ end
32
+ end
33
+ end