rails_live_dashboard 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 (78) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +63 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/builds/rails_live_dashboard/application.css +1 -0
  6. data/app/assets/builds/rails_live_dashboard/application.js +39 -0
  7. data/app/assets/builds/rails_live_dashboard/application.js.map +7 -0
  8. data/app/assets/javascripts/rails_live_dashboard/application.js +2 -0
  9. data/app/assets/javascripts/rails_live_dashboard/controllers/application.js +9 -0
  10. data/app/assets/javascripts/rails_live_dashboard/controllers/index.js +6 -0
  11. data/app/assets/javascripts/rails_live_dashboard/controllers/reveal_controller.js +28 -0
  12. data/app/assets/javascripts/rails_live_dashboard/controllers/tabs_controller.js +37 -0
  13. data/app/assets/stylesheets/rails_live_dashboard/application.css +5 -0
  14. data/app/components/rails_live_dashboard/query_duration_badge_component.html.erb +3 -0
  15. data/app/components/rails_live_dashboard/query_duration_badge_component.rb +27 -0
  16. data/app/components/rails_live_dashboard/request_duration_badge_component.html.erb +3 -0
  17. data/app/components/rails_live_dashboard/request_duration_badge_component.rb +27 -0
  18. data/app/components/rails_live_dashboard/request_method_badge_component.html.erb +6 -0
  19. data/app/components/rails_live_dashboard/request_method_badge_component.rb +24 -0
  20. data/app/components/rails_live_dashboard/request_status_badge_component.html.erb +3 -0
  21. data/app/components/rails_live_dashboard/request_status_badge_component.rb +22 -0
  22. data/app/controllers/rails_live_dashboard/application_controller.rb +4 -0
  23. data/app/controllers/rails_live_dashboard/clean_controller.rb +9 -0
  24. data/app/controllers/rails_live_dashboard/dashboard_controller.rb +8 -0
  25. data/app/controllers/rails_live_dashboard/exceptions_controller.rb +13 -0
  26. data/app/controllers/rails_live_dashboard/queries_controller.rb +11 -0
  27. data/app/controllers/rails_live_dashboard/requests_controller.rb +13 -0
  28. data/app/controllers/rails_live_dashboard/widgets/slowest_queries_controller.rb +11 -0
  29. data/app/controllers/rails_live_dashboard/widgets/slowest_requests_controller.rb +11 -0
  30. data/app/helpers/rails_live_dashboard/application_helper.rb +4 -0
  31. data/app/helpers/rails_live_dashboard/clean_helper.rb +4 -0
  32. data/app/helpers/rails_live_dashboard/dashboard_helper.rb +4 -0
  33. data/app/helpers/rails_live_dashboard/exceptions_helper.rb +4 -0
  34. data/app/helpers/rails_live_dashboard/requests_helper.rb +4 -0
  35. data/app/jobs/rails_live_dashboard/application_job.rb +4 -0
  36. data/app/mailers/rails_live_dashboard/application_mailer.rb +6 -0
  37. data/app/models/rails_live_dashboard/application_record.rb +5 -0
  38. data/app/models/rails_live_dashboard/entry.rb +5 -0
  39. data/app/models/rails_live_dashboard/exception.rb +31 -0
  40. data/app/models/rails_live_dashboard/query.rb +5 -0
  41. data/app/models/rails_live_dashboard/request.rb +45 -0
  42. data/app/models/rails_live_dashboard/types/content.rb +32 -0
  43. data/app/models/rails_live_dashboard/types/exception_content.rb +42 -0
  44. data/app/models/rails_live_dashboard/types/query_content.rb +42 -0
  45. data/app/models/rails_live_dashboard/types/request_content.rb +49 -0
  46. data/app/views/layouts/rails_live_dashboard/application.html.erb +18 -0
  47. data/app/views/rails_live_dashboard/dashboard/show.html.erb +27 -0
  48. data/app/views/rails_live_dashboard/exceptions/_tabs.html.erb +16 -0
  49. data/app/views/rails_live_dashboard/exceptions/index.html.erb +55 -0
  50. data/app/views/rails_live_dashboard/exceptions/show.html.erb +41 -0
  51. data/app/views/rails_live_dashboard/queries/_list.html.erb +43 -0
  52. data/app/views/rails_live_dashboard/queries/index.html.erb +11 -0
  53. data/app/views/rails_live_dashboard/queries/show.html.erb +33 -0
  54. data/app/views/rails_live_dashboard/requests/_contents.html.erb +26 -0
  55. data/app/views/rails_live_dashboard/requests/_exceptions.html.erb +43 -0
  56. data/app/views/rails_live_dashboard/requests/_queries.html.erb +11 -0
  57. data/app/views/rails_live_dashboard/requests/_relateds.html.erb +23 -0
  58. data/app/views/rails_live_dashboard/requests/index.html.erb +48 -0
  59. data/app/views/rails_live_dashboard/requests/show.html.erb +46 -0
  60. data/app/views/rails_live_dashboard/shared/_header.html.erb +43 -0
  61. data/app/views/rails_live_dashboard/widgets/slowest_queries/show.html.erb +42 -0
  62. data/app/views/rails_live_dashboard/widgets/slowest_requests/show.html.erb +42 -0
  63. data/config/routes.rb +14 -0
  64. data/db/migrate/20240213133517_create_rails_live_dashboard_entries.rb +14 -0
  65. data/lib/generators/rails_live_dashboard/install_generator.rb +11 -0
  66. data/lib/generators/templates/initializer.rb +3 -0
  67. data/lib/rails_live_dashboard/configuration.rb +13 -0
  68. data/lib/rails_live_dashboard/context.rb +19 -0
  69. data/lib/rails_live_dashboard/engine.rb +28 -0
  70. data/lib/rails_live_dashboard/recorders/exception_recorder.rb +42 -0
  71. data/lib/rails_live_dashboard/recorders/query_recorder.rb +30 -0
  72. data/lib/rails_live_dashboard/recorders/request_recorder.rb +30 -0
  73. data/lib/rails_live_dashboard/subscribers/action_controller_subscriber.rb +28 -0
  74. data/lib/rails_live_dashboard/subscribers/active_record_subscriber.rb +23 -0
  75. data/lib/rails_live_dashboard/version.rb +3 -0
  76. data/lib/rails_live_dashboard.rb +19 -0
  77. data/lib/tasks/rails_live_dashboard_tasks.rake +4 -0
  78. metadata +136 -0
@@ -0,0 +1,19 @@
1
+ require 'singleton'
2
+
3
+ module RailsLiveDashboard
4
+ class Context
5
+ include Singleton
6
+
7
+ def start
8
+ @batch_id = SecureRandom.uuid
9
+ end
10
+
11
+ def batch_id
12
+ @batch_id ||= SecureRandom.uuid
13
+ end
14
+
15
+ def reset
16
+ @batch_id = nil
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ module RailsLiveDashboard
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace RailsLiveDashboard
4
+
5
+ initializer 'rails_live_dashboard', after: :load_config_initializers do |_app|
6
+ next unless RailsLiveDashboard.configuration.enabled
7
+ end
8
+
9
+ initializer 'rails_live_dashboard.assets.precompile' do |app|
10
+ next unless RailsLiveDashboard.configuration.enabled
11
+
12
+ app.config.assets.precompile += [
13
+ 'builds/rails_live_dashboard/application.js',
14
+ 'builds/rails_live_dashboard/application.css'
15
+ ]
16
+ end
17
+
18
+ initializer 'rails_live_dashboard.action_controller' do
19
+ next unless RailsLiveDashboard.configuration.enabled
20
+
21
+ Subscribers::ActionControllerSubscriber.new
22
+ end
23
+
24
+ initializer 'rails_live_dashboard.action_record' do
25
+ Subscribers::ActiveRecordSubscriber.new
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,42 @@
1
+ module RailsLiveDashboard
2
+ module Recorders
3
+ class ExceptionRecorder
4
+ def initialize(exception)
5
+ @exception = exception
6
+ end
7
+
8
+ def execute
9
+ Exception.of_class(@exception.class).update_all(should_show: false)
10
+
11
+ Exception.create(
12
+ batch_id: RailsLiveDashboard::Context.instance.batch_id,
13
+ content: build_content
14
+ )
15
+ end
16
+
17
+ private
18
+
19
+ def build_content
20
+ occurrences = Exception.of_class(@exception.class).count
21
+
22
+ {
23
+ class: @exception.class,
24
+ message: @exception.message,
25
+ file: file_line[0],
26
+ line: file_line[1],
27
+ backtrace: @exception.backtrace,
28
+ occurrences: occurrences + 1
29
+ }
30
+ end
31
+
32
+ def file_line
33
+ return ['', ''] unless @exception.backtrace
34
+
35
+ file = @exception.backtrace[0].split(':').first
36
+ line = @exception.backtrace[0].split(':')[1]
37
+
38
+ [file, line]
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,30 @@
1
+ module RailsLiveDashboard
2
+ module Recorders
3
+ class QueryRecorder
4
+ def initialize(event)
5
+ @event = event
6
+ end
7
+
8
+ def execute
9
+ Query.create(
10
+ batch_id: RailsLiveDashboard::Context.instance.batch_id,
11
+ content: build_content
12
+ )
13
+ end
14
+
15
+ private
16
+
17
+ def build_content
18
+ payload = @event.payload
19
+ {
20
+ name: payload[:name],
21
+ sql: payload[:sql].strip.gsub(/(^(\s+)?$\n)/, ''),
22
+ parameters: payload[:type_casted_binds],
23
+ duration: (@event.end - @event.time).round(2),
24
+ kind: payload[:sql].match(/INSERT|UPDATE|DELETE/) ? 'WRITE' : 'READ',
25
+ cached: payload[:cached] ? true : false
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ module RailsLiveDashboard
2
+ module Recorders
3
+ class RequestRecorder
4
+ def initialize(event)
5
+ @event = event
6
+ end
7
+
8
+ def execute
9
+ Request.create(
10
+ batch_id: RailsLiveDashboard::Context.instance.batch_id,
11
+ content: build_content
12
+ )
13
+ end
14
+
15
+ private
16
+
17
+ def build_content
18
+ payload = @event.payload
19
+ payload.merge(
20
+ {
21
+ headers: payload[:request].headers.env.reject { |key| key.to_s.include?('.') },
22
+ body: payload[:response]&.body || nil,
23
+ duration: @event.duration.round(2),
24
+ allocations: @event.allocations
25
+ }
26
+ )
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ module RailsLiveDashboard
2
+ module Subscribers
3
+ class ActionControllerSubscriber
4
+ def initialize
5
+ ActiveSupport::Notifications.subscribe 'start_processing.action_controller' do |_event|
6
+ RailsLiveDashboard::Context.instance.start
7
+ end
8
+
9
+ ActiveSupport::Notifications.subscribe 'process_action.action_controller' do |event|
10
+ next if event.payload[:controller].include?('RailsLiveDashboard')
11
+
12
+ handle_event(event)
13
+ rescue StandardError => e
14
+ Rails.logger.error "Error on handle action controller event: #{e.message}"
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def handle_event(event)
21
+ Recorders::RequestRecorder.new(event).execute
22
+ Recorders::ExceptionRecorder.new(event.payload[:exception_object]).execute if event.payload[:exception_object]
23
+
24
+ RailsLiveDashboard::Context.instance.reset
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ module RailsLiveDashboard
2
+ module Subscribers
3
+ class ActiveRecordSubscriber
4
+ def initialize
5
+ ActiveSupport::Notifications.subscribe 'sql.active_record' do |event|
6
+ next if should_skip(event)
7
+
8
+ Recorders::QueryRecorder.new(event).execute
9
+ rescue StandardError => e
10
+ Rails.logger.error "ActionRecordSubscriber - Error on handle active record event: #{e.message}"
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def should_skip(event)
17
+ event.payload[:name].blank? ||
18
+ event.payload[:name].match(/SCHEMA|TRANSACTION|ActiveRecord|RailsLiveDashboard/) ||
19
+ event.payload[:sql].match(/BEGIN|COMMIT/)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ module RailsLiveDashboard
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,19 @@
1
+ require 'rails_live_dashboard/version'
2
+ require 'rails_live_dashboard/engine'
3
+ require 'rails_live_dashboard/configuration'
4
+ require 'rails_live_dashboard/context'
5
+ require 'rails_live_dashboard/recorders/exception_recorder'
6
+ require 'rails_live_dashboard/recorders/request_recorder'
7
+ require 'rails_live_dashboard/recorders/query_recorder'
8
+ require 'rails_live_dashboard/subscribers/action_controller_subscriber'
9
+ require 'rails_live_dashboard/subscribers/active_record_subscriber'
10
+
11
+ module RailsLiveDashboard
12
+ def self.configuration
13
+ @configuration ||= Configuration.instance
14
+ end
15
+
16
+ def self.configure
17
+ yield(configuration)
18
+ end
19
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :rails_live_dashboard do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_live_dashboard
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Anderson Dalmina
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-02-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 7.1.3
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 7.1.3
27
+ description: Realtime dashboard for Rails applications
28
+ email:
29
+ - andersondalmina@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - MIT-LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - app/assets/builds/rails_live_dashboard/application.css
38
+ - app/assets/builds/rails_live_dashboard/application.js
39
+ - app/assets/builds/rails_live_dashboard/application.js.map
40
+ - app/assets/javascripts/rails_live_dashboard/application.js
41
+ - app/assets/javascripts/rails_live_dashboard/controllers/application.js
42
+ - app/assets/javascripts/rails_live_dashboard/controllers/index.js
43
+ - app/assets/javascripts/rails_live_dashboard/controllers/reveal_controller.js
44
+ - app/assets/javascripts/rails_live_dashboard/controllers/tabs_controller.js
45
+ - app/assets/stylesheets/rails_live_dashboard/application.css
46
+ - app/components/rails_live_dashboard/query_duration_badge_component.html.erb
47
+ - app/components/rails_live_dashboard/query_duration_badge_component.rb
48
+ - app/components/rails_live_dashboard/request_duration_badge_component.html.erb
49
+ - app/components/rails_live_dashboard/request_duration_badge_component.rb
50
+ - app/components/rails_live_dashboard/request_method_badge_component.html.erb
51
+ - app/components/rails_live_dashboard/request_method_badge_component.rb
52
+ - app/components/rails_live_dashboard/request_status_badge_component.html.erb
53
+ - app/components/rails_live_dashboard/request_status_badge_component.rb
54
+ - app/controllers/rails_live_dashboard/application_controller.rb
55
+ - app/controllers/rails_live_dashboard/clean_controller.rb
56
+ - app/controllers/rails_live_dashboard/dashboard_controller.rb
57
+ - app/controllers/rails_live_dashboard/exceptions_controller.rb
58
+ - app/controllers/rails_live_dashboard/queries_controller.rb
59
+ - app/controllers/rails_live_dashboard/requests_controller.rb
60
+ - app/controllers/rails_live_dashboard/widgets/slowest_queries_controller.rb
61
+ - app/controllers/rails_live_dashboard/widgets/slowest_requests_controller.rb
62
+ - app/helpers/rails_live_dashboard/application_helper.rb
63
+ - app/helpers/rails_live_dashboard/clean_helper.rb
64
+ - app/helpers/rails_live_dashboard/dashboard_helper.rb
65
+ - app/helpers/rails_live_dashboard/exceptions_helper.rb
66
+ - app/helpers/rails_live_dashboard/requests_helper.rb
67
+ - app/jobs/rails_live_dashboard/application_job.rb
68
+ - app/mailers/rails_live_dashboard/application_mailer.rb
69
+ - app/models/rails_live_dashboard/application_record.rb
70
+ - app/models/rails_live_dashboard/entry.rb
71
+ - app/models/rails_live_dashboard/exception.rb
72
+ - app/models/rails_live_dashboard/query.rb
73
+ - app/models/rails_live_dashboard/request.rb
74
+ - app/models/rails_live_dashboard/types/content.rb
75
+ - app/models/rails_live_dashboard/types/exception_content.rb
76
+ - app/models/rails_live_dashboard/types/query_content.rb
77
+ - app/models/rails_live_dashboard/types/request_content.rb
78
+ - app/views/layouts/rails_live_dashboard/application.html.erb
79
+ - app/views/rails_live_dashboard/dashboard/show.html.erb
80
+ - app/views/rails_live_dashboard/exceptions/_tabs.html.erb
81
+ - app/views/rails_live_dashboard/exceptions/index.html.erb
82
+ - app/views/rails_live_dashboard/exceptions/show.html.erb
83
+ - app/views/rails_live_dashboard/queries/_list.html.erb
84
+ - app/views/rails_live_dashboard/queries/index.html.erb
85
+ - app/views/rails_live_dashboard/queries/show.html.erb
86
+ - app/views/rails_live_dashboard/requests/_contents.html.erb
87
+ - app/views/rails_live_dashboard/requests/_exceptions.html.erb
88
+ - app/views/rails_live_dashboard/requests/_queries.html.erb
89
+ - app/views/rails_live_dashboard/requests/_relateds.html.erb
90
+ - app/views/rails_live_dashboard/requests/index.html.erb
91
+ - app/views/rails_live_dashboard/requests/show.html.erb
92
+ - app/views/rails_live_dashboard/shared/_header.html.erb
93
+ - app/views/rails_live_dashboard/widgets/slowest_queries/show.html.erb
94
+ - app/views/rails_live_dashboard/widgets/slowest_requests/show.html.erb
95
+ - config/routes.rb
96
+ - db/migrate/20240213133517_create_rails_live_dashboard_entries.rb
97
+ - lib/generators/rails_live_dashboard/install_generator.rb
98
+ - lib/generators/templates/initializer.rb
99
+ - lib/rails_live_dashboard.rb
100
+ - lib/rails_live_dashboard/configuration.rb
101
+ - lib/rails_live_dashboard/context.rb
102
+ - lib/rails_live_dashboard/engine.rb
103
+ - lib/rails_live_dashboard/recorders/exception_recorder.rb
104
+ - lib/rails_live_dashboard/recorders/query_recorder.rb
105
+ - lib/rails_live_dashboard/recorders/request_recorder.rb
106
+ - lib/rails_live_dashboard/subscribers/action_controller_subscriber.rb
107
+ - lib/rails_live_dashboard/subscribers/active_record_subscriber.rb
108
+ - lib/rails_live_dashboard/version.rb
109
+ - lib/tasks/rails_live_dashboard_tasks.rake
110
+ homepage: https://github.com/andersondalmina/rails-live-dashboard
111
+ licenses:
112
+ - MIT
113
+ metadata:
114
+ homepage_uri: https://github.com/andersondalmina/rails-live-dashboard
115
+ source_code_uri: https://github.com/andersondalmina/rails-live-dashboard
116
+ changelog_uri: https://github.com/andersondalmina/rails-live-dashboard/blob/main/CHANGELOG.md
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubygems_version: 3.4.10
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: Realtime dashboard for Rails applications
136
+ test_files: []