activeinsights 0.2.3 → 0.3.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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/active_insights/application_controller.rb +5 -1
  3. data/app/controllers/active_insights/jobs_controller.rb +13 -0
  4. data/app/controllers/active_insights/jobs_latencies_controller.rb +22 -0
  5. data/app/controllers/active_insights/jobs_p_values_controller.rb +33 -0
  6. data/app/controllers/active_insights/jpm_controller.rb +17 -0
  7. data/app/controllers/active_insights/requests_controller.rb +1 -1
  8. data/app/controllers/active_insights/requests_p_values_controller.rb +35 -0
  9. data/app/controllers/active_insights/rpm_controller.rb +1 -1
  10. data/app/helpers/active_insights/application_helper.rb +1 -1
  11. data/app/models/active_insights/job.rb +16 -0
  12. data/app/models/active_insights/record.rb +75 -0
  13. data/app/models/active_insights/request.rb +6 -70
  14. data/app/views/active_insights/jobs/index.html.erb +65 -0
  15. data/app/views/active_insights/jobs_latencies/index.html.erb +27 -0
  16. data/app/views/active_insights/{controller_p_values → jobs_p_values}/index.html.erb +9 -3
  17. data/app/views/active_insights/jpm/index.html.erb +26 -0
  18. data/app/views/active_insights/requests/index.html.erb +11 -7
  19. data/app/views/active_insights/{p_values → requests_p_values}/index.html.erb +9 -3
  20. data/app/views/active_insights/rpm/index.html.erb +1 -1
  21. data/app/views/layouts/active_insights/application.html.erb +7 -0
  22. data/config/routes.rb +25 -6
  23. data/db/migrate/{20240111225806_active_insights_request.rb → 20240111225806_create_active_insights_tables.rb} +19 -1
  24. data/lib/active_insights/engine.rb +11 -10
  25. data/lib/active_insights/seeders/jobs.rb +81 -0
  26. data/lib/active_insights/{seeder.rb → seeders/requests.rb} +3 -1
  27. data/lib/active_insights/version.rb +1 -1
  28. metadata +16 -10
  29. data/app/controllers/active_insights/controller_p_values_controller.rb +0 -24
  30. data/app/controllers/active_insights/p_values_controller.rb +0 -21
  31. data/vendor/javascript/chart.js.js +0 -10
  32. data/vendor/javascript/chartkick.js +0 -2
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class ActiveInsightsRequest < ActiveRecord::Migration[7.1]
3
+ class CreateActiveInsightsTables < ActiveRecord::Migration[7.1]
4
4
  def change
5
5
  create_table :active_insights_requests, if_not_exists: true do |t|
6
6
  t.string :controller
@@ -28,5 +28,23 @@ class ActiveInsightsRequest < ActiveRecord::Migration[7.1]
28
28
 
29
29
  t.timestamps
30
30
  end
31
+
32
+ create_table :active_insights_jobs, if_not_exists: true do |t|
33
+ t.string :job
34
+ t.string :queue
35
+ t.float :db_runtime
36
+ t.datetime :scheduled_at
37
+ t.datetime :started_at
38
+ t.datetime :finished_at
39
+ t.string :uuid
40
+ t.float :duration
41
+ t.float :queue_time
42
+
43
+ t.index :started_at
44
+ t.index %i(started_at duration)
45
+ t.index %i(started_at duration queue_time)
46
+
47
+ t.timestamps
48
+ end
31
49
  end
32
50
  end
@@ -24,7 +24,15 @@ module ActiveInsights
24
24
  Engine.root.join("config/initializers/importmap.rb")
25
25
  end
26
26
 
27
- initializer "active_insights.subscriber" do |_app|
27
+ initializer "active_insights.job_subscriber" do
28
+ ActiveSupport::Notifications.
29
+ subscribe("perform.active_job") do |_name,
30
+ started, finished, unique_id, payload|
31
+ ActiveInsights::Job.setup(started, finished, unique_id, payload)
32
+ end
33
+ end
34
+
35
+ initializer "active_insights.request_subscriber" do
28
36
  ActiveSupport::Notifications.
29
37
  subscribe("process_action.action_controller") do |_name,
30
38
  started, finished, unique_id, payload|
@@ -33,15 +41,8 @@ module ActiveInsights
33
41
 
34
42
  Thread.new do
35
43
  ActiveRecord::Base.connection_pool.with_connection do
36
- ActiveInsights::Request.create!(
37
- started_at: started, finished_at: finished, uuid: unique_id,
38
- duration: (finished - started) * 1000.0,
39
- controller: payload[:controller],
40
- action: payload[:action], format: payload[:format],
41
- http_method: payload[:method], status: payload[:status],
42
- view_runtime: payload[:view_runtime],
43
- db_runtime: payload[:db_runtime]
44
- )
44
+ ActiveInsights::Request.
45
+ setup(started, finished, unique_id, payload)
45
46
  end
46
47
  end
47
48
  end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nocov:
4
+ require "rubystats"
5
+
6
+ module ActiveInsights
7
+ class JobSeeder
8
+ def initialize(date, rpm, p50, p95, p99)
9
+ @date = date
10
+ @rpm = rpm
11
+ @p50 = p50
12
+ @p95 = p95
13
+ @p99 = p99
14
+ end
15
+
16
+ def seed
17
+ ActiveInsights::Job.insert_all(seed_attributes)
18
+ end
19
+
20
+ def find_percentile(sorted_data, percentile)
21
+ sorted_data[(percentile * sorted_data.length).ceil - 1]
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :date, :rpm, :p50, :p95, :p99
27
+
28
+ def seed_attributes
29
+ 24.times.flat_map do |hour|
30
+ 60.times.flat_map do |min|
31
+ processing_times.map { |duration| attributes(hour, min, duration) }
32
+ end
33
+ end
34
+ end
35
+
36
+ def processing_times
37
+ Array.new(rpm) do
38
+ p50 + (beta_distribution.rng * (p95 - p50))
39
+ end.select { |time| time <= p99 }
40
+ end
41
+
42
+ def beta_distribution
43
+ @beta_distribution ||= Rubystats::BetaDistribution.new(2, 5)
44
+ end
45
+
46
+ def sample_job
47
+ %w(UserNotificationSenderJob DailyReportGeneratorJob DataCleanupWorkerJob
48
+ InvoiceProcessingJob EmailDigestSenderJob DatabaseBackupJob
49
+ OrderFulfillmentJob ProductCatalogUpdateJob MonthlyBillingJob
50
+ SubscriptionRenewalCheckerJob SocialMediaPostSchedulerJob
51
+ CustomerDataImporterJob SearchIndexRebuilderJob EventReminderSenderJob
52
+ FileExportJob).sample
53
+ end
54
+
55
+ def attributes(hour, min, duration)
56
+ started_at = date.dup.to_time.change(hour:, min:)
57
+ job = sample_job
58
+ queue = sample_queue(job)
59
+
60
+ default_attributes.merge(duration:, started_at:, job:, queue:,
61
+ scheduled_at: started_at - sample_latency,
62
+ finished_at: started_at + (duration / 1000.0))
63
+ end
64
+
65
+ def default_attributes
66
+ { created_at: Time.current, updated_at: Time.current,
67
+ uuid: SecureRandom.uuid }
68
+ end
69
+
70
+ def sample_latency
71
+ (1..500).to_a.sample.seconds
72
+ end
73
+
74
+ def sample_queue(job)
75
+ @sample_queues ||= {}
76
+ @sample_queues[job] ||=
77
+ %w(default mailers high_priority low_priority).sample
78
+ end
79
+ end
80
+ end
81
+ # :nocov:
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :nocov:
3
4
  require "rubystats"
4
5
 
5
6
  module ActiveInsights
6
- class Seeder
7
+ class RequestSeeder
7
8
  def initialize(date, rpm, p50, p95, p99)
8
9
  @date = date
9
10
  @rpm = rpm
@@ -64,3 +65,4 @@ module ActiveInsights
64
65
  end
65
66
  end
66
67
  end
68
+ # :nocov:
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveInsights
4
- VERSION = "0.2.3"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activeinsights
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Pezza
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-18 00:00:00.000000000 Z
11
+ date: 2024-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chartkick
@@ -62,29 +62,35 @@ files:
62
62
  - README.md
63
63
  - Rakefile
64
64
  - app/controllers/active_insights/application_controller.rb
65
- - app/controllers/active_insights/controller_p_values_controller.rb
66
- - app/controllers/active_insights/p_values_controller.rb
65
+ - app/controllers/active_insights/jobs_controller.rb
66
+ - app/controllers/active_insights/jobs_latencies_controller.rb
67
+ - app/controllers/active_insights/jobs_p_values_controller.rb
68
+ - app/controllers/active_insights/jpm_controller.rb
67
69
  - app/controllers/active_insights/requests_controller.rb
70
+ - app/controllers/active_insights/requests_p_values_controller.rb
68
71
  - app/controllers/active_insights/rpm_controller.rb
69
72
  - app/helpers/active_insights/application_helper.rb
73
+ - app/models/active_insights/job.rb
70
74
  - app/models/active_insights/record.rb
71
75
  - app/models/active_insights/request.rb
72
- - app/views/active_insights/controller_p_values/index.html.erb
73
- - app/views/active_insights/p_values/index.html.erb
76
+ - app/views/active_insights/jobs/index.html.erb
77
+ - app/views/active_insights/jobs_latencies/index.html.erb
78
+ - app/views/active_insights/jobs_p_values/index.html.erb
79
+ - app/views/active_insights/jpm/index.html.erb
74
80
  - app/views/active_insights/requests/index.html.erb
81
+ - app/views/active_insights/requests_p_values/index.html.erb
75
82
  - app/views/active_insights/rpm/index.html.erb
76
83
  - app/views/layouts/active_insights/application.html.erb
77
84
  - config/initializers/importmap.rb
78
85
  - config/routes.rb
79
- - db/migrate/20240111225806_active_insights_request.rb
86
+ - db/migrate/20240111225806_create_active_insights_tables.rb
80
87
  - lib/active_insights.rb
81
88
  - lib/active_insights/engine.rb
82
- - lib/active_insights/seeder.rb
89
+ - lib/active_insights/seeders/jobs.rb
90
+ - lib/active_insights/seeders/requests.rb
83
91
  - lib/active_insights/version.rb
84
92
  - lib/activeinsights.rb
85
93
  - lib/generators/active_insights/install/install_generator.rb
86
- - vendor/javascript/chart.js.js
87
- - vendor/javascript/chartkick.js
88
94
  homepage: https://github.com/npezza93/activeinsights
89
95
  licenses:
90
96
  - MIT
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveInsights
4
- class ControllerPValuesController < ApplicationController
5
- def index
6
- @p50 = minutes.map{ |minute| [minute.pretty_started_at, minute.p50] }
7
- @p95 = minutes.map{ |minute| [minute.pretty_started_at, minute.p95] }
8
- @p99 = minutes.map{ |minute| [minute.pretty_started_at, minute.p99] }
9
- end
10
-
11
- def redirection
12
- redirect_to controller_p_values_path(params[:date],
13
- params[:formatted_controller])
14
- end
15
-
16
- private
17
-
18
- def minutes
19
- @minutes ||=
20
- base_scope.where(formatted_controller: params[:formatted_controller]).
21
- minute_by_minute.with_durations.select_started_at
22
- end
23
- end
24
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveInsights
4
- class PValuesController < ApplicationController
5
- def index
6
- @p50 = minutes.map{ |minute| [minute.pretty_started_at, minute.p50] }
7
- @p95 = minutes.map{ |minute| [minute.pretty_started_at, minute.p95] }
8
- @p99 = minutes.map{ |minute| [minute.pretty_started_at, minute.p99] }
9
- end
10
-
11
- def redirection
12
- redirect_to p_values_path(params[:date])
13
- end
14
-
15
- private
16
-
17
- def minutes
18
- @minutes ||= base_scope.minute_by_minute.with_durations.select_started_at
19
- end
20
- end
21
- end