gruf-prometheus 0.0.2

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: 1b2ac2951ece4595b35a0b951bbcd9d8d246238b755771554316fb22b97ab5ef
4
+ data.tar.gz: db1793e8f126900fa981fc8cc2f36f665bbce8590f2d8cfab5912b5763180ec3
5
+ SHA512:
6
+ metadata.gz: 6766ed05abc90b57c8b46a587fe16c2f16c8aa46883a62f7493ae61938212a89d0c5b53a805949c1030dfe03a55dc9fd56e1f7972e12c50f7535f15e4397af04
7
+ data.tar.gz: 6be2cc11e6d60caf4861196852a722c08ba1b20dc37a4e449033cf09ed41337aa66b6ba90d0bd73d66304b82b2d7acf49e3578f52eceb65781419054b1d41747
data/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ Changelog for the gruf-prometheus gem.
2
+
3
+ ### Pending Release
4
+
5
+ ### 0.0.2
6
+
7
+ - Cleaner starting of the gruf server and collectors
8
+ - Improved logging and visibility around starting/stopping of collectors/server
9
+
10
+ ### 0.0.1
11
+
12
+ - Initial public release
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at splittingred@gmail.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # gruf-prometheus - Prometheus support for gruf
2
+
3
+ [![CircleCI](https://circleci.com/gh/bigcommerce/gruf-prometheus/tree/master.svg?style=svg)](https://circleci.com/gh/bigcommerce/gruf-prometheus/tree/master)
4
+
5
+ Adds Prometheus support for [gruf](https://github.com/bigcommerce/gruf) 2.7.0+.
6
+
7
+ ## Installation
8
+
9
+ ```ruby
10
+ gem 'gruf-prometheus'
11
+ ```
12
+
13
+ In your gruf initializer:
14
+
15
+ ```ruby
16
+ require 'gruf/prometheus'
17
+
18
+ Gruf.configure do |c|
19
+ c.hooks.use(Gruf::Prometheus::Hook)
20
+ end
21
+ ```
22
+
23
+ Then `bundle exec gruf` and you'll automatically have prometheus metrics for gruf servers.
24
+
25
+ ## Configuration
26
+
27
+ You can further configure with:
28
+
29
+ | Option | Description | Default |
30
+ | ------ | ----------- | ------- |
31
+ | client_custom_labels | A hash of custom labels to send with each client request | `{}` |
32
+ | client_max_queue_size | The max amount of metrics to send before flushing | 10000 |
33
+ | client_thread_sleep | How often to sleep the worker thread that manages the client buffer (seconds) | 0.5 |
34
+ | process_label | The label to use for metric prefixing | grpc |
35
+ | process_name | Label to use for process name in logging | grpc |
36
+ | collection_frequency | How often to poll collection metrics (seconds) | 15 |
37
+ | server_host | The host to run the collector on | '0.0.0.0' |
38
+ | server_port | The port to run the collector on | 9394 |
39
+ | server_prefix | The prefix for all collected metrics | ruby_ |
40
+ | server_timeout | Timeout when exporting metrics (seconds) | 2 |
41
+
42
+ ## License
43
+
44
+ Copyright (c) 2019-present, BigCommerce Pty. Ltd. All rights reserved
45
+
46
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
47
+ documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
48
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
49
+ persons to whom the Software is furnished to do so, subject to the following conditions:
50
+
51
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
52
+ Software.
53
+
54
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
55
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
56
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
57
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ $:.push File.expand_path('../lib', __FILE__)
19
+ require 'gruf/prometheus/version'
20
+
21
+ Gem::Specification.new do |spec|
22
+ spec.name = 'gruf-prometheus'
23
+ spec.version = Gruf::Prometheus::VERSION
24
+ spec.authors = ['Shaun McCormick']
25
+ spec.email = ['shaun.mccormick@bigcommerce.com']
26
+
27
+ spec.summary = 'Prometheus support for gruf'
28
+ spec.description = spec.summary
29
+ spec.homepage = 'https://github.com/bigcommerce/gruf-prometheus'
30
+ spec.license = 'MIT'
31
+
32
+ spec.files = Dir['README.md', 'CHANGELOG.md', 'CODE_OF_CONDUCT.md', 'lib/**/*', 'gruf-prometheus.gemspec']
33
+ spec.require_paths = ['lib']
34
+
35
+ spec.add_development_dependency 'rake', '>= 10.0'
36
+ spec.add_development_dependency 'rspec', '>= 3.8'
37
+ spec.add_development_dependency 'rspec_junit_formatter', '>= 0.4'
38
+ spec.add_development_dependency 'bundler-audit', '>= 0.6'
39
+ spec.add_development_dependency 'rubocop', '>= 0.68'
40
+ spec.add_development_dependency 'simplecov', '>= 0.16'
41
+ spec.add_development_dependency 'null-logger', '>= 0.1'
42
+ spec.add_development_dependency 'pry', '>= 0.12'
43
+
44
+ spec.add_runtime_dependency 'gruf', '>= 2.7'
45
+ spec.add_runtime_dependency 'prometheus_exporter', '~> 0.4'
46
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ require 'prometheus_exporter'
19
+ require 'prometheus_exporter/server'
20
+ require 'prometheus_exporter/client'
21
+ require 'prometheus_exporter/middleware'
22
+ require 'prometheus_exporter/instrumentation'
23
+ require 'gruf'
24
+
25
+ require_relative 'prometheus/version'
26
+ require_relative 'prometheus/configuration'
27
+ require_relative 'prometheus/client'
28
+ require_relative 'prometheus/server'
29
+ require_relative 'prometheus/collectors/grpc'
30
+ require_relative 'prometheus/type_collectors/grpc'
31
+ require_relative 'prometheus/hook'
32
+
33
+ module Gruf
34
+ ##
35
+ # Base top-level gruf prometheus module
36
+ #
37
+ module Prometheus
38
+ extend Configuration
39
+
40
+ def self.client
41
+ Gruf::Prometheus::Client.instance
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Prometheus
20
+ ##
21
+ # Client implementation for Prometheus
22
+ #
23
+ class Client < ::PrometheusExporter::Client
24
+ include Singleton
25
+
26
+ def initialize
27
+ super(
28
+ host: ::Gruf::Prometheus.server_host,
29
+ port: ::Gruf::Prometheus.server_port,
30
+ max_queue_size: ::Gruf::Prometheus.client_max_queue_size,
31
+ thread_sleep: ::Gruf::Prometheus.client_thread_sleep,
32
+ custom_labels: ::Gruf::Prometheus.client_custom_labels
33
+ )
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Prometheus
20
+ module Collectors
21
+ ##
22
+ # Prometheus instrumentor for gRPC servers
23
+ #
24
+ class Grpc
25
+ include Gruf::Loggable
26
+
27
+ ##
28
+ # @param [Gruf::Server] server
29
+ # @param [Gruf::Prometheus::Client] client
30
+ # @param [Integer] frequency
31
+ #
32
+ def initialize(server:, client:, frequency: nil)
33
+ @server = server
34
+ @client = client
35
+ @frequency = frequency || 15
36
+ end
37
+
38
+ ##
39
+ # Start the instrumentor
40
+ #
41
+ # @param [Gruf::Server] server
42
+ # @param [Gruf::Prometheus::Client] client
43
+ # @param [Integer] frequency
44
+ #
45
+ def self.start(server:, client: nil, frequency: nil)
46
+ collector = new(server: server, client: client, frequency: frequency)
47
+ Thread.new do
48
+ loop do
49
+ collector.run
50
+ end
51
+ end
52
+ end
53
+
54
+ def run
55
+ metric = collect
56
+ logger.debug "[gruf-prometheus] Pushing metrics to collector: #{metric.inspect}"
57
+ @client.send_json metric
58
+ rescue StandardError => e
59
+ logger.error "[gruf-prometheus] Failed to collect gruf-prometheus stats: #{e.message}"
60
+ ensure
61
+ sleep @frequency
62
+ end
63
+
64
+ private
65
+
66
+ def collect
67
+ metric = {}
68
+ metric[:type] = 'grpc'
69
+ rpc_server = @server.server
70
+ rpc_server.instance_variable_get(:@run_mutex).synchronize do
71
+ collect_server_metrics(rpc_server, metric)
72
+ end
73
+ metric
74
+ end
75
+
76
+ ##
77
+ # @param [GRPC::RpcServer] rpc_server
78
+ #
79
+ def collect_server_metrics(rpc_server, metric)
80
+ pool = rpc_server.instance_variable_get(:@pool)
81
+ metric[:pool_jobs_waiting_total] = pool.jobs_waiting.to_i
82
+ metric[:pool_ready_workers_total] = pool.instance_variable_get(:@ready_workers).size
83
+ metric[:pool_workers_total] = pool.instance_variable_get(:@workers)&.size
84
+ metric[:pool_initial_size] = rpc_server.instance_variable_get(:@pool_size).to_i
85
+ metric[:poll_period] = rpc_server.instance_variable_get(:@poll_period).to_i
86
+ end
87
+
88
+ ##
89
+ # @return [GRPC::RpcServer]
90
+ #
91
+ def grpc_server
92
+ @server.server
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Prometheus
20
+ ##
21
+ # General configuration for gruf prometheus integration
22
+ #
23
+ module Configuration
24
+ VALID_CONFIG_KEYS = {
25
+ client_custom_labels: nil,
26
+ client_max_queue_size: 10_000,
27
+ client_thread_sleep: 0.5,
28
+ process_label: 'grpc',
29
+ process_name: 'grpc',
30
+ collection_frequency: 15,
31
+ server_host: '0.0.0.0',
32
+ server_port: ::PrometheusExporter::DEFAULT_PORT,
33
+ server_prefix: ::PrometheusExporter::DEFAULT_PREFIX,
34
+ server_timeout: ::PrometheusExporter::DEFAULT_TIMEOUT
35
+ }.freeze
36
+
37
+ attr_accessor *VALID_CONFIG_KEYS.keys
38
+
39
+ ##
40
+ # Whenever this is extended into a class, setup the defaults
41
+ #
42
+ def self.extended(base)
43
+ base.reset
44
+ end
45
+
46
+ ##
47
+ # Yield self for ruby-style initialization
48
+ #
49
+ # @yields [Bigcommerce::Prometheus::Configuration]
50
+ # @return [Bigcommerce::Prometheus::Configuration]
51
+ #
52
+ def configure
53
+ reset unless @configured
54
+ yield self
55
+ @configured = true
56
+ end
57
+
58
+ ##
59
+ # Return the current configuration options as a Hash
60
+ #
61
+ # @return [Hash]
62
+ #
63
+ def options
64
+ opts = {}
65
+ VALID_CONFIG_KEYS.each_key do |k|
66
+ opts.merge!(k => send(k))
67
+ end
68
+ opts
69
+ end
70
+
71
+ ##
72
+ # Set the default configuration onto the extended class
73
+ #
74
+ def reset
75
+ VALID_CONFIG_KEYS.each do |k, v|
76
+ send("#{k}=".to_sym, v)
77
+ end
78
+ self.client_max_queue_size = ENV.fetch('PROMETHEUS_CLIENT_MAX_QUEUE_SIZE', 10_000).to_i
79
+ self.client_thread_sleep = ENV.fetch('PROMETHEUS_CLIENT_THREAD_SLEEP', 0.5).to_i
80
+ self.process_label = ENV.fetch('PROMETHEUS_PROCESS_LABEL', 'grpc').to_s
81
+ self.collection_frequency = ENV.fetch('PROMETHEUS_COLLECTION_FREQUENCY', 30).to_i
82
+ self.server_host = ENV.fetch('PROMETHEUS_SERVER_HOST', '0.0.0.0').to_s
83
+ self.server_port = ENV.fetch('PROMETHEUS_SERVER_PORT', ::PrometheusExporter::DEFAULT_PORT).to_i
84
+ self.server_timeout = ENV.fetch('PROMETHEUS_SERVER_TIMEOUT', ::PrometheusExporter::DEFAULT_TIMEOUT).to_i
85
+ end
86
+
87
+ ##
88
+ # Automatically determine environment
89
+ #
90
+ # @return [String] The current Ruby environment
91
+ #
92
+ def environment
93
+ if defined?(Rails)
94
+ Rails.env.to_s
95
+ else
96
+ (ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development').to_s
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Prometheus
20
+ ##
21
+ # Hook for implementing prometheus stats before a gruf server starts
22
+ #
23
+ class Hook < Gruf::Hooks::Base
24
+ ##
25
+ # Startup the instrumentors for collection of gRPC and process metrics prior to server start
26
+ #
27
+ # @param [Gruf::Server] server
28
+ #
29
+ def before_server_start(server:)
30
+ start_collectors(server: server)
31
+ prometheus_server.add_type_collector(Gruf::Prometheus::TypeCollectors::Grpc)
32
+ prometheus_server.start
33
+ rescue StandardError => e
34
+ logger.error "[gruf-prometheus][#{::Gruf::Prometheus.process_name}] Failed to start gruf instrumentation - #{e.message} - #{e.backtrace[0..4].join("\n")}"
35
+ end
36
+
37
+ ##
38
+ # Handle proper shutdown of the prometheus server
39
+ #
40
+ def after_server_stop(server:)
41
+ logger.debug "[gruf-prometheus][#{::Gruf::Prometheus.process_name}] Stopping #{server.class}"
42
+ prometheus_server.stop
43
+ rescue StandardError => e
44
+ logger.error "[gruf-prometheus][#{::Gruf::Prometheus.process_name}] Failed to stop gruf instrumentation - #{e.message} - #{e.backtrace[0..4].join("\n")}"
45
+ end
46
+
47
+ private
48
+
49
+ ##
50
+ # Start collectors for the gRPC process
51
+ #
52
+ def start_collectors(server:)
53
+ ::PrometheusExporter::Instrumentation::Process.start(
54
+ type: ::Gruf::Prometheus.process_label,
55
+ client: ::Gruf::Prometheus.client,
56
+ frequency: ::Gruf::Prometheus.collection_frequency
57
+ )
58
+ ::Gruf::Prometheus::Collectors::Grpc.start(
59
+ server: server,
60
+ client: ::Gruf::Prometheus.client,
61
+ frequency: ::Gruf::Prometheus.collection_frequency
62
+ )
63
+ end
64
+
65
+ ##
66
+ # @return [Gruf::Prometheus::Server]
67
+ #
68
+ def prometheus_server
69
+ @prometheus_server ||= ::Gruf::Prometheus::Server.new(
70
+ port: Gruf::Prometheus.server_port,
71
+ timeout: Gruf::Prometheus.server_timeout,
72
+ prefix: Gruf::Prometheus.server_prefix
73
+ )
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Prometheus
20
+ ##
21
+ # Prometheus server that runs with gruf hooks
22
+ #
23
+ class Server
24
+ include Gruf::Loggable
25
+
26
+ ##
27
+ # @param [Integer] port
28
+ # @param [Integer] timeout
29
+ # @param [String] prefix
30
+ # @param [Boolean] verbose
31
+ # @param [Class] server_class
32
+ #
33
+ def initialize(
34
+ port:,
35
+ timeout:,
36
+ prefix: nil,
37
+ verbose: false,
38
+ server_class: nil
39
+ )
40
+ @port = (port || ::PrometheusExporter::DEFAULT_PORT).to_i
41
+ @timeout = (timeout || ::PrometheusExporter::DEFAULT_TIMEOUT).to_i
42
+ @prefix = (prefix || ::PrometheusExporter::DEFAULT_PREFIX).to_s
43
+ @verbose = verbose
44
+ @server_class = server_class || ::PrometheusExporter::Server::WebServer
45
+ @running = false
46
+ @process_name = ::Gruf::Prometheus.process_name
47
+ end
48
+
49
+ def start
50
+ logger.info "[gruf-prometheus][#{@process_name}] Starting prometheus exporter on port #{@port}"
51
+ server.start
52
+ logger.info "[gruf-prometheus][#{@process_name}] Prometheus exporter started on port #{@port}"
53
+
54
+ @running = true
55
+ server
56
+ rescue StandardError => e
57
+ logger.error "[gruf-prometheus][#{@process_name}] Failed to start exporter: #{e.message}"
58
+ end
59
+
60
+ ##
61
+ # Stop the server
62
+ #
63
+ def stop
64
+ logger.info "[gruf-prometheus][#{@process_name}] Shutting down prometheus exporter"
65
+ server.stop
66
+ logger.info "[gruf-prometheus][#{@process_name}] Prometheus exporter cleanly shut down"
67
+ rescue StandardError => e
68
+ logger.error "[gruf-prometheus][#{@process_name}] Failed to stop exporter: #{e.message}"
69
+ end
70
+
71
+ ##
72
+ # Whether or not the server is running
73
+ #
74
+ # @return [Boolean]
75
+ #
76
+ def running?
77
+ @running
78
+ end
79
+
80
+ ##
81
+ # Add a type collector to this server
82
+ #
83
+ # @param [Class] collector A type collector for the prometheus server
84
+ #
85
+ def add_type_collector(collector)
86
+ runner.type_collectors = runner.type_collectors.push(collector)
87
+ end
88
+
89
+ private
90
+
91
+ ##
92
+ # @return [::PrometheusExporter::Server::Runner]
93
+ #
94
+ def runner
95
+ unless @runner
96
+ @runner = ::PrometheusExporter::Server::Runner.new(
97
+ timeout: @timeout,
98
+ port: @port,
99
+ prefix: @prefix,
100
+ verbose: @verbose,
101
+ server_class: @server_class
102
+ )
103
+ PrometheusExporter::Metric::Base.default_prefix = @runner.prefix
104
+ end
105
+ @runner
106
+ end
107
+
108
+ ##
109
+ # @return [PrometheusExporter::Server::WebServer]
110
+ #
111
+ def server
112
+ @server ||= begin
113
+ runner.send(:register_type_collectors)
114
+ runner.server_class.new(
115
+ port: runner.port,
116
+ collector: runner.collector,
117
+ timeout: runner.timeout,
118
+ verbose: runner.verbose
119
+ )
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Prometheus
20
+ module TypeCollectors
21
+ ##
22
+ # Type Collector for prometheus and grpc instrumentation
23
+ #
24
+ class Grpc < PrometheusExporter::Server::TypeCollector
25
+ ##
26
+ # Initialize the collector
27
+ #
28
+ def initialize
29
+ @pool_jobs_waiting_total = PrometheusExporter::Metric::Gauge.new('grpc_pool_jobs_waiting_total', 'Number jobs in the gRPC thread pool that are actively waiting')
30
+ @pool_ready_workers_total = PrometheusExporter::Metric::Gauge.new('grpc_pool_ready_workers_total', 'The amount of non-busy workers in the thread pool')
31
+ @pool_workers_total = PrometheusExporter::Metric::Gauge.new('grpc_pool_workers_total', 'Number of workers in the gRPC thread pool')
32
+ @pool_initial_size = PrometheusExporter::Metric::Gauge.new('grpc_pool_initial_size', 'Initial size of the gRPC thread pool')
33
+ @poll_period = PrometheusExporter::Metric::Gauge.new('grpc_poll_period', 'Polling period for the gRPC thread pool')
34
+ @thread_pool_exhausted = PrometheusExporter::Metric::Counter.new('grpc_thread_pool_exhausted', 'Times the gRPC thread pool has been exhausted')
35
+ end
36
+
37
+ ##
38
+ # @return [String]
39
+ #
40
+ def type
41
+ 'grpc'
42
+ end
43
+
44
+ ##
45
+ # @return [Array]
46
+ #
47
+ def metrics
48
+ return [] unless @pool_jobs_waiting_total
49
+
50
+ [
51
+ @pool_jobs_waiting_total,
52
+ @pool_ready_workers_total,
53
+ @pool_workers_total,
54
+ @pool_initial_size,
55
+ @poll_period,
56
+ @thread_pool_exhausted
57
+ ]
58
+ end
59
+
60
+ ##
61
+ # Collect the object into the buffer
62
+ #
63
+ def collect(obj)
64
+ default_labels = {}
65
+ default_labels['environment'] = obj['environment'] if obj['environment']
66
+
67
+ custom_labels = obj['custom_labels'] || {}
68
+ labels = custom_labels.nil? ? default_labels : default_labels.merge(custom_labels)
69
+
70
+ @pool_jobs_waiting_total.observe(obj['pool_jobs_waiting_total'], labels)
71
+ @pool_ready_workers_total.observe(obj['pool_ready_workers_total'], labels)
72
+ @pool_workers_total.observe(obj['pool_workers_total'], labels)
73
+ @pool_initial_size.observe(obj['pool_initial_size'], labels)
74
+ @poll_period.observe(obj['poll_period'], labels)
75
+ @thread_pool_exhausted.observe(obj['thread_pool_exhausted'], labels)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Gruf
19
+ module Prometheus
20
+ VERSION = '0.0.2'
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,196 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gruf-prometheus
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Shaun McCormick
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-06-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '10.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '10.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '3.8'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '3.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec_junit_formatter
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0.4'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler-audit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0.6'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0.68'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0.68'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0.16'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0.16'
97
+ - !ruby/object:Gem::Dependency
98
+ name: null-logger
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0.1'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0.1'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0.12'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0.12'
125
+ - !ruby/object:Gem::Dependency
126
+ name: gruf
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '2.7'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '2.7'
139
+ - !ruby/object:Gem::Dependency
140
+ name: prometheus_exporter
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.4'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.4'
153
+ description: Prometheus support for gruf
154
+ email:
155
+ - shaun.mccormick@bigcommerce.com
156
+ executables: []
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - CHANGELOG.md
161
+ - CODE_OF_CONDUCT.md
162
+ - README.md
163
+ - gruf-prometheus.gemspec
164
+ - lib/gruf/prometheus.rb
165
+ - lib/gruf/prometheus/client.rb
166
+ - lib/gruf/prometheus/collectors/grpc.rb
167
+ - lib/gruf/prometheus/configuration.rb
168
+ - lib/gruf/prometheus/hook.rb
169
+ - lib/gruf/prometheus/server.rb
170
+ - lib/gruf/prometheus/type_collectors/grpc.rb
171
+ - lib/gruf/prometheus/version.rb
172
+ homepage: https://github.com/bigcommerce/gruf-prometheus
173
+ licenses:
174
+ - MIT
175
+ metadata: {}
176
+ post_install_message:
177
+ rdoc_options: []
178
+ require_paths:
179
+ - lib
180
+ required_ruby_version: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: '0'
185
+ required_rubygems_version: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ requirements: []
191
+ rubyforge_project:
192
+ rubygems_version: 2.7.9
193
+ signing_key:
194
+ specification_version: 4
195
+ summary: Prometheus support for gruf
196
+ test_files: []