deimos 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eb1166f1af8b6589e45dc0a2ab20fec615b691db7348e91199b368714a43e3a1
4
- data.tar.gz: 562fd8af67609e08de2f1063053a6f8cd6f84671a844e4d44b5bf61543a14800
3
+ metadata.gz: 15cc6372bc401ffa051316be8573fd8066b5f1749753679d680459c8846a394d
4
+ data.tar.gz: 504c5872e4c5c71ebd1f269075667589697fd3e20b95e6f10461e01fb2d8009a
5
5
  SHA512:
6
- metadata.gz: 980ee84529e282e676faa1191f8053ee6ff451d466f13888a5ecbf0448e450ef9e5c27cb04392847bedb2511c8fb473f38cd2ceeea7320132b5463df619c204b
7
- data.tar.gz: 20afcdeea07eab350938a88580898c0a6e5a11a7b695394c94eac68eeb5ea37e44bc80722f3b70fe5d50f82ccfa397fc0508f8bdd53d1cc61505224a2678b7f3
6
+ metadata.gz: 115bd70bb83642e7e58eeb5fd79856a0c1bb42390f879898ae015d0180bd81770ef6eb9499af239b1dc0ed6c90330f175abd4176a8b0b61834d1603e5dc83075
7
+ data.tar.gz: 4bf4b534367761779afc0c359cd5081c308d7245049b4a8c28fd953ef1d7a332d3d4af32e45098221f96a86a32ae94e2e8f02238b53fb635572a38668bbb6da9
data/Gemfile.lock CHANGED
@@ -2,23 +2,38 @@ PATH
2
2
  remote: .
3
3
  specs:
4
4
  deimos (0.1.0)
5
+ activesupport
6
+ concurrent-ruby
5
7
  huyegger
8
+ prometheus-client
6
9
  sinatra
7
10
  sinatra-contrib
8
11
 
9
12
  GEM
10
13
  remote: https://rubygems.org/
11
14
  specs:
15
+ activesupport (5.2.2)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 0.7, < 2)
18
+ minitest (~> 5.1)
19
+ tzinfo (~> 1.1)
12
20
  backports (3.12.0)
13
21
  coderay (1.1.2)
22
+ concurrent-ruby (1.1.4)
14
23
  diff-lcs (1.3)
15
24
  huyegger (0.4.4)
25
+ i18n (1.6.0)
26
+ concurrent-ruby (~> 1.0)
16
27
  method_source (0.9.2)
28
+ minitest (5.11.3)
17
29
  multi_json (1.13.1)
18
30
  mustermann (1.0.3)
31
+ prometheus-client (0.9.0)
32
+ quantile (~> 0.2.1)
19
33
  pry (0.12.2)
20
34
  coderay (~> 1.1.0)
21
35
  method_source (~> 0.9.0)
36
+ quantile (0.2.1)
22
37
  rack (2.0.6)
23
38
  rack-protection (2.0.5)
24
39
  rack
@@ -48,7 +63,10 @@ GEM
48
63
  rack-protection (= 2.0.5)
49
64
  sinatra (= 2.0.5)
50
65
  tilt (>= 1.3, < 3)
66
+ thread_safe (0.3.6)
51
67
  tilt (2.0.9)
68
+ tzinfo (1.2.5)
69
+ thread_safe (~> 0.1)
52
70
 
53
71
  PLATFORMS
54
72
  ruby
data/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # Deimos
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/deimos`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Deimos is an application designed to be run alongside Phobos, but can be run in any context to provide a unified status and metrics interface for kubernetes style applications.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ ## Name
6
+
7
+ Deimos, brother of Phobos, from Greek mythology. The personification of dread and terror. Also it is the other natural Martian satelite, the first being Phobos
6
8
 
7
9
  ## Installation
8
10
 
@@ -22,7 +24,74 @@ Or install it yourself as:
22
24
 
23
25
  ## Usage
24
26
 
25
- TODO: Write usage instructions here
27
+ ### Configuration
28
+
29
+ ```ruby
30
+ Deimos.configure do |config|
31
+ config.log_level = ENV.fetch("LOG_LEVEL", ::Logger::INFO)
32
+ config.port = ENV.fetch("PORT", 5000)
33
+ config.bind = ENV.fetch("BIND_IP", "0.0.0.0")
34
+ # An application hash that allows you to add more rack apps
35
+ # Doesn't override the defaults, just merges
36
+ config.applications.merge('/path' => Rack::App.new)
37
+ # Allows you to inject more middlewares into the application
38
+ config.applications.middleware << Middleware
39
+ end
40
+ ```
41
+
42
+ ### Status
43
+
44
+ Deimos allows you to add as many status checks are you like, however the API expects a true or false response. Any false responses from the bound blocks will return an `internal_server_error`
45
+
46
+ ```ruby
47
+ Deimos.status.add(:allocations) { AllocationService::Status.new.call }
48
+ Deimos.status.add(:another_check) { true }
49
+ ```
50
+ ```json
51
+ # GET /status
52
+ { "allocations":true, "another_check":true }
53
+ ```
54
+
55
+ Status checks are run in parallel.
56
+
57
+
58
+ ### Metrics
59
+
60
+ Deimos uses `ActiveSupport::Notification` and `Prometheus` under the hood.
61
+
62
+ #### Subscribing
63
+
64
+ The subsription takes, three required arguments and a block.
65
+ * The event name to subscribe to
66
+ * The type of collector
67
+ * The prometheus label
68
+
69
+ It also takes any extra keyword arguments and passes them to the collector, allowing you to specify extra options for each type of collector
70
+
71
+ * [Prometheus Collectors](https://github.com/prometheus/client_ruby#metrics)
72
+ * [ActiveSupport Notifications](https://api.rubyonrails.org/classes/ActiveSupport/Notifications.html)
73
+
74
+ ```ruby
75
+ Deimos.metrics.subscribe('event.name', type: :gauge, label: 'Label') do |event, collector|
76
+ collector.increment({}, event.payload[:value])
77
+ # event is an ActiveSupport::Notification::Event
78
+ # event.name # => "render"
79
+ # event.duration # => 10 (in milliseconds)
80
+ # event.payload # => {some: :payload}
81
+
82
+ # collector is a Prometheus::Client::#{type.classify}
83
+ end
84
+ ```
85
+
86
+ #### Instrumenting
87
+
88
+ `Deimos.metrics.instrument` delegates directly to `ActiveSupport::Notifications.instrument`, please see the [ActiveSupport Notifications](https://api.rubyonrails.org/classes/ActiveSupport/Notifications.html) documentation for more information
89
+
90
+ ```ruby
91
+ Deimos.metrics.instrument('product_count', value: 10 + i) do
92
+ # can wrap a block to give you code execution duration
93
+ end
94
+ ```
26
95
 
27
96
  ## Development
28
97
 
@@ -32,7 +101,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
101
 
33
102
  ## Contributing
34
103
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/deimos.
104
+ Bug reports and pull requests are welcome on GitHub at https://github.com/adamcarlile/deimos.
36
105
 
37
106
  ## License
38
107
 
data/deimos.gemspec CHANGED
@@ -23,6 +23,9 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency "sinatra"
24
24
  spec.add_dependency "sinatra-contrib"
25
25
  spec.add_dependency "huyegger"
26
+ spec.add_dependency "concurrent-ruby"
27
+ spec.add_dependency "prometheus-client"
28
+ spec.add_dependency "activesupport"
26
29
 
27
30
  spec.add_development_dependency "bundler", "~> 1.16"
28
31
  spec.add_development_dependency "rake", "~> 10.0"
@@ -0,0 +1,11 @@
1
+ module Deimos
2
+ module Endpoints
3
+ class Metrics < Sinatra::Application
4
+ disable :logging
5
+ set :logger, Deimos.logger
6
+
7
+ use Prometheus::Middleware::Exporter, registry: Deimos.metrics.registry, path: ''
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ module Deimos
2
+ module Endpoints
3
+ class Status < Sinatra::Application
4
+ disable :logging
5
+ set :logger, Deimos.logger
6
+
7
+ get "/" do
8
+ status_runner = Deimos.status.run!
9
+
10
+ content_type :json
11
+ status status_runner.status
12
+ status_runner.body
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ module Deimos
2
+ module Metrics
3
+ class Manager
4
+ TYPES = {
5
+ counter: Prometheus::Client::Counter,
6
+ gauge: Prometheus::Client::Gauge,
7
+ histogram: Prometheus::Client::Histogram,
8
+ summary: Prometheus::Client::Summary
9
+ }
10
+
11
+ delegate :instrument, to: ActiveSupport::Notifications
12
+
13
+ def subscriptions
14
+ @subscriptions ||= []
15
+ end
16
+
17
+ def collectors
18
+ @collectors ||= {}
19
+ end
20
+
21
+ def registry
22
+ @registry ||= Prometheus::Client.registry
23
+ end
24
+
25
+ def subscribe(event_name, type:, label:, **kwargs, &block)
26
+ Deimos.logger.info "Metrics: Subscribed to #{event_name}..."
27
+ subscriptions << ActiveSupport::Notifications.subscribe(event_name) do |*args|
28
+ event = ActiveSupport::Notifications::Event.new(*args)
29
+ collector = register_collector!(event_name, type, label, kwargs)
30
+ if block_given?
31
+ yield(event, collector)
32
+ else
33
+ Deimos.logger.info event
34
+ end
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def register_collector!(event_name, type, about, **kwargs)
41
+ return collectors[event_name] if collectors[event_name].present?
42
+ name = event_name.gsub(".", "_").to_sym
43
+ collectors[event_name] = TYPES[type].new(name, about, kwargs).tap { |x| registry.register(x) }
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,21 @@
1
+ module Deimos
2
+ module Status
3
+ class Manager
4
+
5
+ attr_reader :checks
6
+ def checks
7
+ @checks ||= {}
8
+ end
9
+
10
+ def add(name, &block)
11
+ Deimos.logger.info "Status: Reporting #{name} status..."
12
+
13
+ checks[name] = block || Proc.new { true }
14
+ end
15
+
16
+ def run!
17
+ Deimos::Status::Runner.new(checks)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ module Deimos
2
+ module Status
3
+ class Runner
4
+ def initialize(checks)
5
+ @checks = checks.dup
6
+ end
7
+
8
+ def status
9
+ ok? ? :ok : :internal_server_error
10
+ end
11
+
12
+ def body
13
+ completed_checks.to_json
14
+ end
15
+
16
+ private
17
+
18
+ def ok?
19
+ completed_checks.values.all?
20
+ end
21
+
22
+ def completed_checks
23
+ @completed_checks ||= @checks.transform_values do |function|
24
+ Concurrent::Promises.future(&function)
25
+ end.transform_values(&:value)
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -1,3 +1,3 @@
1
1
  module Deimos
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/deimos.rb CHANGED
@@ -1,27 +1,53 @@
1
+ require 'rack'
1
2
  require 'huyegger'
2
3
  require 'sinatra'
4
+ require 'active_support'
3
5
  require 'sinatra/contrib'
6
+ require "sinatra/json"
4
7
  require 'webrick'
5
8
  require 'logger'
9
+ require 'webrick'
10
+ require 'concurrent-ruby'
11
+ require 'prometheus/client'
12
+ require 'prometheus/middleware/exporter'
6
13
 
7
14
  require "deimos/version"
8
15
 
9
16
  require 'deimos/logger'
10
- require 'deimos/manager'
17
+ require 'deimos/status/runner'
18
+ require 'deimos/status/manager'
19
+ require 'deimos/metrics/manager'
11
20
 
12
21
  module Deimos
13
22
  module_function
14
23
 
15
24
  def boot!
16
- require 'deimos/status'
17
- Thread.new { Deimos::Status.run! }
25
+ require 'deimos/endpoints/status'
26
+ require 'deimos/endpoints/metrics'
27
+ Thread.new do
28
+ ::Rack::Handler::WEBrick.run(application, {
29
+ BindAddress: Deimos.config.bind,
30
+ Port: Deimos.config.port,
31
+ Logger: Deimos.logger,
32
+ AccessLog: []
33
+ })
34
+ end
35
+ end
36
+
37
+ def application
38
+ Rack::Builder.new do
39
+ Deimos.middleware.each { |m| use m }
40
+ run Rack::URLMap.new(Deimos.applications)
41
+ end
18
42
  end
19
43
 
20
44
  def config
21
45
  @config ||= OpenStruct.new.tap do |x|
22
- x.log_level = ENV.fetch("LOG_LEVEL", ::Logger::INFO)
23
- x.port = ENV.fetch("PORT", 5000)
24
- x.bind = ENV.fetch("BIND_IP", "0.0.0.0")
46
+ x.log_level = ENV.fetch("LOG_LEVEL", ::Logger::INFO)
47
+ x.port = ENV.fetch("PORT", 5000)
48
+ x.bind = ENV.fetch("BIND_IP", "0.0.0.0")
49
+ x.applications = {}
50
+ x.middleware = []
25
51
  end
26
52
  end
27
53
 
@@ -29,12 +55,23 @@ module Deimos
29
55
  yield(config)
30
56
  end
31
57
 
32
- def manager
33
- @manager ||= Deimos::Manager.new
58
+ def middleware
59
+ @middleware ||= [Rack::Deflater, Deimos::Logger] | config.middleware
60
+ end
61
+
62
+ def applications
63
+ @applications ||= {
64
+ "/status" => Deimos::Endpoints::Status,
65
+ "/metrics" => Deimos::Endpoints::Metrics
66
+ }.merge(config.applications)
67
+ end
68
+
69
+ def status
70
+ @status ||= Deimos::Status::Manager.new
34
71
  end
35
72
 
36
- def add(*args, &block)
37
- manager.add(*args, &block)
73
+ def metrics
74
+ @metrics ||= Deimos::Metrics::Manager.new
38
75
  end
39
76
 
40
77
  def logger
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deimos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Carlile
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-03-03 00:00:00.000000000 Z
11
+ date: 2019-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -52,6 +52,48 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: concurrent-ruby
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: prometheus-client
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: activesupport
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
55
97
  - !ruby/object:Gem::Dependency
56
98
  name: bundler
57
99
  requirement: !ruby/object:Gem::Requirement
@@ -127,9 +169,12 @@ files:
127
169
  - bin/setup
128
170
  - deimos.gemspec
129
171
  - lib/deimos.rb
172
+ - lib/deimos/endpoints/metrics.rb
173
+ - lib/deimos/endpoints/status.rb
130
174
  - lib/deimos/logger.rb
131
- - lib/deimos/manager.rb
132
- - lib/deimos/status.rb
175
+ - lib/deimos/metrics/manager.rb
176
+ - lib/deimos/status/manager.rb
177
+ - lib/deimos/status/runner.rb
133
178
  - lib/deimos/version.rb
134
179
  homepage: https://github.com/adamcarlile/deimos
135
180
  licenses:
@@ -1,17 +0,0 @@
1
- module Deimos
2
- class Manager
3
-
4
- def checks
5
- @checks ||= {}
6
- end
7
-
8
- def add(name, &block)
9
- checks[name] = block || Proc.new { true }
10
- end
11
-
12
- def call
13
- checks.transform_values(&:call).to_json
14
- end
15
-
16
- end
17
- end
data/lib/deimos/status.rb DELETED
@@ -1,27 +0,0 @@
1
- require "sinatra/base"
2
- require "sinatra/json"
3
- require 'webrick'
4
-
5
- # Sinatra Applicaiton to present basic health check endpoint
6
- module Deimos
7
- class Status < Sinatra::Application
8
-
9
- set :bind, Deimos.config.bind
10
- set :port, Deimos.config.port
11
- disable :show_exceptions, :traps, :logging
12
-
13
- use Deimos::Logger
14
-
15
- set :quiet, true
16
- set :logger, Deimos.logger
17
- set :server, :webrick
18
- set :server_settings,
19
- Logger: Deimos.logger,
20
- AccessLog: []
21
-
22
- get "/status" do
23
- content_type :json
24
- Deimos.manager.call
25
- end
26
- end
27
- end