gruf-prometheus 1.0.1 → 2.0.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: 94521bc11036957fc917248b31bcf494ad3f722623d830eff57150ad66c713ff
4
- data.tar.gz: 8ebd7717b4f6203ecd8ab80d15504536dab599cfd4db0da41a4bd73a25dcd795
3
+ metadata.gz: bde4487ef4bd6038fe38578ed17becfa9d8b72e50cc2ed1593d83285e02abf7f
4
+ data.tar.gz: a5934b48753295219ff703cb5b5d53dcfb3cf4575c6a693444026695f19731db
5
5
  SHA512:
6
- metadata.gz: feba751d2044a89a2d950892d4cbbb94101a3d753eb953a30210f5020f6552871a981720e8052c7461b0298b9e0897536bfae709df9e7b7a4c157c612e1990fb
7
- data.tar.gz: 588f16d8a45586d71adf4223ba308678cd08495177d23483068c4de22c3e6b8c1d140dd5d960f3b4f7a76dca632e410ed809fae6b8a9b0a19d85acd7e4b54a67
6
+ metadata.gz: 7bedc3d3375e23ba127364f3c3a1824c0a11403c26e52aa81d7c2a30266e4dfaede052c686020bb4bb66d24f224bdf20668c702e3bc52ec0614e145871798b2d
7
+ data.tar.gz: 294cd6cc3dd8330fde2af43d86281695e0aa18dabd6c430ba889d05e3b7a2135edc45258bb41b3572ed2b80623c11f77890fcddcc627ee97f3f4c961202c579a
@@ -2,6 +2,30 @@ Changelog for the gruf-prometheus gem.
2
2
 
3
3
  ### Pending Release
4
4
 
5
+ - Add server interceptor for measuring counters/histograms for server metrics
6
+ - Add client interceptor for measuring counters/histograms for client metrics
7
+ - Bump Rubocop to 1.1, remove development dependency on null_logger
8
+
9
+ ### 1.3.0
10
+
11
+ - Drop Ruby < 2.6 support
12
+ - Bump bc-prometheus-ruby dependency to 0.3
13
+ - Adds support for Ruby 2.7
14
+ - Adds help script for testing locally
15
+
16
+ ### 1.2.0
17
+
18
+ - Add the ability to have custom collectors and type collectors
19
+
20
+ ### 1.1.0
21
+
22
+ - Refactor collector/type collector to utilize new base abstractions
23
+ - Bump bc-prometheus-ruby dependency
24
+
25
+ ### 1.0.2
26
+
27
+ - Bump bc-prometheus-ruby dependency
28
+
5
29
  ### 1.0.1
6
30
 
7
31
  - Bump bc-prometheus-ruby dependency
data/README.md CHANGED
@@ -1,6 +1,6 @@
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
5
  Adds Prometheus support for [gruf](https://github.com/bigcommerce/gruf) 2.7.0+.
6
6
 
@@ -24,16 +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
-
37
139
  ## License
38
140
 
39
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,16 +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'
34
35
 
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
-
36
+ # Runtime dependencies
37
+ spec.add_runtime_dependency 'bc-prometheus-ruby', '~> 0.3'
44
38
  spec.add_runtime_dependency 'gruf', '>= 2.7'
45
- spec.add_runtime_dependency 'bc-prometheus-ruby', '~> 0.1.4'
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'
46
51
  end
@@ -27,8 +27,15 @@ require 'bigcommerce/prometheus'
27
27
 
28
28
  require_relative 'prometheus/version'
29
29
  require_relative 'prometheus/configuration'
30
- require_relative 'prometheus/collectors/grpc'
31
- require_relative 'prometheus/type_collectors/grpc'
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'
37
+ require_relative 'prometheus/collector'
38
+ require_relative 'prometheus/type_collector'
32
39
  require_relative 'prometheus/hook'
33
40
 
34
41
  module Gruf
@@ -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