gruf-prometheus 1.3.0 → 2.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: 9125b43ec8d517f1bf324d3d3400f182638f95d74aff3c15aaebdd165ac373da
4
- data.tar.gz: 25a42e807dd8271ee51b1bf034bdffd604d942a2e4ce431942d7b5442a9aa641
3
+ metadata.gz: e4d188e003e056aad2639d57d67d87455f6ee1e579191337a94f8d8234f630c0
4
+ data.tar.gz: 92ebeb27934e4d4966663a70e2c6d4f32ac35571958f582fae1d332d0c390a12
5
5
  SHA512:
6
- metadata.gz: 208c6b8581538e752a792e27677dc28ce6da9169805d823a890848f636588556d526a6bbb0879beda0605133cde09b090226f3f2da85c81867753a090fe2f852
7
- data.tar.gz: 16278ab75bb295ed885aec4f4d641fc4841db3ecb63782b5bc608db22fe56f7ede66d6ecea3f564ec730b563499053129d73c346531dd0fc2ff70a4716a0a7d4
6
+ metadata.gz: 9c2973b859cffa4a72ef328fec5013c4977a28a21eef80098f9abe010b7c2766f771e924ce52342def4a917088cfe686ddc622aa26224cf832b0245718ea152a
7
+ data.tar.gz: 339f3d05134b151167c7af0f59685a669ac5d967d950ddd4e12129712e942664328c518795aaa482d5873377cd5267ddf74e4ae47d9becf75ad418c3502977f0
data/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@ Changelog for the gruf-prometheus gem.
2
2
 
3
3
  ### Pending Release
4
4
 
5
+ ### 2.2.0
6
+
7
+ - Add Ruby 3.1 support
8
+ - Drop support for Ruby 2.6
9
+ - Add CircleCI test suite for Ruby 3.1
10
+
11
+ ### 2.1.0
12
+
13
+ - Add Ruby 3 support
14
+
15
+ ### 2.0.0
16
+
17
+ - Add server interceptor for measuring counters/histograms for server metrics
18
+ - Add client interceptor for measuring counters/histograms for client metrics
19
+ - Bump Rubocop to 1.1, remove development dependency on null_logger
20
+
5
21
  ### 1.3.0
6
22
 
7
23
  - Drop Ruby < 2.6 support
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # gruf-prometheus - Prometheus support for gruf
2
2
 
3
- [![CircleCI](https://circleci.com/gh/bigcommerce/gruf-prometheus/tree/master.svg?style=svg)](https://circleci.com/gh/bigcommerce/gruf-prometheus/tree/master) [![Gem Version](https://badge.fury.io/rb/gruf-prometheus.svg)](https://badge.fury.io/rb/gruf-prometheus) [![Documentation](https://inch-ci.org/github/bigcommerce/gruf-prometheus.svg?branch=master)](https://inch-ci.org/github/bigcommerce/gruf-prometheus?branch=master)
3
+ [![CircleCI](https://circleci.com/gh/bigcommerce/gruf-prometheus/tree/main.svg?style=svg)](https://circleci.com/gh/bigcommerce/gruf-prometheus/tree/main) [![Gem Version](https://badge.fury.io/rb/gruf-prometheus.svg)](https://badge.fury.io/rb/gruf-prometheus) [![Documentation](https://inch-ci.org/github/bigcommerce/gruf-prometheus.svg?branch=main)](https://inch-ci.org/github/bigcommerce/gruf-prometheus?branch=main)
4
4
 
5
- Adds Prometheus support for [gruf](https://github.com/bigcommerce/gruf) 2.7.0+.
5
+ Adds Prometheus support for [gruf](https://github.com/bigcommerce/gruf) 2.7.0+. Supports Ruby 2.7-3.1.
6
6
 
7
7
  ## Installation
8
8
 
@@ -24,18 +24,118 @@ Then `bundle exec gruf` and you'll automatically have prometheus metrics for you
24
24
 
25
25
  The gruf server will by default run on port 9394, and can be scraped at `/metrics`.
26
26
 
27
+ ## Integrations
28
+
29
+ ### System Metrics
30
+
31
+ The gem comes with general system metrics out of the box that illustrate server health/statistics:
32
+
33
+ |Name|Type|Description|
34
+ |---|---|---|
35
+ |ruby_grpc_pool_jobs_waiting_total|gauge|Number of jobs in the gRPC thread pool that are actively waiting|
36
+ |ruby_grpc_pool_ready_workers_total|gauge|The amount of non-busy workers in the thread pool|
37
+ |ruby_grpc_pool_workers_total|gauge|Number of workers in the gRPC thread pool|
38
+ |ruby_grpc_pool_initial_size|gauge|Initial size of the gRPC thread pool|
39
+ |ruby_grpc_poll_period|gauge|Polling period for the gRPC thread pool|
40
+
41
+ ### Server Metrics
42
+
43
+ Furthermore, the server interceptor measures general counts (and optionally, latencies), and can be setup via:
44
+
45
+ ```ruby
46
+ ::Gruf.interceptors.use(::Gruf::Prometheus::Server::Interceptor)
47
+ ```
48
+
49
+ This will output the following metrics:
50
+
51
+ |Name|Type|Description|
52
+ |---|---|---|
53
+ |ruby_grpc_server_started_total|counter|Total number of RPCs started on the server|
54
+ |ruby_grpc_server_handled_total|counter|Total number of RPCs completed on the server, regardless of success or failure|
55
+ |ruby_grpc_server_handled_latency_seconds|histogram|Histogram of response latency of RPCs handled by the server, in seconds|
56
+
57
+ Note that the histogram is disabled by default - you'll have to turn it on either through the `server_measure_latency`
58
+ configuration yielded in `Gruf::Prometheus.configure`, or through the `PROMETHEUS_SERVER_MEASURE_LATENCY` environment
59
+ variable. Also, the `measure_latency: true` option can be passed as a second argument to `Gruf.interceptors.use` to
60
+ configure this directly in the interceptor.
61
+
62
+ The precedence order for this is, from first to last, with last taking precedence:
63
+ 1) `measure_latency: true` passed into the interceptor
64
+ 2) `Gruf::Prometheus.configure` explicit setting globally
65
+ 3) `PROMETHEUS_SERVER_MEASURE_LATENCY` ENV var globally. This is the only value set by default - to `false` - and will
66
+ be the default unless other methods are invoked.
67
+
68
+ ### Client Metrics
69
+
70
+ gruf-prometheus can also measure gruf client timings, via the interceptor:
71
+
72
+ ```ruby
73
+ Gruf::Client.new(
74
+ service: MyService,
75
+ client_options: {
76
+ interceptors: [Gruf::Prometheus::Client::Interceptor.new]
77
+ }
78
+ )
79
+ ```
80
+
81
+ |Name|Type|Description|
82
+ |---|---|---|
83
+ |ruby_grpc_client_started_total|counter|Total number of RPCs started by the client|
84
+ |ruby_grpc_client_completed|counter|Total number of RPCs completed by the client, regardless of success or failure|
85
+ |ruby_grpc_client_completed_latency_seconds|histogram|Histogram of response latency of RPCs completed by the client, in seconds|
86
+
87
+ Note that the histogram is disabled by default - you'll have to turn it on either through the `client_measure_latency`
88
+ configuration yielded in `Gruf::Prometheus.configure`, or through the `PROMETHEUS_CLIENT_MEASURE_LATENCY` environment
89
+ variable. Optionally, you can pass in `measure_latency: true` into the Interceptor directly as an option argument in the
90
+ initializer.
91
+
92
+ The precedence order for this is, from first to last, with last taking precedence:
93
+ 1) `measure_latency: true` passed into the interceptor
94
+ 2) `Gruf::Prometheus.configure` explicit setting globally
95
+ 3) `PROMETHEUS_CLIENT_MEASURE_LATENCY` ENV var globally. This is the only value set by default - to `false` - and will
96
+ be the default unless other methods are invoked.
97
+
98
+ ### Running the Client Interceptor in Non-gRPC Processes
99
+
100
+ One caveat is that you _must_ have the appropriate Type Collector setup in whatever process you are running in. If
101
+ you are already doing this in a gruf gRPC service that is using the hook provided by this gem above, no further
102
+ configuration is needed. Otherwise, in whatever bc-prometheus-ruby configuration you have setup, you'll need to ensure
103
+ the type collector is loaded:
104
+
105
+ ```ruby
106
+ # prometheus_server is whatever `::Bigcommerce::Prometheus::Server` instance you are using in the current process
107
+ # Often hooks into these are exposed as configuration options, e.g. `web_collectors`, `resque_collectors`, etc
108
+ prometheus_server.add_type_collector(::Gruf::Prometheus::Client::TypeCollector.new)
109
+ ```
110
+
111
+ Note that you don't need to do this for the `Gruf::Prometheus::Client::Collector`, as it is an on-demand collector
112
+ that does not run in a threaded loop.
113
+
114
+ See [bc-prometheus-ruby](https://github.com/bigcommerce/bc-prometheus-ruby#custom-server-integrations)'s documentation
115
+ on custom server integrations for more information.
116
+
27
117
  ## Configuration
28
118
 
29
- You can further configure via bc-prometheus-ruby with:
119
+ You can further configure `Gruf::Prometheus` globally using the block syntax:
120
+
121
+ ```ruby
122
+ Gruf::Prometheus.configure do |config|
123
+ # config here
124
+ end
125
+ ```
126
+
127
+ where the options available are:
128
+
129
+ | Option | Description | Default | ENV Name |
130
+ | ------ | ----------- | ------- | -------- |
131
+ | process_label | The label to use for metric prefixing | grpc | PROMETHEUS_PROCESS_LABEL |
132
+ | process_name | Label to use for process name in logging | grpc | PROMETHEUS_PROCESS_NAME |
133
+ | collection_frequency | The period in seconds in which to collect metrics | 30 | PROMETHEUS_COLLECTION_FREQUENCY |
134
+ | collectors | Any collectors you would like to start with the server. Passed as a hash of collector class => options | {} | |
135
+ | type_collectors | Any type collectors you would like to start with the server. Passed as an array of collector objects | [] | |
136
+ | server_measure_latency| Whether or not to measure latency as a histogram for servers | 0 | PROMETHEUS_SERVER_MEASURE_LATENCY |
137
+ | client_measure_latency| Whether or not to measure latency as a histogram for clients | 0 | PROMETHEUS_CLIENT_MEASURE_LATENCY |
30
138
 
31
- | Option | Description | Default |
32
- | ------ | ----------- | ------- |
33
- | process_label | The label to use for metric prefixing | grpc |
34
- | process_name | Label to use for process name in logging | grpc |
35
- | collection_frequency | The period in seconds in which to collect metrics | 30 |
36
- | collectors | Any collectors you would like to start with the server. Passed as a hash of collector class => options | {} |
37
- | type_collectors | Any type collectors you would like to start with the server. Passed as an array of collector objects | [] |
38
-
39
139
  ## License
40
140
 
41
141
  Copyright (c) 2019-present, BigCommerce Pty. Ltd. All rights reserved
@@ -15,7 +15,7 @@
15
15
  # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
16
  # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
17
  #
18
- $:.push File.expand_path('../lib', __FILE__)
18
+ $LOAD_PATH.push File.expand_path('lib', __dir__)
19
19
  require 'gruf/prometheus/version'
20
20
 
21
21
  Gem::Specification.new do |spec|
@@ -31,17 +31,21 @@ Gem::Specification.new do |spec|
31
31
 
32
32
  spec.files = Dir['README.md', 'CHANGELOG.md', 'CODE_OF_CONDUCT.md', 'lib/**/*', 'gruf-prometheus.gemspec']
33
33
  spec.require_paths = ['lib']
34
- spec.required_ruby_version = '>= 2.6'
35
-
36
- spec.add_development_dependency 'rake', '>= 10.0'
37
- spec.add_development_dependency 'rspec', '>= 3.8'
38
- spec.add_development_dependency 'rspec_junit_formatter', '>= 0.4'
39
- spec.add_development_dependency 'bundler-audit', '>= 0.6'
40
- spec.add_development_dependency 'rubocop', '>= 0.68'
41
- spec.add_development_dependency 'simplecov', '>= 0.16'
42
- spec.add_development_dependency 'null-logger', '>= 0.1'
43
- spec.add_development_dependency 'pry', '>= 0.12'
34
+ spec.required_ruby_version = '>= 2.7', '< 4'
44
35
 
36
+ # Runtime dependencies
37
+ spec.add_runtime_dependency 'bc-prometheus-ruby', '>= 0.5.1'
45
38
  spec.add_runtime_dependency 'gruf', '>= 2.7'
46
- spec.add_runtime_dependency 'bc-prometheus-ruby', '~> 0.3'
39
+
40
+ # Development dependencies
41
+ spec.add_development_dependency 'bundler-audit', '>= 0.6'
42
+ spec.add_development_dependency 'pry', '>= 0.13'
43
+ spec.add_development_dependency 'rake', '>= 13.0'
44
+ spec.add_development_dependency 'rspec', '>= 3.10'
45
+ spec.add_development_dependency 'rspec_junit_formatter', '>= 0.4'
46
+ spec.add_development_dependency 'rubocop', '>= 1.1'
47
+ spec.add_development_dependency 'rubocop-packaging', '~> 0.5'
48
+ spec.add_development_dependency 'rubocop-performance', '~> 1.8'
49
+ spec.add_development_dependency 'rubocop-thread_safety', '~> 0.3'
50
+ spec.add_development_dependency 'simplecov', '>= 0.19'
47
51
  end
@@ -0,0 +1,107 @@
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 Client
21
+ ##
22
+ # Prometheus instrumentor for gRPC clients
23
+ #
24
+ class Collector < Bigcommerce::Prometheus::Collectors::Base
25
+ RESPONSE_CODE_OK = 'OK'
26
+
27
+ ##
28
+ # @param [Gruf::Outbound::RequestContext] request_context
29
+ #
30
+ def started_total(request_context:)
31
+ push(
32
+ grpc_client_started_total: 1,
33
+ custom_labels: custom_labels(request_context: request_context)
34
+ )
35
+ end
36
+
37
+ ##
38
+ # @param [Gruf::Controller::RequestContext] request_context
39
+ # @param [Gruf::Interceptors::Timer::Result] result
40
+ #
41
+ def completed(request_context:, result:)
42
+ push(
43
+ grpc_client_completed: 1,
44
+ custom_labels: custom_labels(request_context: request_context, result: result)
45
+ )
46
+ end
47
+
48
+ ##
49
+ # @param [Gruf::Outbound::RequestContext] request_context
50
+ # @param [Gruf::Interceptors::Timer::Result] result
51
+ #
52
+ def completed_latency_seconds(request_context:, result:)
53
+ push(
54
+ grpc_client_completed_latency_seconds: result.elapsed.to_f,
55
+ custom_labels: custom_labels(request_context: request_context, result: result)
56
+ )
57
+ end
58
+
59
+ private
60
+
61
+ ##
62
+ # @param [Gruf::Outbound::RequestContext] request_context
63
+ # @param [Gruf::Interceptors::Timer::Result|NilClass] result
64
+ # @return [Hash]
65
+ #
66
+ def custom_labels(request_context:, result: nil)
67
+ labels = {
68
+ grpc_service: format_service_name(request_context.method.to_s),
69
+ grpc_method: request_context.method_name,
70
+ grpc_type: determine_type(request_context)
71
+ }
72
+ if result
73
+ labels[:grpc_code] = result.successful? ? RESPONSE_CODE_OK : result.message_class_name.split('::').last
74
+ end
75
+ labels
76
+ end
77
+
78
+ ##
79
+ # Format the service name as `path.to.Service` (from `/path.to.Service/MethodName`)
80
+ #
81
+ # @param [String] name
82
+ # @return [String]
83
+ #
84
+ def format_service_name(name)
85
+ name.split('/').reject(&:empty?).first
86
+ end
87
+
88
+ ##
89
+ # @param [Gruf::Outbound::RequestContext] request_context
90
+ # @return [String]
91
+ #
92
+ def determine_type(request_context)
93
+ case request_context.type.to_sym
94
+ when :client_streamer
95
+ Gruf::Prometheus::RequestTypes::CLIENT_STREAM
96
+ when :server_streamer
97
+ Gruf::Prometheus::RequestTypes::SERVER_STREAM
98
+ when :bidi_streamer
99
+ Gruf::Prometheus::RequestTypes::BIDI_STREAM
100
+ else
101
+ Gruf::Prometheus::RequestTypes::UNARY
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,69 @@
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 Client
21
+ ##
22
+ # Server interceptor for measuring counter/timers for gRPC inbound requests
23
+ #
24
+ class Interceptor < ::Gruf::Interceptors::ClientInterceptor
25
+ ##
26
+ # Intercept the call and send metrics
27
+ #
28
+ def call(request_context:, &block)
29
+ result = ::Gruf::Interceptors::Timer.time(&block)
30
+
31
+ send_metrics(request_context: request_context, result: result)
32
+
33
+ raise result.message unless result.successful?
34
+
35
+ result.message
36
+ end
37
+
38
+ private
39
+
40
+ ##
41
+ # @param [Gruf::Outbound::RequestContext] request_context
42
+ # @param [Gruf::Interceptors::Timer::Result] result
43
+ #
44
+ def send_metrics(request_context:, result:)
45
+ prometheus_collector.started_total(request_context: request_context)
46
+ prometheus_collector.completed(request_context: request_context, result: result)
47
+ prometheus_collector.completed_latency_seconds(request_context: request_context, result: result) if measure_latency?
48
+ rescue StandardError => e
49
+ # we don't want this to affect actual RPC execution, so just log an error and move on
50
+ Gruf.logger.error "Failed registering metric to prometheus type collector: #{e.message} - #{e.class.name}"
51
+ end
52
+
53
+ ##
54
+ # @return [::Gruf::Prometheus::Client::Collector]
55
+ #
56
+ def prometheus_collector
57
+ @prometheus_collector ||= ::Gruf::Prometheus::Client::Collector.new(type: 'grpc_client')
58
+ end
59
+
60
+ ##
61
+ # @return [Boolean]
62
+ #
63
+ def measure_latency?
64
+ @measure_latency ||= @options.fetch(:measure_latency, ::Gruf::Prometheus.client_measure_latency)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,61 @@
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 Client
21
+ ##
22
+ # Type Collector for grpc client metrics
23
+ #
24
+ class TypeCollector < Bigcommerce::Prometheus::TypeCollectors::Base
25
+ def type
26
+ 'grpc_client'
27
+ end
28
+
29
+ private
30
+
31
+ ##
32
+ # Initialize the collector
33
+ #
34
+ def build_metrics
35
+ metrics = {
36
+ grpc_client_started_total: PrometheusExporter::Metric::Counter.new('grpc_client_started_total', 'Total number of RPCs started by the client'),
37
+ grpc_client_completed: PrometheusExporter::Metric::Counter.new('grpc_client_completed', 'Total number of RPCs completed by the client, regardless of success or failure')
38
+ }
39
+ metrics[:grpc_client_completed_latency_seconds] = PrometheusExporter::Metric::Histogram.new('grpc_client_completed_latency_seconds', 'Histogram of response latency of RPCs completed by the client, in seconds') if measure_latency?
40
+ metrics
41
+ end
42
+
43
+ ##
44
+ # Collect the object into the buffer
45
+ #
46
+ def collect_metrics(data: {}, labels: {})
47
+ metric(:grpc_client_started_total)&.observe(data['grpc_client_started_total'].to_i, labels)
48
+ metric(:grpc_client_completed)&.observe(data['grpc_client_completed'].to_i, labels)
49
+ metric(:grpc_client_completed_latency_seconds)&.observe(data['grpc_client_completed_latency_seconds'].to_f, labels) if measure_latency?
50
+ end
51
+
52
+ ##
53
+ # @return [Boolean]
54
+ #
55
+ def measure_latency?
56
+ @measure_latency ||= ::Gruf::Prometheus.client_measure_latency
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -26,7 +26,9 @@ module Gruf
26
26
  process_name: 'grpc',
27
27
  collection_frequency: 30,
28
28
  type_collectors: [],
29
- collectors: []
29
+ collectors: [],
30
+ client_measure_latency: false,
31
+ server_measure_latency: false
30
32
  }.freeze
31
33
 
32
34
  attr_accessor *VALID_CONFIG_KEYS.keys
@@ -41,13 +43,14 @@ module Gruf
41
43
  ##
42
44
  # Yield self for ruby-style initialization
43
45
  #
44
- # @yields [Bigcommerce::Prometheus::Configuration]
45
- # @return [Bigcommerce::Prometheus::Configuration]
46
+ # @yields [Gruf::Prometheus::Configuration]
47
+ # @return [Gruf::Prometheus::Configuration]
46
48
  #
47
49
  def configure
48
50
  reset unless @configured
49
51
  yield self
50
52
  @configured = true
53
+ self
51
54
  end
52
55
 
53
56
  ##
@@ -73,6 +76,8 @@ module Gruf
73
76
  self.process_label = ENV.fetch('PROMETHEUS_PROCESS_LABEL', 'grpc').to_s
74
77
  self.process_name = ENV.fetch('PROMETHEUS_PROCESS_NAME', 'grpc').to_s
75
78
  self.collection_frequency = ENV.fetch('PROMETHEUS_COLLECTION_FREQUENCY', 30).to_i
79
+ self.server_measure_latency = ENV.fetch('PROMETHEUS_SERVER_MEASURE_LATENCY', 0).to_i.positive?
80
+ self.client_measure_latency = ENV.fetch('PROMETHEUS_CLIENT_MEASURE_LATENCY', 0).to_i.positive?
76
81
  end
77
82
 
78
83
  ##
@@ -29,6 +29,8 @@ module Gruf
29
29
  def before_server_start(server:)
30
30
  logger.info "[gruf-prometheus][#{::Gruf::Prometheus.process_name}] Starting #{server.class}"
31
31
  prometheus_server.add_type_collector(::Gruf::Prometheus::TypeCollector.new)
32
+ prometheus_server.add_type_collector(::Gruf::Prometheus::Server::TypeCollector.new)
33
+ prometheus_server.add_type_collector(::Gruf::Prometheus::Client::TypeCollector.new)
32
34
  prometheus_server.add_type_collector(::PrometheusExporter::Server::ActiveRecordCollector.new)
33
35
  custom_type_collectors.each do |tc|
34
36
  prometheus_server.add_type_collector(tc)
@@ -83,7 +85,7 @@ module Gruf
83
85
  end
84
86
 
85
87
  ##
86
- # @return [Gruf::Prometheus::Server]
88
+ # @return [Bigcommerce::Prometheus::Server]
87
89
  #
88
90
  def prometheus_server
89
91
  @prometheus_server ||= ::Bigcommerce::Prometheus::Server.new(
@@ -99,14 +101,14 @@ module Gruf
99
101
  # @return [Array<Bigcommerce::Prometheus::TypeCollectors::Base>]
100
102
  #
101
103
  def custom_type_collectors
102
- @options.fetch(:type_collectors, [])
104
+ @options.fetch(:type_collectors, []) || []
103
105
  end
104
106
 
105
107
  ##
106
108
  # @return [Array<Bigcommerce::Prometheus::Collectors::Base>]
107
109
  #
108
110
  def custom_collectors
109
- @options.fetch(:collectors, [])
111
+ @options.fetch(:collectors, []) || []
110
112
  end
111
113
  end
112
114
  end
@@ -0,0 +1,27 @@
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 RequestTypes
21
+ UNARY = 'UNARY'
22
+ CLIENT_STREAM = 'CLIENT_STREAM'
23
+ SERVER_STREAM = 'SERVER_STREAM'
24
+ BIDI_STREAM = 'BIDI_STREAM'
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,122 @@
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 Server
21
+ ##
22
+ # Prometheus instrumentor for gRPC servers
23
+ #
24
+ class Collector < Bigcommerce::Prometheus::Collectors::Base
25
+ RESPONSE_CODE_OK = 'OK'
26
+
27
+ ##
28
+ # @param [Gruf::Controller::Request] request
29
+ #
30
+ def started_total(request:)
31
+ push(
32
+ grpc_server_started_total: 1,
33
+ custom_labels: custom_labels(request: request)
34
+ )
35
+ end
36
+
37
+ ##
38
+ # @param [Gruf::Controller::Request] request
39
+ # @param [Gruf::Interceptors::Timer::Result] result:party
40
+ #
41
+ def handled_total(request:, result:)
42
+ push(
43
+ grpc_server_handled_total: 1,
44
+ custom_labels: custom_labels(request: request, result: result)
45
+ )
46
+ end
47
+
48
+ ##
49
+ # @param [Gruf::Controller::Request] request
50
+ # @param [Gruf::Interceptors::Timer::Result] result
51
+ #
52
+ def handled_latency_seconds(request:, result:)
53
+ push(
54
+ grpc_server_handled_latency_seconds: result.elapsed.to_f,
55
+ custom_labels: custom_labels(request: request, result: result)
56
+ )
57
+ end
58
+
59
+ private
60
+
61
+ ##
62
+ # @param [Gruf::Controller::Request] request
63
+ # @param [Gruf::Interceptors::Timer::Result|NilClass] result
64
+ # @return [Hash]
65
+ #
66
+ def custom_labels(request:, result: nil)
67
+ labels = {
68
+ grpc_service: format_grpc_service_name(request.service.name.to_s),
69
+ grpc_method: format_grpc_method_name(request.method_key.to_s),
70
+ grpc_type: determine_type(request)
71
+ }
72
+ if result
73
+ labels[:grpc_code] = result.successful? ? RESPONSE_CODE_OK : result.message_class_name.split('::').last
74
+ end
75
+ labels
76
+ end
77
+
78
+ ##
79
+ # Format the service name as `path.to.Service` (from Path::To::Service)
80
+ #
81
+ # @param [String] name
82
+ # @return [String]
83
+ #
84
+ def format_grpc_service_name(name)
85
+ parts = name.split('::')
86
+ return '' unless parts.any?
87
+
88
+ svc = parts.pop.to_s
89
+ parts.map!(&:downcase)
90
+ parts << svc
91
+ parts.join('.')
92
+ end
93
+
94
+ ##
95
+ # Format the method name as `MethodName` (from method_name)
96
+ #
97
+ # @param [String] name
98
+ # @return [String]
99
+ #
100
+ def format_grpc_method_name(name)
101
+ name.split('_').map(&:capitalize).join
102
+ end
103
+
104
+ ##
105
+ # @param [Gruf::Controller::Request] request
106
+ # @return [String]
107
+ #
108
+ def determine_type(request)
109
+ if request.client_streamer?
110
+ Gruf::Prometheus::RequestTypes::CLIENT_STREAM
111
+ elsif request.server_streamer?
112
+ Gruf::Prometheus::RequestTypes::SERVER_STREAM
113
+ elsif request.bidi_streamer?
114
+ Gruf::Prometheus::RequestTypes::BIDI_STREAM
115
+ else
116
+ Gruf::Prometheus::RequestTypes::UNARY
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,72 @@
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 Server
21
+ ##
22
+ # Server interceptor for measuring counter/timers for gRPC inbound requests
23
+ #
24
+ class Interceptor < ::Gruf::Interceptors::ServerInterceptor
25
+ ##
26
+ # Intercept the call and send metrics
27
+ #
28
+ def call(&block)
29
+ result = ::Gruf::Interceptors::Timer.time(&block)
30
+
31
+ send_metrics(result)
32
+
33
+ raise result.message unless result.successful?
34
+
35
+ result.message
36
+ end
37
+
38
+ private
39
+
40
+ ##
41
+ # @param [Gruf::Interceptors::Timer::Result] result
42
+ #
43
+ def send_metrics(result)
44
+ prometheus_collector.started_total(request: request)
45
+ prometheus_collector.handled_total(request: request, result: result)
46
+ prometheus_collector.handled_latency_seconds(request: request, result: result) if measure_latency?
47
+ rescue StandardError => e
48
+ # we don't want this to affect actual RPC execution, so just log an error and move on
49
+ Gruf.logger.error "Failed registering metric to prometheus type collector: #{e.message} - #{e.class.name}"
50
+ end
51
+
52
+ ##
53
+ # @return [::Gruf::Prometheus::Server::Collector]
54
+ #
55
+ def prometheus_collector
56
+ @prometheus_collector ||= ::Gruf::Prometheus::Server::Collector.new(type: 'grpc_server')
57
+ end
58
+
59
+ ##
60
+ # @return [Boolean]
61
+ #
62
+ def measure_latency?
63
+ unless @measure_latency
64
+ v = @options.fetch(:measure_latency, ::Gruf::Prometheus.server_measure_latency)
65
+ @measure_latency = v.nil? ? false : v
66
+ end
67
+ @measure_latency
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,61 @@
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 Server
21
+ ##
22
+ # Type Collector for grpc server metrics
23
+ #
24
+ class TypeCollector < Bigcommerce::Prometheus::TypeCollectors::Base
25
+ def type
26
+ 'grpc_server'
27
+ end
28
+
29
+ private
30
+
31
+ ##
32
+ # Initialize the collector
33
+ #
34
+ def build_metrics
35
+ metrics = {
36
+ grpc_server_started_total: PrometheusExporter::Metric::Counter.new('grpc_server_started_total', 'Total number of RPCs started on the server'),
37
+ grpc_server_handled_total: PrometheusExporter::Metric::Counter.new('grpc_server_handled_total', 'Total number of RPCs completed on the server, regardless of success or failure')
38
+ }
39
+ metrics[:grpc_server_handled_latency_seconds] = PrometheusExporter::Metric::Histogram.new('grpc_server_handled_latency_seconds', 'Histogram of response latency of RPCs handled by the server, in seconds') if measure_latency?
40
+ metrics
41
+ end
42
+
43
+ ##
44
+ # Collect the object into the buffer
45
+ #
46
+ def collect_metrics(data: {}, labels: {})
47
+ metric(:grpc_server_started_total)&.observe(data['grpc_server_started_total'].to_i, labels)
48
+ metric(:grpc_server_handled_total)&.observe(data['grpc_server_handled_total'].to_i, labels)
49
+ metric(:grpc_server_handled_latency_seconds)&.observe(data['grpc_server_handled_latency_seconds'].to_f, labels) if measure_latency?
50
+ end
51
+
52
+ ##
53
+ # @return [Boolean]
54
+ #
55
+ def measure_latency?
56
+ @measure_latency ||= ::Gruf::Prometheus.server_measure_latency
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -17,6 +17,6 @@
17
17
  #
18
18
  module Gruf
19
19
  module Prometheus
20
- VERSION = '1.3.0'
20
+ VERSION = '2.2.0'
21
21
  end
22
22
  end
@@ -27,6 +27,13 @@ require 'bigcommerce/prometheus'
27
27
 
28
28
  require_relative 'prometheus/version'
29
29
  require_relative 'prometheus/configuration'
30
+ require_relative 'prometheus/request_types'
31
+ require_relative 'prometheus/server/collector'
32
+ require_relative 'prometheus/server/interceptor'
33
+ require_relative 'prometheus/server/type_collector'
34
+ require_relative 'prometheus/client/collector'
35
+ require_relative 'prometheus/client/interceptor'
36
+ require_relative 'prometheus/client/type_collector'
30
37
  require_relative 'prometheus/collector'
31
38
  require_relative 'prometheus/type_collector'
32
39
  require_relative 'prometheus/hook'
metadata CHANGED
@@ -1,155 +1,183 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gruf-prometheus
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shaun McCormick
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-18 00:00:00.000000000 Z
11
+ date: 2022-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rake
14
+ name: bc-prometheus-ruby
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '10.0'
20
- type: :development
19
+ version: 0.5.1
20
+ type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '10.0'
26
+ version: 0.5.1
27
27
  - !ruby/object:Gem::Dependency
28
- name: rspec
28
+ name: gruf
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '3.8'
34
- type: :development
33
+ version: '2.7'
34
+ type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '3.8'
40
+ version: '2.7'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec_junit_formatter
42
+ name: bundler-audit
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0.4'
47
+ version: '0.6'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '0.4'
54
+ version: '0.6'
55
55
  - !ruby/object:Gem::Dependency
56
- name: bundler-audit
56
+ name: pry
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '0.6'
61
+ version: '0.13'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '0.6'
68
+ version: '0.13'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rubocop
70
+ name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '0.68'
75
+ version: '13.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '0.68'
82
+ version: '13.0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: simplecov
84
+ name: rspec
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '0.16'
89
+ version: '3.10'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: '0.16'
96
+ version: '3.10'
97
97
  - !ruby/object:Gem::Dependency
98
- name: null-logger
98
+ name: rspec_junit_formatter
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: '0.1'
103
+ version: '0.4'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: '0.1'
110
+ version: '0.4'
111
111
  - !ruby/object:Gem::Dependency
112
- name: pry
112
+ name: rubocop
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: '0.12'
117
+ version: '1.1'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: '0.12'
124
+ version: '1.1'
125
125
  - !ruby/object:Gem::Dependency
126
- name: gruf
126
+ name: rubocop-packaging
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ">="
129
+ - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '2.7'
132
- type: :runtime
131
+ version: '0.5'
132
+ type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ">="
136
+ - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '2.7'
138
+ version: '0.5'
139
139
  - !ruby/object:Gem::Dependency
140
- name: bc-prometheus-ruby
140
+ name: rubocop-performance
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '1.8'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '1.8'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop-thread_safety
141
155
  requirement: !ruby/object:Gem::Requirement
142
156
  requirements:
143
157
  - - "~>"
144
158
  - !ruby/object:Gem::Version
145
159
  version: '0.3'
146
- type: :runtime
160
+ type: :development
147
161
  prerelease: false
148
162
  version_requirements: !ruby/object:Gem::Requirement
149
163
  requirements:
150
164
  - - "~>"
151
165
  - !ruby/object:Gem::Version
152
166
  version: '0.3'
167
+ - !ruby/object:Gem::Dependency
168
+ name: simplecov
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0.19'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0.19'
153
181
  description: Prometheus support for gruf
154
182
  email:
155
183
  - shaun.mccormick@bigcommerce.com
@@ -162,9 +190,16 @@ files:
162
190
  - README.md
163
191
  - gruf-prometheus.gemspec
164
192
  - lib/gruf/prometheus.rb
193
+ - lib/gruf/prometheus/client/collector.rb
194
+ - lib/gruf/prometheus/client/interceptor.rb
195
+ - lib/gruf/prometheus/client/type_collector.rb
165
196
  - lib/gruf/prometheus/collector.rb
166
197
  - lib/gruf/prometheus/configuration.rb
167
198
  - lib/gruf/prometheus/hook.rb
199
+ - lib/gruf/prometheus/request_types.rb
200
+ - lib/gruf/prometheus/server/collector.rb
201
+ - lib/gruf/prometheus/server/interceptor.rb
202
+ - lib/gruf/prometheus/server/type_collector.rb
168
203
  - lib/gruf/prometheus/type_collector.rb
169
204
  - lib/gruf/prometheus/version.rb
170
205
  homepage: https://github.com/bigcommerce/gruf-prometheus
@@ -179,14 +214,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
179
214
  requirements:
180
215
  - - ">="
181
216
  - !ruby/object:Gem::Version
182
- version: '2.6'
217
+ version: '2.7'
218
+ - - "<"
219
+ - !ruby/object:Gem::Version
220
+ version: '4'
183
221
  required_rubygems_version: !ruby/object:Gem::Requirement
184
222
  requirements:
185
223
  - - ">="
186
224
  - !ruby/object:Gem::Version
187
225
  version: '0'
188
226
  requirements: []
189
- rubygems_version: 3.0.6
227
+ rubygems_version: 3.3.7
190
228
  signing_key:
191
229
  specification_version: 4
192
230
  summary: Prometheus support for gruf