solid_cache_dashboard 0.0.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.
- checksums.yaml +7 -0
- data/README.md +121 -0
- data/Rakefile +10 -0
- data/app/assets/javascripts/solid_cache_dashboard/alpine.js +5 -0
- data/app/assets/javascripts/solid_cache_dashboard/application.js +60 -0
- data/app/assets/stylesheets/solid_cache_dashboard/application.css +1468 -0
- data/app/assets/stylesheets/solid_cache_dashboard/tailwind.css +625 -0
- data/app/controllers/solid_cache_dashboard/appearance_controller.rb +9 -0
- data/app/controllers/solid_cache_dashboard/application_controller.rb +12 -0
- data/app/controllers/solid_cache_dashboard/cache_entries_controller.rb +37 -0
- data/app/controllers/solid_cache_dashboard/cache_events_controller.rb +9 -0
- data/app/controllers/solid_cache_dashboard/dashboard_controller.rb +69 -0
- data/app/controllers/solid_cache_dashboard/stats_controller.rb +19 -0
- data/app/helpers/solid_cache_dashboard/application_helper.rb +20 -0
- data/app/views/layouts/solid_cache_dashboard/application.html.erb +28 -0
- data/app/views/solid_cache_dashboard/application/_flash_messages.html.erb +10 -0
- data/app/views/solid_cache_dashboard/application/_footer.html.erb +12 -0
- data/app/views/solid_cache_dashboard/application/_navbar.html.erb +32 -0
- data/app/views/solid_cache_dashboard/cache_entries/index.html.erb +136 -0
- data/app/views/solid_cache_dashboard/cache_entries/show.html.erb +118 -0
- data/app/views/solid_cache_dashboard/cache_events/index.html.erb +152 -0
- data/app/views/solid_cache_dashboard/dashboard/index.html.erb +163 -0
- data/app/views/solid_cache_dashboard/stats/index.html.erb +302 -0
- data/config/routes.rb +17 -0
- data/lib/generators/solid_cache_dashboard/install/install_generator.rb +17 -0
- data/lib/generators/solid_cache_dashboard/install/templates/create_solid_cache_dashboard_events.rb +16 -0
- data/lib/solid_cache_dashboard/cache_entry.rb +18 -0
- data/lib/solid_cache_dashboard/cache_event.rb +22 -0
- data/lib/solid_cache_dashboard/configuration.rb +17 -0
- data/lib/solid_cache_dashboard/decorators/cache_entries_decorator.rb +27 -0
- data/lib/solid_cache_dashboard/decorators/cache_entry_decorator.rb +59 -0
- data/lib/solid_cache_dashboard/decorators/cache_event_decorator.rb +72 -0
- data/lib/solid_cache_dashboard/decorators/cache_events_decorator.rb +44 -0
- data/lib/solid_cache_dashboard/engine.rb +19 -0
- data/lib/solid_cache_dashboard/instrumentation.rb +58 -0
- data/lib/solid_cache_dashboard/models/cache_event.rb +51 -0
- data/lib/solid_cache_dashboard/version.rb +5 -0
- data/lib/solid_cache_dashboard.rb +39 -0
- data/package-lock.json +1040 -0
- data/package.json +16 -0
- metadata +125 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
module SolidCacheDashboard
|
2
|
+
module Decorators
|
3
|
+
class CacheEventDecorator
|
4
|
+
def initialize(event)
|
5
|
+
@event = event
|
6
|
+
end
|
7
|
+
|
8
|
+
def id
|
9
|
+
@event.id
|
10
|
+
end
|
11
|
+
|
12
|
+
def event_type
|
13
|
+
@event.event_type
|
14
|
+
end
|
15
|
+
|
16
|
+
def key_hash
|
17
|
+
@event.key_hash
|
18
|
+
end
|
19
|
+
|
20
|
+
def key_string
|
21
|
+
@event.key_string || @event.key_hash.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def byte_size
|
25
|
+
@event.byte_size
|
26
|
+
end
|
27
|
+
|
28
|
+
def human_byte_size
|
29
|
+
return nil unless @event.byte_size
|
30
|
+
ActiveSupport::NumberHelper.number_to_human_size(@event.byte_size)
|
31
|
+
end
|
32
|
+
|
33
|
+
def duration
|
34
|
+
@event.duration
|
35
|
+
end
|
36
|
+
|
37
|
+
def human_duration
|
38
|
+
return nil unless @event.duration
|
39
|
+
"#{(@event.duration * 1000).round(2)} ms"
|
40
|
+
end
|
41
|
+
|
42
|
+
def created_at
|
43
|
+
@event.created_at
|
44
|
+
end
|
45
|
+
|
46
|
+
def color
|
47
|
+
@event.color
|
48
|
+
end
|
49
|
+
|
50
|
+
def created_at_ago
|
51
|
+
time_ago_in_words(created_at)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def time_ago_in_words(time)
|
57
|
+
distance_in_seconds = (Time.now - time).round
|
58
|
+
|
59
|
+
case distance_in_seconds
|
60
|
+
when 0..59
|
61
|
+
"#{distance_in_seconds} seconds ago"
|
62
|
+
when 60..3599
|
63
|
+
"#{(distance_in_seconds / 60).round} minutes ago"
|
64
|
+
when 3600..86399
|
65
|
+
"#{(distance_in_seconds / 3600).round} hours ago"
|
66
|
+
else
|
67
|
+
"#{(distance_in_seconds / 86400).round} days ago"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module SolidCacheDashboard
|
2
|
+
module Decorators
|
3
|
+
class CacheEventsDecorator
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
delegate :current_page, :total_pages, :limit_value, :total_count, :offset_value, to: :@events
|
7
|
+
|
8
|
+
def initialize(events)
|
9
|
+
@events = events
|
10
|
+
end
|
11
|
+
|
12
|
+
def each(&block)
|
13
|
+
@events.each do |event|
|
14
|
+
block.call(SolidCacheDashboard.decorate(event))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def hit_count
|
19
|
+
@hit_count ||= @events.hits.count
|
20
|
+
end
|
21
|
+
|
22
|
+
def miss_count
|
23
|
+
@miss_count ||= @events.misses.count
|
24
|
+
end
|
25
|
+
|
26
|
+
def write_count
|
27
|
+
@write_count ||= @events.writes.count
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete_count
|
31
|
+
@delete_count ||= @events.deletes.count
|
32
|
+
end
|
33
|
+
|
34
|
+
def hit_ratio
|
35
|
+
return 0 if hit_count + miss_count == 0
|
36
|
+
hit_count.to_f / (hit_count + miss_count)
|
37
|
+
end
|
38
|
+
|
39
|
+
def hit_percentage
|
40
|
+
"#{(hit_ratio * 100).round(2)}%"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SolidCacheDashboard
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
isolate_namespace SolidCacheDashboard
|
4
|
+
|
5
|
+
initializer "solid_cache_dashboard.assets.precompile" do |app|
|
6
|
+
app.config.assets.precompile += %w[
|
7
|
+
solid_cache_dashboard/alpine.js
|
8
|
+
solid_cache_dashboard/application.js
|
9
|
+
solid_cache_dashboard/application.css
|
10
|
+
]
|
11
|
+
end
|
12
|
+
|
13
|
+
initializer "solid_cache_dashboard.instrumentation" do
|
14
|
+
config.after_initialize do
|
15
|
+
SolidCacheDashboard::Instrumentation.install
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/notifications"
|
4
|
+
|
5
|
+
module SolidCacheDashboard
|
6
|
+
module Instrumentation
|
7
|
+
def self.install
|
8
|
+
ActiveSupport::Notifications.subscribe("cache_read.active_support") do |*args|
|
9
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
10
|
+
key_hash = event.payload[:key].hash
|
11
|
+
key_string = event.payload[:key].to_s
|
12
|
+
hit = event.payload[:hit]
|
13
|
+
|
14
|
+
SolidCacheDashboard::CacheEvent.create!(
|
15
|
+
event_type: hit ? SolidCacheDashboard::CacheEvent::HIT : SolidCacheDashboard::CacheEvent::MISS,
|
16
|
+
key_hash: key_hash,
|
17
|
+
key_string: key_string.truncate(100),
|
18
|
+
duration: event.duration / 1000.0, # Convert from ms to seconds
|
19
|
+
created_at: Time.current
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
ActiveSupport::Notifications.subscribe("cache_write.active_support") do |*args|
|
24
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
25
|
+
key_hash = event.payload[:key].hash
|
26
|
+
key_string = event.payload[:key].to_s
|
27
|
+
|
28
|
+
entry_size = nil
|
29
|
+
if event.payload[:entry]
|
30
|
+
entry_size = event.payload[:entry].bytesize
|
31
|
+
end
|
32
|
+
|
33
|
+
SolidCacheDashboard::CacheEvent.create!(
|
34
|
+
event_type: SolidCacheDashboard::CacheEvent::WRITE,
|
35
|
+
key_hash: key_hash,
|
36
|
+
key_string: key_string.truncate(100),
|
37
|
+
byte_size: entry_size,
|
38
|
+
duration: event.duration / 1000.0, # Convert from ms to seconds
|
39
|
+
created_at: Time.current
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
ActiveSupport::Notifications.subscribe("cache_delete.active_support") do |*args|
|
44
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
45
|
+
key_hash = event.payload[:key].hash
|
46
|
+
key_string = event.payload[:key].to_s
|
47
|
+
|
48
|
+
SolidCacheDashboard::CacheEvent.create!(
|
49
|
+
event_type: SolidCacheDashboard::CacheEvent::DELETE,
|
50
|
+
key_hash: key_hash,
|
51
|
+
key_string: key_string.truncate(100),
|
52
|
+
duration: event.duration / 1000.0, # Convert from ms to seconds
|
53
|
+
created_at: Time.current
|
54
|
+
)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module SolidCacheDashboard
|
2
|
+
class CacheEvent < ActiveRecord::Base
|
3
|
+
# Types of cache events
|
4
|
+
HIT = :hit
|
5
|
+
MISS = :miss
|
6
|
+
WRITE = :write
|
7
|
+
DELETE = :delete
|
8
|
+
|
9
|
+
EVENT_TYPES = [HIT, MISS, WRITE, DELETE]
|
10
|
+
|
11
|
+
EVENT_COLORS = {
|
12
|
+
HIT => "green",
|
13
|
+
MISS => "amber",
|
14
|
+
WRITE => "sky",
|
15
|
+
DELETE => "red"
|
16
|
+
}
|
17
|
+
|
18
|
+
def self.event_color(event_type)
|
19
|
+
EVENT_COLORS[event_type] || "zinc"
|
20
|
+
end
|
21
|
+
|
22
|
+
self.table_name = 'solid_cache_dashboard_events'
|
23
|
+
|
24
|
+
scope :hits, -> { where(event_type: SolidCacheDashboard::CacheEvent::HIT) }
|
25
|
+
scope :misses, -> { where(event_type: SolidCacheDashboard::CacheEvent::MISS) }
|
26
|
+
scope :writes, -> { where(event_type: SolidCacheDashboard::CacheEvent::WRITE) }
|
27
|
+
scope :deletes, -> { where(event_type: SolidCacheDashboard::CacheEvent::DELETE) }
|
28
|
+
|
29
|
+
scope :recent, -> { order(created_at: :desc) }
|
30
|
+
|
31
|
+
def hit?
|
32
|
+
event_type.to_sym == SolidCacheDashboard::CacheEvent::HIT
|
33
|
+
end
|
34
|
+
|
35
|
+
def miss?
|
36
|
+
event_type.to_sym == SolidCacheDashboard::CacheEvent::MISS
|
37
|
+
end
|
38
|
+
|
39
|
+
def write?
|
40
|
+
event_type.to_sym == SolidCacheDashboard::CacheEvent::WRITE
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete?
|
44
|
+
event_type.to_sym == SolidCacheDashboard::CacheEvent::DELETE
|
45
|
+
end
|
46
|
+
|
47
|
+
def color
|
48
|
+
SolidCacheDashboard::CacheEvent.event_color(event_type.to_sym)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails"
|
4
|
+
require "groupdate"
|
5
|
+
require "chartkick"
|
6
|
+
require_relative "solid_cache_dashboard/version"
|
7
|
+
require_relative "solid_cache_dashboard/configuration"
|
8
|
+
require_relative "solid_cache_dashboard/engine"
|
9
|
+
require_relative "solid_cache_dashboard/cache_entry"
|
10
|
+
# require_relative "solid_cache_dashboard/cache_event"
|
11
|
+
require_relative "solid_cache_dashboard/instrumentation"
|
12
|
+
require_relative "solid_cache_dashboard/models/cache_event"
|
13
|
+
require_relative "solid_cache_dashboard/decorators/cache_entry_decorator"
|
14
|
+
require_relative "solid_cache_dashboard/decorators/cache_entries_decorator"
|
15
|
+
require_relative "solid_cache_dashboard/decorators/cache_event_decorator"
|
16
|
+
require_relative "solid_cache_dashboard/decorators/cache_events_decorator"
|
17
|
+
|
18
|
+
module SolidCacheDashboard
|
19
|
+
class Error < StandardError; end
|
20
|
+
|
21
|
+
def self.cache_keys
|
22
|
+
SolidCache::Entry.pluck(:key_hash).uniq
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.decorate(object)
|
26
|
+
case object
|
27
|
+
when SolidCache::Entry
|
28
|
+
Decorators::CacheEntryDecorator.new(object)
|
29
|
+
when SolidCache::Entry.const_get(:ActiveRecord_Relation)
|
30
|
+
Decorators::CacheEntriesDecorator.new(object)
|
31
|
+
when SolidCacheDashboard::CacheEvent
|
32
|
+
Decorators::CacheEventDecorator.new(object)
|
33
|
+
when SolidCacheDashboard::CacheEvent.const_get(:ActiveRecord_Relation)
|
34
|
+
Decorators::CacheEventsDecorator.new(object)
|
35
|
+
else
|
36
|
+
raise Error, "Cannot decorate #{object.class}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|