inner_performance 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 (30) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +80 -0
  3. data/Rakefile +8 -0
  4. data/app/assets/config/inner_performance_manifest.js +1 -0
  5. data/app/assets/stylesheets/inner_performance/application.css +15 -0
  6. data/app/controllers/inner_performance/application_controller.rb +4 -0
  7. data/app/controllers/inner_performance/dashboard_controller.rb +17 -0
  8. data/app/controllers/inner_performance/events_controller.rb +12 -0
  9. data/app/helpers/inner_performance/application_helper.rb +15 -0
  10. data/app/jobs/inner_performance/application_job.rb +4 -0
  11. data/app/jobs/inner_performance/cleanup_job.rb +7 -0
  12. data/app/jobs/inner_performance/save_event_job.rb +15 -0
  13. data/app/mailers/inner_performance/application_mailer.rb +6 -0
  14. data/app/models/inner_performance/application_record.rb +5 -0
  15. data/app/models/inner_performance/event.rb +13 -0
  16. data/app/models/inner_performance/events/perform_active_job.rb +6 -0
  17. data/app/models/inner_performance/events/process_action_action_controller.rb +6 -0
  18. data/app/views/inner_performance/dashboard/index.html.erb +54 -0
  19. data/app/views/inner_performance/events/_event.html.erb +8 -0
  20. data/app/views/inner_performance/events/index.html.erb +30 -0
  21. data/app/views/layouts/inner_performance/application.html.erb +33 -0
  22. data/config/routes.rb +7 -0
  23. data/db/migrate/20241123121600_create_inner_performance_events.rb +13 -0
  24. data/db/migrate/20241124111458_add_type_to_inner_performance_events.rb +5 -0
  25. data/lib/inner_performance/configuration.rb +21 -0
  26. data/lib/inner_performance/engine.rb +13 -0
  27. data/lib/inner_performance/version.rb +3 -0
  28. data/lib/inner_performance.rb +55 -0
  29. data/lib/tasks/inner_performance_tasks.rake +4 -0
  30. metadata +143 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5b0f7620adf9d09e4c9a58a007fdf054d5a89760ad099e8d699bc3deff12f00d
4
+ data.tar.gz: 271e25fe6de8f021a05ac78ac295cbcf3b8c69ebde3b798151526143776eed86
5
+ SHA512:
6
+ metadata.gz: 1cdcbbef0725de7a886b2c10ad2a392d0bfe77c9591bdebc4d26219bba832caf25694a7a79d4ef9476748db9e576e48214db5edf896e0688906e6f36bedb4e2d
7
+ data.tar.gz: 3321bac2c9273787a3b3d0a3c6ed84e8a0a702be9cb180fada9bd5188eca7412ca5e2275702e20b043da06699a945ea8da82cc296be8145521bc4bb036b1b212
data/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # InnerPerformance
2
+ Database-backed modest performance monitoring tool for your Rails app.
3
+
4
+ <img width="1188" alt="image" src="https://github.com/user-attachments/assets/cb659c76-8139-4ee0-b683-d6acef227dc6">
5
+
6
+ ## Installation
7
+ Add `inner_performance` gem to your bundle
8
+
9
+ ```ruby
10
+ $ bundle add inner_performance
11
+ ```
12
+
13
+ Install migrations
14
+
15
+ ```ruby
16
+ $ rails inner_performance:install:migrations
17
+ $ rails db:migrate
18
+ ```
19
+
20
+ Mount UI in `routes.rb` (don't forget to protect it!)
21
+
22
+ ```ruby
23
+ mount InnerPerformance::Engine, at: '/inner_performance'
24
+ ```
25
+
26
+ ## Configuration
27
+
28
+ inner_performance comes with some good defaults but in order to customize
29
+ them, you have a following options available:
30
+
31
+ ```ruby
32
+ InnerPerformance.configure do |config|
33
+ config.sample_rates = {
34
+ # 2% of all the requests will be stored and analyzed. I would
35
+ # recommend keeping it low because otherwise your database will
36
+ # get full of events quite fast. It will also probably impact
37
+ # your app's performance. As an example: In a Spree shop with
38
+ # approx. 170 requests per minute, keeping it at default 2%
39
+ # provides me more than enough data to analyze and locate the
40
+ # bottlenecks.
41
+ 'process_action.action_controller' => 2,
42
+
43
+ # 100% of all the jobs will be stored and analyzed.
44
+ 'perform.active_job' => 100
45
+ }
46
+
47
+ # For how long events should be stored. All the ones that exceeds
48
+ # this limit will be cleared out by InnerPerformance::CleanupJob.
49
+ config.events_retention = 1.week
50
+
51
+ # Used mostly by UI. Tells the UI what's the middle range when it
52
+ # comes to event duration. For the example below, all the durations
53
+ # between 0 and 200ms will be considered fast, all the ones between
54
+ # 200ms and 999ms will be considered medium and all above 999ms will
55
+ # be considered slow.
56
+ config.medium_duration_range = [200, 999]
57
+
58
+ # Rules for ignoring an event. There are two rules applied by default:
59
+ # * sample_rates - operates on configured sample rate and drops events
60
+ # which do not got lucky when drawing a random number
61
+ # * InnerPerformance job namespace - we don't want to save events for
62
+ # the job that saves the events because that leeds to infinite loop.
63
+ # Better not remove this rule as it will lead to stack overflow.
64
+ config.ignore_rules.push(
65
+ proc { |event| event.is_a?(ActiveSupport::Notifications::Event) }
66
+ )
67
+ end
68
+ ```
69
+
70
+ `InnerPerformance` will produce an infinite amount of event records so in order
71
+ to clean them up, you should periodically run
72
+ `InnerPerformance::CleanupJob.perform_later`.
73
+
74
+ # Alternatives
75
+
76
+ * [rails_performance](https://github.com/igorkasyanchuk/rails_performance) - much better but depends on Redis
77
+
78
+ ## License
79
+ The gem is available as open source under the terms of the
80
+ [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/inner_performance .css
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,4 @@
1
+ module InnerPerformance
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,17 @@
1
+ module InnerPerformance
2
+ class DashboardController < ApplicationController
3
+ def index
4
+ @q = InnerPerformance::Event.all.ransack(params[:q])
5
+ @q.sorts = "created_at desc" if @q.sorts.empty?
6
+ @recent_events = @q.result.limit(100)
7
+
8
+ @average_req_duration = InnerPerformance::Events::ProcessActionActionController.all.average(:duration)
9
+ @average_job_duration = InnerPerformance::Events::PerformActiveJob.average(:duration) || 0
10
+ @biggest_events = \
11
+ InnerPerformance::Event.select('SUM(duration) as duration, name, COUNT(*) as count, AVG(duration) as avg_duration')
12
+ .group(:name)
13
+ .order('duration DESC')
14
+ .limit(10)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,12 @@
1
+ module InnerPerformance
2
+ class EventsController < ApplicationController
3
+ include Pagy::Backend
4
+ include Pagy::Frontend
5
+
6
+ def index
7
+ @q = InnerPerformance::Event.all.ransack(params[:q])
8
+ @q.sorts = "created_at desc" if @q.sorts.empty?
9
+ @pagy, @events = pagy(@q.result)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ module InnerPerformance
2
+ module ApplicationHelper
3
+ # Based on https://stackoverflow.com/a/45428183/552936 and
4
+ # https://datadome.co/learning-center/how-to-reduce-server-response-time/
5
+ def row_class_from_duration(duration)
6
+ medium_duration_range = InnerPerformance.configuration.medium_duration_range
7
+
8
+ if duration.between?(medium_duration_range[0], medium_duration_range[1])
9
+ 'text-warning'
10
+ elsif duration >= medium_duration_range[1]
11
+ 'text-danger'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ module InnerPerformance
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module InnerPerformance
2
+ class CleanupJob < ApplicationJob
3
+ def perform
4
+ InnerPerformance::Event.where('created_at >= ?', InnerPerformance.configuration.events_retention)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ module InnerPerformance
2
+ class SaveEventJob < ApplicationJob
3
+ def perform(type:, created_at:, event:, name:, duration:, db_runtime:, properties: {})
4
+ InnerPerformance::Event.create(
5
+ type: type,
6
+ created_at: created_at,
7
+ event: event,
8
+ name: name,
9
+ duration: duration,
10
+ db_runtime: db_runtime,
11
+ properties: properties
12
+ )
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,6 @@
1
+ module InnerPerformance
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: "from@example.com"
4
+ layout "mailer"
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module InnerPerformance
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ module InnerPerformance
2
+ class Event < ApplicationRecord
3
+ serialize :properties, coder: JSON
4
+
5
+ def self.ransackable_attributes(auth_object = nil)
6
+ ["created_at", "db_runtime", "duration", "event", "format", "id", "name"]
7
+ end
8
+
9
+ def self.ransackable_associations(auth_object = nil)
10
+ []
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ module InnerPerformance
2
+ module Events
3
+ class PerformActiveJob < InnerPerformance::Event
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module InnerPerformance
2
+ module Events
3
+ class ProcessActionActionController < InnerPerformance::Event
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,54 @@
1
+ <div class="row mb-4">
2
+ <div class="col-auto">
3
+ <div class="card">
4
+ <div class="card-body">
5
+ <span class="card-subtitle d-block">Avg. request duration</span>
6
+ <span class="card-title h1 d-block mb-0"><%= number_to_human(@average_req_duration, units: { unit: 'ms' }) %></span>
7
+ </div>
8
+ </div>
9
+ </div>
10
+
11
+ <div class="col-auto">
12
+ <div class="card">
13
+ <div class="card-body">
14
+ <span class="card-subtitle d-block">Avg. job duration</span>
15
+ <span class="card-title h1 d-block mb-0"><%= number_to_human(@average_job_duration, units: { unit: 'ms' }) %></span>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ </div>
20
+
21
+ <h4>Most time consuming</h4>
22
+ <table class="table table-hover">
23
+ <thead>
24
+ <th>Name</th>
25
+ <th class="text-end">Count</th>
26
+ <th class="text-end">Avg. duration</th>
27
+ <th class="text-end">Total duration</th>
28
+ </thead>
29
+ <tbody>
30
+ <% @biggest_events.each do |event| %>
31
+ <tr>
32
+ <td><%= link_to event.name, events_path(q: { name_eq: event.name }) %></td>
33
+ <td class="text-end"><%= event.count %></td>
34
+ <td class="text-end <%= row_class_from_duration(event.avg_duration) %>"><%= number_to_human(event.avg_duration, units: { unit: 'ms' }) %></td>
35
+ <td class="text-end"><%= number_to_human(event.duration, units: { unit: 'ms' }) %></td>
36
+ </tr>
37
+ <% end %>
38
+ </tbody>
39
+ </table>
40
+
41
+ <h4 class="mt-4">Recent events</h4>
42
+ <table class="table table-hover">
43
+ <thead>
44
+ <th><%= sort_link @q, :name, hide_indicator: true %></th>
45
+ <th><%= sort_link @q, :duration, hide_indicator: true %></th>
46
+ <th><%= sort_link @q, :db_runtime, hide_indicator: true %></th>
47
+ <th class="text-end"><%= sort_link @q, :created_at, hide_indicator: true %></th>
48
+ </thead>
49
+ <tbody>
50
+ <% @recent_events.each do |event| %>
51
+ <%= render event.becomes(InnerPerformance::Event) %>
52
+ <% end %>
53
+ </tbody>
54
+ </table>
@@ -0,0 +1,8 @@
1
+ <tr>
2
+ <td><%= link_to event.name, events_path(q: { name_eq: event.name }) %></td>
3
+ <td class="<%= row_class_from_duration(event.duration) %>">
4
+ <%= number_to_human(event.duration, units: { unit: 'ms' }) %>
5
+ </td>
6
+ <td><%= number_to_human(event.db_runtime, units: { unit: 'ms' }) %></td>
7
+ <td class="text-end"><%= event.created_at %></td>
8
+ </tr>
@@ -0,0 +1,30 @@
1
+ <%= search_form_for @q, class: 'mb-4' do |f| %>
2
+ <div class="row align-items-end">
3
+ <div class="col-10">
4
+ <%= f.label :name_eq, class: 'form-label' %>
5
+ <%= f.select :name_eq, options_for_select(InnerPerformance::Event.all.pluck(:name).uniq, f.object.name_eq),
6
+ { include_blank: true },
7
+ { class: 'form-select' } %>
8
+ </div>
9
+
10
+ <div class="col-2 text-end">
11
+ <%= f.submit 'Filter', class: 'btn btn-primary' %>
12
+ </div>
13
+ </div>
14
+ <% end %>
15
+
16
+ <table class="table table-hover">
17
+ <thead>
18
+ <th><%= sort_link @q, :name, hide_indicator: true %></th>
19
+ <th><%= sort_link @q, :duration, hide_indicator: true %></th>
20
+ <th><%= sort_link @q, :db_runtime, hide_indicator: true %></th>
21
+ <th class="text-end"><%= sort_link @q, :created_at, hide_indicator: true %></th>
22
+ </thead>
23
+ <tbody>
24
+ <% @events.each do |event| %>
25
+ <%= render event.becomes(InnerPerformance::Event) %>
26
+ <% end %>
27
+ </tbody>
28
+ </table>
29
+
30
+ <%== pagy_nav(@pagy) if @pagy.pages > 1 %>
@@ -0,0 +1,33 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>☯️ Inner performance</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "inner_performance/application", media: "all" %>
9
+
10
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
11
+ </head>
12
+ <body>
13
+
14
+ <nav class="navbar navbar-expand-lg bg-body-tertiary">
15
+ <div class="container">
16
+ <a class="navbar-brand" href="<%= root_path %>">☯️ InnerPerformance</a>
17
+
18
+ <div class="ml-auto">
19
+ <ul class="navbar-nav me-auto mb-2 mb-lg-0">
20
+ <li class="nav-item">
21
+ <a class="nav-link" href="<%= events_path %>">Events</a>
22
+ </li>
23
+ </ul>
24
+ </div>
25
+ </div>
26
+ </nav>
27
+
28
+ <div class="container pt-4">
29
+ <%= yield %>
30
+ </div>
31
+
32
+ </body>
33
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,7 @@
1
+ InnerPerformance::Engine.routes.draw do
2
+ mount InnerPerformance::Engine, at: '/performance'
3
+
4
+ resources :events, only: [:index]
5
+
6
+ root to: "dashboard#index"
7
+ end
@@ -0,0 +1,13 @@
1
+ class CreateInnerPerformanceEvents < ActiveRecord::Migration[7.1]
2
+ def change
3
+ create_table :inner_performance_events, force: :cascade do |t|
4
+ t.string "event"
5
+ t.string "name"
6
+ t.decimal "duration"
7
+ t.decimal "db_runtime"
8
+ t.datetime "created_at", null: false
9
+ t.datetime "updated_at", null: false
10
+ t.text "properties", default: "{}"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ class AddTypeToInnerPerformanceEvents < ActiveRecord::Migration[8.0]
2
+ def change
3
+ add_column :inner_performance_events, :type, :string
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ module InnerPerformance
2
+ class Configuration
3
+ attr_accessor :sample_rates
4
+ attr_accessor :events_retention
5
+ attr_accessor :medium_duration_range
6
+ attr_accessor :ignore_rules
7
+
8
+ def initialize
9
+ @sample_rates = {
10
+ 'process_action.action_controller' => 2,
11
+ 'perform.active_job' => 100
12
+ }
13
+ @events_retention = 1.week
14
+ @medium_duration_range = [200, 999]
15
+ @ignore_rules = [
16
+ proc { |event| rand(100) <= InnerPerformance.configuration.sample_rates[event.name.to_s] },
17
+ proc { |event| (event.payload[:job]&.class&.name || '').exclude?('InnerPerformance') }
18
+ ]
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module InnerPerformance
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace InnerPerformance
4
+
5
+ config.generators do |g|
6
+ g.test_framework :rspec
7
+ end
8
+
9
+ initializer 'inner_performance.install' do
10
+ InnerPerformance.install!
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module InnerPerformance
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,55 @@
1
+ require "inner_performance/version"
2
+ require "inner_performance/engine"
3
+ require "inner_performance/configuration"
4
+
5
+ require "ransack"
6
+ require "pagy"
7
+
8
+ module InnerPerformance
9
+ class << self
10
+ def configuration
11
+ @configuration ||= Configuration.new
12
+ end
13
+
14
+ def configure
15
+ yield(configuration)
16
+ end
17
+
18
+ def install!
19
+ ActiveSupport::Notifications.subscribe "process_action.action_controller" do |event|
20
+ if save_event?(event)
21
+ InnerPerformance::SaveEventJob.perform_later(
22
+ type: InnerPerformance::Events::ProcessActionActionController.name,
23
+ created_at: event.payload[:started],
24
+ event: event.name,
25
+ name: "#{event.payload[:controller]}##{event.payload[:action]}",
26
+ duration: event.duration,
27
+ db_runtime: event.payload[:db_runtime],
28
+ properties: {
29
+ view_runtime: event.payload[:view_runtime]
30
+ }
31
+ )
32
+ end
33
+ end
34
+
35
+ ActiveSupport::Notifications.subscribe "perform.active_job" do |event|
36
+ if save_event?(event)
37
+ InnerPerformance::SaveEventJob.perform_later(
38
+ type: InnerPerformance::Events::PerformActiveJob.name,
39
+ created_at: event.payload[:started],
40
+ event: event.name,
41
+ name: event.payload[:job].class.name,
42
+ duration: event.duration,
43
+ db_runtime: event.payload[:db_runtime]
44
+ )
45
+ end
46
+ end
47
+ end
48
+
49
+ def save_event?(event)
50
+ InnerPerformance.configuration.ignore_rules.each_with_object([]) do |rule, arr|
51
+ arr << rule.call(event)
52
+ end.all? { |r| r == true }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :inner_performance do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inner_performance
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - mbajur
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-11-24 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.5
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.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: activejob
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 7.1.5
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 7.1.5
41
+ - !ruby/object:Gem::Dependency
42
+ name: ransack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 4.2.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 4.2.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: pagy
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 9.3.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 9.3.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Database-backed modest performance monitoring tool for your Rails app.
84
+ email:
85
+ - mbajur@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - README.md
91
+ - Rakefile
92
+ - app/assets/config/inner_performance_manifest.js
93
+ - app/assets/stylesheets/inner_performance/application.css
94
+ - app/controllers/inner_performance/application_controller.rb
95
+ - app/controllers/inner_performance/dashboard_controller.rb
96
+ - app/controllers/inner_performance/events_controller.rb
97
+ - app/helpers/inner_performance/application_helper.rb
98
+ - app/jobs/inner_performance/application_job.rb
99
+ - app/jobs/inner_performance/cleanup_job.rb
100
+ - app/jobs/inner_performance/save_event_job.rb
101
+ - app/mailers/inner_performance/application_mailer.rb
102
+ - app/models/inner_performance/application_record.rb
103
+ - app/models/inner_performance/event.rb
104
+ - app/models/inner_performance/events/perform_active_job.rb
105
+ - app/models/inner_performance/events/process_action_action_controller.rb
106
+ - app/views/inner_performance/dashboard/index.html.erb
107
+ - app/views/inner_performance/events/_event.html.erb
108
+ - app/views/inner_performance/events/index.html.erb
109
+ - app/views/layouts/inner_performance/application.html.erb
110
+ - config/routes.rb
111
+ - db/migrate/20241123121600_create_inner_performance_events.rb
112
+ - db/migrate/20241124111458_add_type_to_inner_performance_events.rb
113
+ - lib/inner_performance.rb
114
+ - lib/inner_performance/configuration.rb
115
+ - lib/inner_performance/engine.rb
116
+ - lib/inner_performance/version.rb
117
+ - lib/tasks/inner_performance_tasks.rake
118
+ homepage: https://github.com/mbajur
119
+ licenses: []
120
+ metadata:
121
+ homepage_uri: https://github.com/mbajur
122
+ source_code_uri: https://github.com/mbajur/inner_performance
123
+ changelog_uri: https://github.com/mbajur/inner_performance
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubygems_version: 3.5.23
140
+ signing_key:
141
+ specification_version: 4
142
+ summary: Database-backed modest performance monitoring tool for your Rails app.
143
+ test_files: []