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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +121 -0
  3. data/Rakefile +10 -0
  4. data/app/assets/javascripts/solid_cache_dashboard/alpine.js +5 -0
  5. data/app/assets/javascripts/solid_cache_dashboard/application.js +60 -0
  6. data/app/assets/stylesheets/solid_cache_dashboard/application.css +1468 -0
  7. data/app/assets/stylesheets/solid_cache_dashboard/tailwind.css +625 -0
  8. data/app/controllers/solid_cache_dashboard/appearance_controller.rb +9 -0
  9. data/app/controllers/solid_cache_dashboard/application_controller.rb +12 -0
  10. data/app/controllers/solid_cache_dashboard/cache_entries_controller.rb +37 -0
  11. data/app/controllers/solid_cache_dashboard/cache_events_controller.rb +9 -0
  12. data/app/controllers/solid_cache_dashboard/dashboard_controller.rb +69 -0
  13. data/app/controllers/solid_cache_dashboard/stats_controller.rb +19 -0
  14. data/app/helpers/solid_cache_dashboard/application_helper.rb +20 -0
  15. data/app/views/layouts/solid_cache_dashboard/application.html.erb +28 -0
  16. data/app/views/solid_cache_dashboard/application/_flash_messages.html.erb +10 -0
  17. data/app/views/solid_cache_dashboard/application/_footer.html.erb +12 -0
  18. data/app/views/solid_cache_dashboard/application/_navbar.html.erb +32 -0
  19. data/app/views/solid_cache_dashboard/cache_entries/index.html.erb +136 -0
  20. data/app/views/solid_cache_dashboard/cache_entries/show.html.erb +118 -0
  21. data/app/views/solid_cache_dashboard/cache_events/index.html.erb +152 -0
  22. data/app/views/solid_cache_dashboard/dashboard/index.html.erb +163 -0
  23. data/app/views/solid_cache_dashboard/stats/index.html.erb +302 -0
  24. data/config/routes.rb +17 -0
  25. data/lib/generators/solid_cache_dashboard/install/install_generator.rb +17 -0
  26. data/lib/generators/solid_cache_dashboard/install/templates/create_solid_cache_dashboard_events.rb +16 -0
  27. data/lib/solid_cache_dashboard/cache_entry.rb +18 -0
  28. data/lib/solid_cache_dashboard/cache_event.rb +22 -0
  29. data/lib/solid_cache_dashboard/configuration.rb +17 -0
  30. data/lib/solid_cache_dashboard/decorators/cache_entries_decorator.rb +27 -0
  31. data/lib/solid_cache_dashboard/decorators/cache_entry_decorator.rb +59 -0
  32. data/lib/solid_cache_dashboard/decorators/cache_event_decorator.rb +72 -0
  33. data/lib/solid_cache_dashboard/decorators/cache_events_decorator.rb +44 -0
  34. data/lib/solid_cache_dashboard/engine.rb +19 -0
  35. data/lib/solid_cache_dashboard/instrumentation.rb +58 -0
  36. data/lib/solid_cache_dashboard/models/cache_event.rb +51 -0
  37. data/lib/solid_cache_dashboard/version.rb +5 -0
  38. data/lib/solid_cache_dashboard.rb +39 -0
  39. data/package-lock.json +1040 -0
  40. data/package.json +16 -0
  41. 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,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidCacheDashboard
4
+ VERSION = "0.0.1"
5
+ 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