puma-metrics 0.0.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52e6b92c221213e6d136e47d8aec1d2cb2a8279614dbd5714a30f7c82aec69b2
4
- data.tar.gz: be07b67faa4b234709fa142bff7fc9beb4bb1923e5dd2753e4169895c00061bd
3
+ metadata.gz: 37f1ce3ea6119b2ed16fc6a44b782c73c8a5556b8a34d05d0405ef858cbe296c
4
+ data.tar.gz: 88c7934712eeaa24b0d4bc7b7046d2a3831da3f03052c30ed9e9b1a3273b7a81
5
5
  SHA512:
6
- metadata.gz: b7e061a28a0a57092508a8d5fa2146f8f24e3b8a65d36b2408ee6a931846d516a53b1bd8af8612553d9cf01850df602694758d16da2b75e9d4d7b61148f035b9
7
- data.tar.gz: a013abe137b98ae273ff7d21b408c04c334f248679757cd70a79332a6478e12050814c2f84a5a1c1df9b9ca1c609b27525dece595cc4c401deaa84823bb992c4
6
+ metadata.gz: 0914550673aeeecf7535cf6a049d041c8e9b350eb416bf090a686a426f4a51e2d9060f4899d60a74359486c02f237e266f5174a59786d4bf1ad110c9978d0e47
7
+ data.tar.gz: 02b8e0d1ee0f29035446915617459d651485b847f8586b8c6d6c2dbf9452ab11ed77a1db840e81e04c2d71c85eee5532e1f1e063fcd2a47e27ce92a1c5ae6224
data/.rubocop.yml CHANGED
@@ -7,3 +7,12 @@ Naming/FileName:
7
7
 
8
8
  Metrics/LineLength:
9
9
  Max: 120
10
+
11
+ Style/Documentation:
12
+ Enabled: false
13
+ Style/MethodMissingSuper:
14
+ Exclude:
15
+ - lib/puma/metrics/parser.rb
16
+ Style/MissingRespondToMissing:
17
+ Exclude:
18
+ - lib/puma/metrics/parser.rb
data/.travis.yml CHANGED
@@ -4,6 +4,10 @@ rvm:
4
4
  - 2.3
5
5
  - 2.4
6
6
  - 2.5
7
+ script:
8
+ - bundle exec rake
9
+ - bundle exec overcommit --sign
10
+ - bundle exec overcommit --run
7
11
  deploy:
8
12
  provider: rubygems
9
13
  api_key:
@@ -11,3 +15,4 @@ deploy:
11
15
  gem: puma-metrics
12
16
  on:
13
17
  repo: harmjanblok/puma-metrics
18
+ rvm: 2.5
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0
4
+
5
+ Initial release of the `puma-metrics` gem.
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- puma-metrics (0.0.0)
4
+ puma-metrics (1.0.0)
5
+ prometheus-client (~> 0.8)
5
6
  puma (~> 3.0)
6
7
 
7
8
  GEM
@@ -13,6 +14,7 @@ GEM
13
14
  ffi (1.9.25)
14
15
  iniparse (1.4.4)
15
16
  jaro_winkler (1.5.1)
17
+ minitest (5.11.3)
16
18
  overcommit (0.46.0)
17
19
  childprocess (~> 0.6, >= 0.6.3)
18
20
  iniparse (~> 1.4)
@@ -20,7 +22,10 @@ GEM
20
22
  parser (2.5.1.2)
21
23
  ast (~> 2.4.0)
22
24
  powerpack (0.1.2)
25
+ prometheus-client (0.8.0)
26
+ quantile (~> 0.2.1)
23
27
  puma (3.12.0)
28
+ quantile (0.2.1)
24
29
  rainbow (3.0.0)
25
30
  rake (10.5.0)
26
31
  rubocop (0.59.0)
@@ -39,6 +44,7 @@ PLATFORMS
39
44
 
40
45
  DEPENDENCIES
41
46
  bundler
47
+ minitest
42
48
  overcommit
43
49
  puma-metrics!
44
50
  rake
data/README.md CHANGED
@@ -1,8 +1,47 @@
1
1
  # puma-metrics
2
2
 
3
+ [![Build Status](https://travis-ci.org/harmjanblok/puma-metrics.svg?branch=master)](https://travis-ci.org/harmjanblok/puma-metrics)
4
+
5
+ A puma plugin to export Puma's internal statistics as Prometheus metrics.
6
+
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'puma-metrics'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install puma-metrics
23
+
24
+
25
+ ## Usage
26
+
27
+ Add following lines to your puma `config.rb` (see
28
+ [Configuration File](https://github.com/puma/puma#configuration-file)):
29
+
30
+ ```ruby
31
+ # config/puma.rb
32
+ # Load the metrics plugin
33
+ plugin 'metrics'
34
+
35
+ # Bind the metric server to "url". "tcp://" is the only accepted protocol.
36
+ #
37
+ # The default is "tcp://0.0.0.0:9393".
38
+ # metrics_url 'tcp://0.0.0.0:9393'
39
+ ```
40
+
3
41
  ## Credits
4
42
 
5
43
  The gem is inspired by the following projects:
44
+ * https://github.com/puma/puma
6
45
  * https://github.com/puma/puma-heroku
7
46
 
8
47
  ## License
data/Rakefile CHANGED
@@ -4,7 +4,28 @@ require 'rake/testtask'
4
4
  Rake::TestTask.new(:test) do |t|
5
5
  t.libs << 'test'
6
6
  t.libs << 'lib'
7
- t.test_files = FileList['test/**/*_test.rb']
7
+ t.test_files = FileList['test/**/test_*.rb']
8
+ end
9
+
10
+ task :server do
11
+ require 'puma'
12
+ require 'puma/configuration'
13
+ require 'puma/events'
14
+ require 'puma/plugin/metrics.rb'
15
+
16
+ configuration = Puma::Configuration.new do |config|
17
+ config.bind 'tcp://127.0.0.1:0'
18
+ config.metrics_url 'tcp://127.0.0.1:9494'
19
+ config.plugin 'metrics'
20
+ config.workers 1
21
+ config.app do |_env|
22
+ [200, {}, ['hello world']]
23
+ end
24
+ end
25
+
26
+ events = Puma::Events.new STDOUT, STDERR
27
+ launcher = Puma::Launcher.new(configuration, events: events)
28
+ launcher.run
8
29
  end
9
30
 
10
31
  task default: :test
@@ -0,0 +1,24 @@
1
+ require 'json'
2
+ require 'prometheus/client/formats/text'
3
+ require 'puma/metrics/parser'
4
+
5
+ module Puma
6
+ module Metrics
7
+ class App
8
+ def initialize(launcher)
9
+ @launcher = launcher
10
+ clustered = (@launcher.options[:workers] || 0) > 0
11
+ @parser = Parser.new clustered
12
+ end
13
+
14
+ def call(_env)
15
+ @parser.parse JSON.parse(@launcher.stats)
16
+ [
17
+ 200,
18
+ { 'Content-Type' => 'text/plain' },
19
+ [Prometheus::Client::Formats::Text.marshal(Prometheus::Client.registry)]
20
+ ]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,7 @@
1
+ module Puma
2
+ class DSL
3
+ def metrics_url(url = 'tcp://0.0.0.0:9393')
4
+ @options[:metrics_url] = url
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,45 @@
1
+ require 'prometheus/client'
2
+
3
+ module Puma
4
+ module Metrics
5
+ class Parser
6
+ def initialize(clustered = false)
7
+ register_default_metrics
8
+ register_clustered_metrics if clustered
9
+ end
10
+
11
+ def parse(stats, labels = {})
12
+ stats.each do |key, value|
13
+ value.each { |s| parse(s, labels.merge(index: s['index'])) } if key == 'worker_status'
14
+ parse(value, labels) if key == 'last_status'
15
+ update_metric(key, value, labels)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def register_clustered_metrics
22
+ registry.gauge(:puma_booted_workers, 'Number of booted workers').set({}, 1)
23
+ registry.gauge(:puma_old_workers, 'Number of old workers').set({}, 0)
24
+ end
25
+
26
+ def register_default_metrics
27
+ registry.gauge(:puma_backlog, 'Number of established but unaccepted connections in the backlog', index: 0)
28
+ registry.gauge(:puma_running, 'Number of running worker threads', index: 0)
29
+ registry.gauge(:puma_pool_capacity, 'Number of allocatable worker threads', index: 0)
30
+ registry.gauge(:puma_max_threads, 'Maximum number of worker threads', index: 0)
31
+ registry.gauge(:puma_workers, 'Number of configured workers').set({}, 1)
32
+ end
33
+
34
+ def registry
35
+ Prometheus::Client.registry
36
+ end
37
+
38
+ def update_metric(key, value, labels)
39
+ return if registry.get("puma_#{key}").nil?
40
+
41
+ registry.get("puma_#{key}").set(labels, value)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,5 +1,5 @@
1
1
  module Puma
2
2
  module Metrics
3
- VERSION = '0.0.0'.freeze
3
+ VERSION = '1.0.0'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1,29 @@
1
+ require 'puma/metrics/dsl'
2
+
3
+ Puma::Plugin.create do
4
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
5
+ def start(launcher)
6
+ str = launcher.options[:metrics_url]
7
+ return unless str
8
+
9
+ require 'puma/metrics/app'
10
+
11
+ app = Puma::Metrics::App.new launcher
12
+ uri = URI.parse str
13
+
14
+ metrics = Puma::Server.new app, launcher.events
15
+ metrics.min_threads = 0
16
+ metrics.max_threads = 1
17
+
18
+ case uri.scheme
19
+ when 'tcp'
20
+ launcher.events.log "* Starting metrics server on #{str}"
21
+ metrics.add_tcp_listener uri.host, uri.port
22
+ else
23
+ launcher.events.error "Invalid control URI: #{str}"
24
+ end
25
+
26
+ metrics.run
27
+ end
28
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
29
+ end
data/puma-metrics.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  lib = File.expand_path('lib', __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
- require 'puma-metrics/version'
4
+ require 'puma/metrics/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.authors = ['Harm-Jan Blok']
@@ -15,9 +15,11 @@ Gem::Specification.new do |spec|
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
17
 
18
+ spec.add_runtime_dependency 'prometheus-client', '~> 0.8'
18
19
  spec.add_runtime_dependency 'puma', '~> 3.0'
19
20
 
20
21
  spec.add_development_dependency 'bundler'
22
+ spec.add_development_dependency 'minitest'
21
23
  spec.add_development_dependency 'overcommit'
22
24
  spec.add_development_dependency 'rake'
23
25
  spec.add_development_dependency 'rubocop'
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puma-metrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harm-Jan Blok
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-11 00:00:00.000000000 Z
11
+ date: 2018-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: prometheus-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.8'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: puma
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +52,20 @@ dependencies:
38
52
  - - ">="
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: overcommit
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -89,12 +117,17 @@ files:
89
117
  - ".overcommit.yml"
90
118
  - ".rubocop.yml"
91
119
  - ".travis.yml"
120
+ - CHANGELOG.md
92
121
  - Gemfile
93
122
  - Gemfile.lock
94
123
  - LICENSE
95
124
  - README.md
96
125
  - Rakefile
97
- - lib/puma-metrics/version.rb
126
+ - lib/puma/metrics/app.rb
127
+ - lib/puma/metrics/dsl.rb
128
+ - lib/puma/metrics/parser.rb
129
+ - lib/puma/metrics/version.rb
130
+ - lib/puma/plugin/metrics.rb
98
131
  - puma-metrics.gemspec
99
132
  homepage: https://github.com/harmjanblok/puma-metrics
100
133
  licenses: