yabeda-puma-plugin 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: 334f667830d1f10ef87b752b222c0a48868f1e378b03d6d10e45e5d5289fa2ba
4
+ data.tar.gz: 764ec2ca14697304378c7cfca7663de24865a362b4664ff42dc4a1ff41f58df7
5
+ SHA512:
6
+ metadata.gz: 5048143d5d9c98727de4e70adb78c46b2147d4d698f083035ff42a3783301a0df2255eeb65d3c603748e4de10fb00c8b2e0fe953a541499e6dc9cb05d0b775dc
7
+ data.tar.gz: 4052ecba8891d22691f7477b0e5fa1eb433a779385f32184f7467d3543f8ea6350ede81f10925268e9e522d67928d3c497be20d6647e354a2c2f27962b692aec
data/.gitignore ADDED
@@ -0,0 +1,53 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ ## Specific to RubyMotion:
17
+ .dat*
18
+ .repl_history
19
+ build/
20
+ *.bridgesupport
21
+ build-iPhoneOS/
22
+ build-iPhoneSimulator/
23
+
24
+ ## Specific to RubyMotion (use of CocoaPods):
25
+ #
26
+ # We recommend against adding the Pods directory to your .gitignore. However
27
+ # you should judge for yourself, the pros and cons are mentioned at:
28
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
29
+ #
30
+ # vendor/Pods/
31
+
32
+ ## Documentation cache and generated files:
33
+ /.yardoc/
34
+ /_yardoc/
35
+ /doc/
36
+ /rdoc/
37
+
38
+ ## Environment normalization:
39
+ /.bundle/
40
+ /vendor/bundle
41
+ /lib/bundler/man/
42
+
43
+ # for a library or gem, you might want to ignore these files since the code is
44
+ # intended to run in multiple environments; otherwise, check them in:
45
+ # Gemfile.lock
46
+ # .ruby-version
47
+ # .ruby-gemset
48
+
49
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
+ .rvmrc
51
+ .byebug_history
52
+ .rspec_status
53
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ sudo: require
2
+ services:
3
+ - docker
4
+
5
+ before_script:
6
+ - unset BUNDLE_GEMFILE
7
+ - docker-compose run app bundle install
8
+ script:
9
+ - docker-compose run app bundle exec rspec
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'prometheus-client'
4
+ gem 'yabeda-prometheus'
5
+ # Specify your gem's dependencies in yabeda-puma.gemspec
6
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Salahutdinov Dmitry
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Salahutdinov Dmitry
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+ <a href="https://amplifr.com/?utm_source=uibook">
2
+ <img width="100" height="140" align="right"
3
+ alt="Sponsored by Amplifr" src="https://amplifr-direct.s3-eu-west-1.amazonaws.com/social_images/image/37b580d9-3668-4005-8d5a-137de3a3e77c.png" />
4
+ </a>
5
+
6
+ # Yabeda::Puma::Plugin
7
+
8
+ Built-in metrics for [Puma](https://github.com/puma/puma) web server monitoring out of the box! Part of the [yabeda](https://github.com/yabeda-rb/yabeda) suite.
9
+
10
+ ## Metrics
11
+
12
+ Works as the Puma plugin and provides following metrics:
13
+ - `puma_workers` - the number of running puma workers
14
+ - `puma_booted_workers` - the number of booted puma workers
15
+ - `puma_old_workers` - the number of old puma worker
16
+
17
+ Segmented by the worker:
18
+ - `puma_pool_capacity` - the capacity of each worker: the number of requests that the server is capable of taking right now. More details are [here](https://github.com/puma/puma/blob/0f8b10737e36fc24cdd572f76a739659b5fad9cb/lib/puma/server.rb#L167).
19
+ - `puma_running` - the number of running threads (spawned threads) for any puma worker
20
+ - `puma_max_threads` - preconfigured maximum number of worker threads
21
+ - `puma_backlog` - the number of backlog threads, the number of connections in that worker's "todo" set waiting for a worker thread.
22
+
23
+ ## Installation
24
+
25
+ Add this line to your application's Gemfile:
26
+
27
+ ```ruby
28
+ gem 'yabeda-puma'
29
+ ```
30
+
31
+ And then execute:
32
+
33
+ $ bundle
34
+
35
+ ## Usage
36
+
37
+ Add those 2 lines of code to your `config/puma.rb` file:
38
+ ```ruby
39
+ activate_control_app
40
+ plugin :yabeda
41
+ ```
42
+ It will activate default puma control application working over the unix socket, and runs the `yabeda` puma plugin, for registering and collecting the metrics.
43
+
44
+ ## Details
45
+
46
+ In accordance with the [architecture](https://github.com/puma/puma/blob/master/docs/architecture.md) of the puma web server lets look how it works:
47
+
48
+ ![Yabeda::Puma get metrics from puma control app over the unix socket](docs/diagram.png).
49
+
50
+
51
+ For the configuration above, we will have the list of metrics (with help of `yabeda-prometheus` exporter):
52
+ ```
53
+ GET /metrics
54
+
55
+ puma_backlog{index="0"} 0
56
+ puma_backlog{index="1"} 0
57
+ puma_running{index="0"} 5
58
+ puma_running{index="1"} 5
59
+ puma_pool_capacity{index="0"} 1
60
+ puma_pool_capacity{index="1"} 5
61
+ puma_max_threads{index="0"} 5
62
+ puma_max_threads{index="1"} 5
63
+ puma_workers 2
64
+ puma_booted_workers 2
65
+ puma_old_workers 0
66
+ ```
67
+
68
+ See also the grafana screenshot of monitoring puma pool size and it's capacity when application is overloaded:
69
+
70
+ ![Monitor puma metrics with grafana](docs/grafana.png).
71
+
72
+
73
+ ## Roadmap (TODO or Help wanted)
74
+
75
+ - Collect also `control-gc` puma metrics
76
+
77
+ ## Development with Docker
78
+
79
+ Get local development environment working and tests running is very easy with docker-compose:
80
+ ```bash
81
+ docker-compose run app bundle
82
+ docker-compose run app bundle exec rspec
83
+ ```
84
+
85
+ ## Contributing
86
+
87
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/yabeda-puma.
88
+
89
+ ## License
90
+
91
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "yabeda/puma"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,18 @@
1
+ version: '3.4'
2
+
3
+ services:
4
+ app:
5
+ image: ruby:2.6.0
6
+ environment:
7
+ - BUNDLE_PATH=/bundle
8
+ - BUNDLE_CONFIG=/app/.bundle/config
9
+ command: bash
10
+ working_dir: /app
11
+ volumes:
12
+ - .:/app:cached
13
+ - bundler_data:/bundle
14
+ tmpfs:
15
+ - /tmp
16
+
17
+ volumes:
18
+ bundler_data:
data/docs/diagram.png ADDED
Binary file
data/docs/grafana.png ADDED
Binary file
@@ -0,0 +1,40 @@
1
+ require 'yabeda/puma/plugin.rb'
2
+
3
+ Puma::Plugin.create do
4
+ def start(launcher)
5
+ clustered = (launcher.options[:workers] || 0) > 0
6
+
7
+ control_url = launcher.options[:control_url]
8
+ raise StandardError, "Puma control app is not activated" if control_url == nil
9
+
10
+ Yabeda::Puma::Plugin.tap do |puma|
11
+ puma.control_url = control_url
12
+ puma.control_auth_token = launcher.options[:control_auth_token]
13
+ end
14
+
15
+ Yabeda.configure do
16
+ group :puma
17
+
18
+ gauge :backlog, comment: 'Number of established but unaccepted connections in the backlog'
19
+ gauge :running, comment: 'Number of running worker threads'
20
+ gauge :pool_capacity, comment: 'Number of allocatable worker threads'
21
+ gauge :max_threads, comment: 'Maximum number of worker threads'
22
+ gauge :workers, comment: 'Number of configured workers'
23
+
24
+ if clustered
25
+ gauge :booted_workers, comment: 'Number of booted workers'
26
+ gauge :old_workers, comment: 'Number of old workers'
27
+ end
28
+
29
+ collect do
30
+ require 'yabeda/puma/plugin/statistics/fetcher'
31
+ stats = Yabeda::Puma::Plugin::Statistics::Fetcher.call
32
+ require 'yabeda/puma/plugin/statistics/parser'
33
+ Yabeda::Puma::Plugin::Statistics::Parser.new(clustered: clustered, data: stats).call.each do |item|
34
+ send("puma_#{item[:name]}").set(item[:labels], item[:value])
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
@@ -0,0 +1,21 @@
1
+ require 'yabeda/puma/plugin/statistics'
2
+ require 'json'
3
+
4
+ module Yabeda
5
+ module Puma
6
+ module Plugin
7
+ module Statistics
8
+ class Fetcher
9
+ def self.call
10
+ body = Socket.unix(Yabeda::Puma::Plugin.control_url.gsub("unix://", '')) do |socket|
11
+ socket << "GET /stats?token=#{Yabeda::Puma::Plugin.control_auth_token} HTTP/1.0\r\n\r\n"
12
+ socket.read
13
+ end
14
+
15
+ JSON.parse(body.split("\n").last)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,36 @@
1
+ require 'yabeda/puma/plugin/statistics'
2
+
3
+ module Yabeda
4
+ module Puma
5
+ module Plugin
6
+ module Statistics
7
+ class Parser
8
+ attr_reader :clustered, :data
9
+
10
+ def initialize(clustered:, data:)
11
+ @clustered = clustered
12
+ @data = data
13
+ end
14
+
15
+ def call
16
+ Array.new.tap { |result| parse(data, result) }
17
+ end
18
+
19
+ private
20
+
21
+ def parse(stats, labels = {}, result)
22
+ stats.each do |key, value|
23
+ value.each { |s| parse(s, labels.merge(index: s['index']), result) } if key == 'worker_status'
24
+ parse(value, labels, result) if key == 'last_status'
25
+ result << {name: key, value: value, labels: labels} if metric?(key)
26
+ end
27
+ end
28
+
29
+ def metric?(name)
30
+ Statistics::METRICS.include?(name.to_sym) || (Statistics::CLUSTERED_METRICS.include?(name.to_sym) && clustered)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,10 @@
1
+ module Yabeda
2
+ module Puma
3
+ module Plugin
4
+ module Statistics
5
+ METRICS = [:backlog, :running, :pool_capacity, :max_threads, :workers]
6
+ CLUSTERED_METRICS = [:booted_workers, :old_workers]
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ module Yabeda
2
+ module Puma
3
+ module Plugin
4
+ VERSION = "0.1.0"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ require "yabeda/puma/plugin/version"
2
+ require 'yabeda'
3
+
4
+ module Yabeda
5
+ module Puma
6
+ module Plugin
7
+ class << self
8
+ attr_accessor :control_url, :control_auth_token
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,32 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "yabeda/puma/plugin/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "yabeda-puma-plugin"
8
+ spec.version = Yabeda::Puma::Plugin::VERSION
9
+ spec.authors = ["Salahutdinov Dmitry"]
10
+ spec.email = ["dsalahutdinov@gmail.com"]
11
+
12
+ spec.summary = %q{Puma web server plugin for collecting puma metrics with Yabeda framework.}
13
+ spec.description = %q{Extends Yabeda metrics with puma web server values by using puma plugin}
14
+ spec.homepage = "http://github.com/yabeda-rb/yabeda-puma-plugin"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_runtime_dependency "yabeda"
25
+ spec.add_runtime_dependency "puma"
26
+ spec.add_runtime_dependency "json"
27
+
28
+ spec.add_development_dependency "bundler"
29
+ spec.add_development_dependency "rake", "~> 10.0"
30
+ spec.add_development_dependency "rspec", "~> 3.0"
31
+ spec.add_development_dependency "rack"
32
+ end
metadata ADDED
@@ -0,0 +1,162 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yabeda-puma-plugin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Salahutdinov Dmitry
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-04-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: yabeda
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: puma
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
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'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rack
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Extends Yabeda metrics with puma web server values by using puma plugin
112
+ email:
113
+ - dsalahutdinov@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - ".travis.yml"
121
+ - Gemfile
122
+ - LICENSE
123
+ - LICENSE.txt
124
+ - README.md
125
+ - Rakefile
126
+ - bin/console
127
+ - bin/setup
128
+ - docker-compose.yml
129
+ - docs/diagram.png
130
+ - docs/grafana.png
131
+ - lib/puma/plugin/yabeda.rb
132
+ - lib/yabeda/puma/plugin.rb
133
+ - lib/yabeda/puma/plugin/statistics.rb
134
+ - lib/yabeda/puma/plugin/statistics/fetcher.rb
135
+ - lib/yabeda/puma/plugin/statistics/parser.rb
136
+ - lib/yabeda/puma/plugin/version.rb
137
+ - yabeda-puma-plugin.gemspec
138
+ homepage: http://github.com/yabeda-rb/yabeda-puma-plugin
139
+ licenses:
140
+ - MIT
141
+ metadata: {}
142
+ post_install_message:
143
+ rdoc_options: []
144
+ require_paths:
145
+ - lib
146
+ required_ruby_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ required_rubygems_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ requirements: []
157
+ rubyforge_project:
158
+ rubygems_version: 2.7.7
159
+ signing_key:
160
+ specification_version: 4
161
+ summary: Puma web server plugin for collecting puma metrics with Yabeda framework.
162
+ test_files: []