cloud66 1.0.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: 354105873b589769eefa61120e7a7762cb6477097554a0c2aa5f1131d09a78c0
4
+ data.tar.gz: 3fe5d67f8d5bbab66998ea17547403d2bbcb907120275d096e1ec4003468768c
5
+ SHA512:
6
+ metadata.gz: b901bbe9aa20b23d021ebdddb5add70aaaaeed1dc3756e201e231db63d9b291b9a4d3e48bc31f326a3d6ec985d868e0e28d8554f4e4ac499c949f895bebe8c48
7
+ data.tar.gz: 989bf075cb02ae0e9b6b618f03bb460df72cbb7b423794277206a622eaa742e9ca6ff20eaa19a8af09ad5de9df2717e096c62e96c3c5f8c989b46333483c71d1
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ # 1.0.0
2
+ Initial release.
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # Cloud66
2
+ This gem provides various integrations with Cloud 66.
3
+
4
+ ## Usage
5
+ ### Queue Metrics Endpoint
6
+ By default, this gem will expose a metrics endpoint in your application at `/cloud66/metrics/queue`, which is only accessible through internal requests to `127.0.0.1` or `::1`.
7
+
8
+ This endpoint will detect which supported queue frameworks your application uses, and then expose some useful metrics:
9
+ - How many jobs are waiting in a given queue
10
+ - How many jobs are currently being processed in a given queue
11
+
12
+ The supported queue frameworks are:
13
+ - [Sidekiq](https://github.com/sidekiq/sidekiq)
14
+ - [Resque](https://github.com/resque/resque)
15
+ - [Delayed Job](https://github.com/collectiveidea/delayed_job) (via the [ActiveRecord backend](https://github.com/collectiveidea/delayed_job_active_record))
16
+
17
+ ### Configuration
18
+ You can configure this gem by creating a file in your Rails initializers (e.g. `config/initializers/cloud66.rb`) and adding the following (values shown are the defaults):
19
+ ```ruby
20
+ Cloud66.configure do |config|
21
+ config.engine_automount = true
22
+ config.engine_automount_endpoint = "/cloud66"
23
+ end
24
+ ```
25
+
26
+ ## Installation
27
+ Add this line to your application's Gemfile:
28
+
29
+ ```ruby
30
+ gem "cloud66"
31
+ ```
32
+
33
+ And then execute:
34
+ ```bash
35
+ $ bundle
36
+ ```
37
+
38
+ Or install it yourself as:
39
+ ```bash
40
+ $ gem install cloud66
41
+ ```
42
+
43
+ ## License
44
+ The gem is available as open source under the terms of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("test/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,4 @@
1
+ module Cloud66
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module Cloud66
2
+ class MetricsController < ApplicationController
3
+ def queue
4
+ render json: ::Cloud66::Metrics::Manager.metrics_array
5
+ end
6
+ end
7
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Cloud66::Engine.routes.draw do
2
+ get "metrics/queue", to: "metrics#queue"
3
+ end
@@ -0,0 +1,13 @@
1
+ module Cloud66
2
+ class Configuration
3
+ # Determines whether the engine is auto-mounted.
4
+ attr_accessor :engine_automount
5
+ # Determines the endpoint to which the engine is auto-mounted to.
6
+ attr_accessor :engine_automount_endpoint
7
+
8
+ def initialize
9
+ self.engine_automount = true
10
+ self.engine_automount_endpoint = "/cloud66"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module Cloud66
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Cloud66
4
+
5
+ initializer "cloud66.configuration" do |app|
6
+ if Cloud66.configuration.engine_automount
7
+ app.routes.append do
8
+ constraints(ip: /127\.0\.0\.1|::1/) do
9
+ mount Cloud66::Engine => Cloud66.configuration.engine_automount_endpoint
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,43 @@
1
+ require "cloud66/metrics/framework_base"
2
+
3
+ module Cloud66
4
+ module Metrics
5
+ class DelayedJobActiveRecord < FrameworkBase
6
+ class << self
7
+ protected
8
+
9
+ def detected_concrete
10
+ return ::Gem.loaded_specs["delayed_job"] &&
11
+ ::Gem.loaded_specs["delayed_job_active_record"] &&
12
+ ::Object.const_defined?(:Delayed) &&
13
+ ::Delayed.const_defined?(:Job) &&
14
+ ::Delayed.const_defined?(:Worker) &&
15
+ ::Delayed::Worker.respond_to?(:backend) &&
16
+ ::Delayed::Worker.backend = :active_record
17
+ end
18
+
19
+ def name_concrete
20
+ return "delayed_job_active_record"
21
+ end
22
+
23
+ def queue_array_concrete
24
+ delayed_job_pending = ::Delayed::Job.where(failed_at: nil, locked_at: nil).group(:queue).count
25
+ delayed_job_working = ::Delayed::Job.where(failed_at: nil).where.not(locked_at: nil).group(:queue).count
26
+
27
+ result = []
28
+ delayed_job_queue_names = delayed_job_pending.keys | delayed_job_working.keys
29
+ delayed_job_queue_names.each do |queue_name|
30
+ result << {
31
+ "backend" => name,
32
+ "queue" => queue_name,
33
+ "waiting" => delayed_job_pending[queue_name] || 0,
34
+ "processing" => delayed_job_working[queue_name] || 0,
35
+ }
36
+ end
37
+
38
+ return result
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,35 @@
1
+ module Cloud66
2
+ module Metrics
3
+ class FrameworkBase
4
+ def self.detected?
5
+ return @detected unless @detected.nil?
6
+ @detected = detected_concrete
7
+ return @detected
8
+ end
9
+
10
+ def self.name
11
+ return name_concrete
12
+ end
13
+
14
+ def self.queue_array
15
+ return queue_array_concrete
16
+ end
17
+
18
+ class << self
19
+ protected
20
+
21
+ def detected_concrete
22
+ raise ::Cloud66::NotImplemented
23
+ end
24
+
25
+ def name_concrete
26
+ raise ::Cloud66::NotImplemented
27
+ end
28
+
29
+ def queue_array_concrete
30
+ raise ::Cloud66::NotImplemented
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,26 @@
1
+ require "cloud66/metrics/sidekiq"
2
+ require "cloud66/metrics/resque"
3
+ require "cloud66/metrics/delayed_job_active_record"
4
+
5
+ module Cloud66
6
+ module Metrics
7
+ class Manager
8
+ QUEUE_FRAMEWORKS = [
9
+ ::Cloud66::Metrics::Sidekiq,
10
+ ::Cloud66::Metrics::Resque,
11
+ ::Cloud66::Metrics::DelayedJobActiveRecord,
12
+ ].freeze
13
+
14
+ def self.metrics_array
15
+ result = []
16
+ QUEUE_FRAMEWORKS.each do |framework|
17
+ next unless framework.detected?
18
+
19
+ result += framework.queue_array
20
+ end
21
+
22
+ return result
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,43 @@
1
+ require "cloud66/metrics/framework_base"
2
+
3
+ module Cloud66
4
+ module Metrics
5
+ class Resque < FrameworkBase
6
+ class << self
7
+ protected
8
+
9
+ def detected_concrete
10
+ return ::Gem.loaded_specs.key?("resque") &&
11
+ ::Object.const_defined?(:Resque) &&
12
+ ::Resque.respond_to?(:queues) &&
13
+ ::Resque.respond_to?(:working) &&
14
+ ::Resque.respond_to?(:size)
15
+ end
16
+
17
+ def name_concrete
18
+ return "resque"
19
+ end
20
+
21
+ def queue_array_concrete
22
+ resque_pending = ::Resque.queues.map { |queue_name| [queue_name, ::Resque.size(queue_name)] }.to_h
23
+
24
+ resque_working_array = ::Resque.working.map { |worker| worker.job["queue"] }.compact
25
+ resque_working = ::Hash.new(0).tap { |h| resque_working_array.each { |queue| h[queue] += 1 } }
26
+
27
+ result = []
28
+ resque_queue_names = resque_pending.keys | resque_working.keys
29
+ resque_queue_names.each do |queue_name|
30
+ result << {
31
+ "backend" => name,
32
+ "queue" => queue_name,
33
+ "waiting" => resque_pending[queue_name] || 0,
34
+ "processing" => resque_working[queue_name] || 0,
35
+ }
36
+ end
37
+
38
+ return result
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,41 @@
1
+ require "cloud66/metrics/framework_base"
2
+
3
+ module Cloud66
4
+ module Metrics
5
+ class Sidekiq < FrameworkBase
6
+ class << self
7
+ protected
8
+
9
+ def detected_concrete
10
+ return ::Gem.loaded_specs.key?("sidekiq") &&
11
+ ::Object.const_defined?(:Sidekiq) &&
12
+ ::Sidekiq.const_defined?(:Queue) &&
13
+ ::Sidekiq.const_defined?(:WorkSet)
14
+ end
15
+ def name_concrete
16
+ return "sidekiq"
17
+ end
18
+
19
+ def queue_array_concrete
20
+ sidekiq_pending = ::Sidekiq::Queue.all.map { |q| [q.name, q.size] }.to_h
21
+
22
+ sidekiq_working_array = ::Sidekiq::WorkSet.new.map { |_, _, work| work["queue"] }
23
+ sidekiq_working = ::Hash.new(0).tap { |h| sidekiq_working_array.each { |queue| h[queue] += 1 } }
24
+
25
+ result = []
26
+ sidekiq_queue_names = sidekiq_pending.keys | sidekiq_working.keys
27
+ sidekiq_queue_names.each do |queue_name|
28
+ result << {
29
+ "backend" => name,
30
+ "queue" => queue_name,
31
+ "waiting" => sidekiq_pending[queue_name] || 0,
32
+ "processing" => sidekiq_working[queue_name] || 0,
33
+ }
34
+ end
35
+
36
+ return result
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,9 @@
1
+ require "cloud66/metrics/sidekiq"
2
+ require "cloud66/metrics/resque"
3
+ require "cloud66/metrics/delayed_job_active_record"
4
+ require "cloud66/metrics/manager"
5
+
6
+ module Cloud66
7
+ module Metrics
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Cloud66
2
+ VERSION = "1.0.0"
3
+ end
data/lib/cloud66.rb ADDED
@@ -0,0 +1,17 @@
1
+ require "cloud66/version"
2
+ require "cloud66/engine"
3
+ require "cloud66/configuration"
4
+ require "cloud66/metrics"
5
+
6
+ module Cloud66
7
+ class Error < StandardError; end
8
+ class NotImplemented < Error; end
9
+
10
+ def self.configuration
11
+ @configuration ||= Cloud66::Configuration.new
12
+ end
13
+
14
+ def self.configure
15
+ yield(configuration)
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cloud66
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Cloud 66
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-10-10 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: '2.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '2.3'
27
+ description: Cloud 66 Ruby plugin
28
+ email:
29
+ - eng@cloud66.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - CHANGELOG.md
35
+ - README.md
36
+ - Rakefile
37
+ - app/controllers/cloud66/application_controller.rb
38
+ - app/controllers/cloud66/metrics_controller.rb
39
+ - config/routes.rb
40
+ - lib/cloud66.rb
41
+ - lib/cloud66/configuration.rb
42
+ - lib/cloud66/engine.rb
43
+ - lib/cloud66/metrics.rb
44
+ - lib/cloud66/metrics/delayed_job_active_record.rb
45
+ - lib/cloud66/metrics/framework_base.rb
46
+ - lib/cloud66/metrics/manager.rb
47
+ - lib/cloud66/metrics/resque.rb
48
+ - lib/cloud66/metrics/sidekiq.rb
49
+ - lib/cloud66/version.rb
50
+ homepage: https://www.cloud66.com
51
+ licenses:
52
+ - MIT
53
+ metadata:
54
+ homepage_uri: https://www.cloud66.com
55
+ source_code_uri: https://github.com/cloud66-oss/cloud66-rails
56
+ changelog_uri: https://github.com/cloud66-oss/cloud66-rails/blob/master/CHANGELOG.md
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubygems_version: 3.4.10
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: Cloud 66 Ruby plugin
76
+ test_files: []