gc_reporter 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c222c825b6a36d78de4bb5c0685ac53caaaaef3f55ead344ff1548a60b4cf941
4
+ data.tar.gz: dcaee860d83bb29c4eaf1a80e575e9de265f16444a2676b57b20c0998be28048
5
+ SHA512:
6
+ metadata.gz: 443044d4c0ddb10027b0b41941d72acad7e2489a78c652a4194743ff00598376b157263caccef1943cb8ef1704939556264351d99647fd6d4169fb148065e3bf
7
+ data.tar.gz: c670a8606e92d7bc64d01f93e63e06bd4f42322e65097c0df55b6ed8666e5292a5b7e46af3864b8780995cd1bf951ee9f23ea2cdb4a5cf8b66ffa54052ffc558
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # GC Reporter
2
+
3
+ A simple Rails extension to collect and report Garbage Collection (`GC.stat`) and `ObjectSpace` statistics from your Ruby applications to a central monitoring application via Action Cable.
4
+
5
+ It is designed to be lightweight and work in various Ruby process types:
6
+ * Rails servers (Puma, Unicorn, etc.)
7
+ * Sidekiq workers
8
+ * Rake tasks
9
+
10
+ ## Receiving Application Setup
11
+
12
+ Before using this gem, you need a Rails application with an Action Cable channel ready to receive the data.
13
+
14
+ 1. **Generate a channel:**
15
+ ```bash
16
+ rails g channel GcStats
17
+ ```
18
+
19
+ 2. **Implement the channel:** The channel needs to define a `report` action, which is the remote procedure call (RPC) endpoint this gem uses.
20
+
21
+ ```ruby
22
+ # app/channels/gc_stats_channel.rb
23
+ class GcStatsChannel < ApplicationCable::Channel
24
+ def subscribed
25
+ stream_from "gc_stats_channel"
26
+ end
27
+
28
+ def unsubscribed
29
+ # Any cleanup needed when a client disconnects
30
+ end
31
+
32
+ # This is the action called by the gem's client.
33
+ def report(data)
34
+ # data is the payload sent from the gc_reporter gem.
35
+ # Process it here: log it, save to a DB, or broadcast to a live dashboard.
36
+ Rails.logger.info "Received GC Stats from #{data['source']} (PID: #{data['process_id']})"
37
+
38
+ # Example: Broadcast to a UI dashboard
39
+ ActionCable.server.broadcast("live_dashboard_channel", data)
40
+ end
41
+ end
42
+ ```
43
+
44
+ ## Installation
45
+
46
+ Add `gc_reporter` to your application's Gemfile.
47
+
48
+ ```ruby
49
+ # Gemfile
50
+ gem 'gc_reporter', git: '[https://github.com/example/gc_reporter](https://github.com/example/gc_reporter)' # Or from RubyGems when published
@@ -0,0 +1,31 @@
1
+ require_relative "lib/gc_reporter/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "gc_reporter"
5
+ spec.version = GcReporter::VERSION
6
+ spec.authors = ["Gemini AI"]
7
+ spec.email = ["ai@google.com"]
8
+
9
+ spec.summary = "Reports GC stats over Action Cable."
10
+ spec.description = "A Rails extension to collect and report GC.stat and ObjectSpace counts from Rails, Sidekiq, and Rake tasks to a central Action Cable endpoint."
11
+ spec.homepage = "https://github.com/codepawpaw/gc_reporter"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = ">= 2.7.0"
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = spec.homepage
17
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/CHANGELOG.md"
18
+
19
+ # Find all files tracked by git, excluding the spec/test directory.
20
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
21
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
22
+ end
23
+ spec.bindir = "exe"
24
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
25
+ spec.require_paths = ["lib"]
26
+
27
+ # Gem Dependencies
28
+ #spec.add_dependency "actioncable-client-ruby", "~> 0.4"
29
+ spec.add_dependency 'action_cable_client', '~> 3.1'
30
+ spec.add_dependency "railties", ">= 5.0.0"
31
+ end
@@ -0,0 +1,13 @@
1
+ module GcReporter
2
+ class Configuration
3
+ attr_accessor :url, :channel, :interval, :source, :verbose
4
+
5
+ def initialize
6
+ @url = nil # Must be configured by the user, e.g., 'ws://localhost:3000/cable'
7
+ @channel = 'GcStatsChannel'
8
+ @interval = 30 # seconds
9
+ @source = "Process-#{Process.pid}" # A default identifier
10
+ @verbose = false
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module GcReporter
2
+ class Railtie < Rails::Railtie
3
+ config.after_initialize do
4
+ if defined?(Rails::Server)
5
+ GcReporter.configuration.source ||= "Rails-#{Process.pid}"
6
+ GcReporter::Reporter.start
7
+
8
+ at_exit { GcReporter::Reporter.stop }
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,86 @@
1
+ require 'action_cable_client'
2
+ require 'time'
3
+ require 'json'
4
+
5
+ module GcReporter
6
+ class Reporter
7
+ def self.start
8
+ config = GcReporter.configuration
9
+ return if running?
10
+ return log("Cannot start: URL not configured.", level: :error) if config.url.nil?
11
+
12
+ @running = true
13
+ @thread = Thread.new do
14
+ client = ActionCableClient.new(config.url, channel: config.channel)
15
+ log("Reporter thread started. Sending stats every #{config.interval}s.")
16
+
17
+ client.connected { log("Successfully connected to Action Cable at #{config.url}.") }
18
+ client.disconnected { log("Disconnected from Action Cable. Client will try to reconnect.") }
19
+
20
+ loop do
21
+ break unless @running
22
+ begin
23
+ client.perform('report', collect_stats) if client.subscribed?
24
+ rescue => e
25
+ log("Error reporting stats: #{e.message}", level: :error)
26
+ end
27
+ sleep config.interval
28
+ end
29
+ end
30
+ end
31
+
32
+ # Stops the background reporting thread.
33
+ def self.stop
34
+ return unless running?
35
+ @running = false
36
+ @thread&.kill
37
+ @thread = nil
38
+ log("Reporter stopped.")
39
+ end
40
+
41
+ # Sends a single, synchronous report.
42
+ # Ideal for short-lived scripts like Rake tasks.
43
+ def self.report_once!
44
+ config = GcReporter.configuration
45
+ return log("Cannot report: URL not configured.", level: :error) if config.url.nil?
46
+
47
+ log("Performing a one-off report...")
48
+ # Using a block ensures the client is created and torn down cleanly.
49
+ ActionCableClient.start(config.url, channel: config.channel) do |client|
50
+ client.subscribed do
51
+ log("One-off report client subscribed. Sending data.")
52
+ client.perform('report', collect_stats)
53
+ # Disconnect after sending to allow the parent script to exit.
54
+ client.disconnect!
55
+ end
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def self.running?
62
+ !!@running
63
+ end
64
+
65
+ def self.collect_stats
66
+ {
67
+ source: GcReporter.configuration.source,
68
+ process_id: Process.pid,
69
+ reported_at: Time.now.utc.iso8601,
70
+ payload: {
71
+ gc_stat: GC.stat,
72
+ object_counts: ObjectSpace.count_objects
73
+ }
74
+ }
75
+ end
76
+
77
+ def self.log(message, level: :info)
78
+ timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S')
79
+ if level == :error
80
+ warn "[GcReporter ERROR] #{timestamp}: #{message}"
81
+ elsif GcReporter.configuration.verbose
82
+ puts "[GcReporter INFO] #{timestamp}: #{message}"
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,12 @@
1
+ # This file must be explicitly required by the user in their Sidekiq initializer.
2
+ if defined?(Sidekiq)
3
+ Sidekiq.configure_server do |config|
4
+ config.on(:startup) do
5
+ GcReporter.configuration.source ||= "Sidekiq-#{Process.pid}"
6
+ GcReporter::Reporter.start
7
+ end
8
+
9
+ config.on(:quiet) { GcReporter::Reporter.stop }
10
+ config.on(:shutdown) { GcReporter::Reporter.stop }
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module GcReporter
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,16 @@
1
+ require "gc_reporter/version"
2
+ require "gc_reporter/configuration"
3
+ require "gc_reporter/reporter"
4
+ require "gc_reporter/railtie" if defined?(Rails::Railtie)
5
+
6
+ module GcReporter
7
+ class Error < StandardError; end
8
+
9
+ def self.configure
10
+ yield(configuration)
11
+ end
12
+
13
+ def self.configuration
14
+ @configuration ||= Configuration.new
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gc_reporter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Gemini AI
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: action_cable_client
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '3.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '3.1'
26
+ - !ruby/object:Gem::Dependency
27
+ name: railties
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 5.0.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 5.0.0
40
+ description: A Rails extension to collect and report GC.stat and ObjectSpace counts
41
+ from Rails, Sidekiq, and Rake tasks to a central Action Cable endpoint.
42
+ email:
43
+ - ai@google.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - README.md
49
+ - gc_reporter.gemspec
50
+ - lib/gc_reporter.rb
51
+ - lib/gc_reporter/configuration.rb
52
+ - lib/gc_reporter/railtie.rb
53
+ - lib/gc_reporter/reporter.rb
54
+ - lib/gc_reporter/sidekiq.rb
55
+ - lib/gc_reporter/version.rb
56
+ homepage: https://github.com/codepawpaw/gc_reporter
57
+ licenses:
58
+ - MIT
59
+ metadata:
60
+ homepage_uri: https://github.com/codepawpaw/gc_reporter
61
+ source_code_uri: https://github.com/codepawpaw/gc_reporter
62
+ changelog_uri: https://github.com/codepawpaw/gc_reporter/CHANGELOG.md
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 2.7.0
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubygems_version: 3.6.9
78
+ specification_version: 4
79
+ summary: Reports GC stats over Action Cable.
80
+ test_files: []