cloud66 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []