gruf-prometheus 1.3.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +110 -10
- data/gruf-prometheus.gemspec +15 -11
- data/lib/gruf/prometheus.rb +7 -0
- data/lib/gruf/prometheus/client/collector.rb +107 -0
- data/lib/gruf/prometheus/client/interceptor.rb +69 -0
- data/lib/gruf/prometheus/client/type_collector.rb +61 -0
- data/lib/gruf/prometheus/configuration.rb +8 -3
- data/lib/gruf/prometheus/hook.rb +5 -3
- data/lib/gruf/prometheus/request_types.rb +27 -0
- data/lib/gruf/prometheus/server/collector.rb +122 -0
- data/lib/gruf/prometheus/server/interceptor.rb +72 -0
- data/lib/gruf/prometheus/server/type_collector.rb +61 -0
- data/lib/gruf/prometheus/version.rb +1 -1
- metadata +72 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bde4487ef4bd6038fe38578ed17becfa9d8b72e50cc2ed1593d83285e02abf7f
|
4
|
+
data.tar.gz: a5934b48753295219ff703cb5b5d53dcfb3cf4575c6a693444026695f19731db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7bedc3d3375e23ba127364f3c3a1824c0a11403c26e52aa81d7c2a30266e4dfaede052c686020bb4bb66d24f224bdf20668c702e3bc52ec0614e145871798b2d
|
7
|
+
data.tar.gz: 294cd6cc3dd8330fde2af43d86281695e0aa18dabd6c430ba889d05e3b7a2135edc45258bb41b3572ed2b80623c11f77890fcddcc627ee97f3f4c961202c579a
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,10 @@ 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
|
+
|
5
9
|
### 1.3.0
|
6
10
|
|
7
11
|
- Drop Ruby < 2.6 support
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# gruf-prometheus - Prometheus support for gruf
|
2
2
|
|
3
|
-
[](https://circleci.com/gh/bigcommerce/gruf-prometheus/tree/main) [](https://badge.fury.io/rb/gruf-prometheus) [](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,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
|
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
|
data/gruf-prometheus.gemspec
CHANGED
@@ -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
|
-
|
18
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
19
19
|
require 'gruf/prometheus/version'
|
20
20
|
|
21
21
|
Gem::Specification.new do |spec|
|
@@ -33,15 +33,19 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.require_paths = ['lib']
|
34
34
|
spec.required_ruby_version = '>= 2.6'
|
35
35
|
|
36
|
-
|
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'
|
44
|
-
|
45
|
-
spec.add_runtime_dependency 'gruf', '>= 2.7'
|
36
|
+
# Runtime dependencies
|
46
37
|
spec.add_runtime_dependency 'bc-prometheus-ruby', '~> 0.3'
|
38
|
+
spec.add_runtime_dependency 'gruf', '>= 2.7'
|
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
|
data/lib/gruf/prometheus.rb
CHANGED
@@ -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'
|
@@ -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 [
|
45
|
-
# @return [
|
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
|
##
|
data/lib/gruf/prometheus/hook.rb
CHANGED
@@ -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 [
|
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
|
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:
|
4
|
+
version: 2.0.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-
|
11
|
+
date: 2020-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: bc-prometheus-ruby
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: gruf
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - ">="
|
18
32
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
type: :
|
33
|
+
version: '2.7'
|
34
|
+
type: :runtime
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
38
|
- - ">="
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
40
|
+
version: '2.7'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
42
|
+
name: bundler-audit
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - ">="
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
47
|
+
version: '0.6'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - ">="
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
54
|
+
version: '0.6'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
56
|
+
name: pry
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - ">="
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0.
|
61
|
+
version: '0.13'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0.
|
68
|
+
version: '0.13'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
70
|
+
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
73
|
- - ">="
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0
|
75
|
+
version: '13.0'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
80
|
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0
|
82
|
+
version: '13.0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
84
|
+
name: rspec
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
87
|
- - ">="
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
89
|
+
version: '3.10'
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
94
|
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
96
|
+
version: '3.10'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
98
|
+
name: rspec_junit_formatter
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
101
|
- - ">="
|
88
102
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0.
|
103
|
+
version: '0.4'
|
90
104
|
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
108
|
- - ">="
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0.
|
110
|
+
version: '0.4'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
112
|
+
name: rubocop
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
115
|
- - ">="
|
102
116
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
117
|
+
version: '1.1'
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
122
|
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
124
|
+
version: '1.1'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
126
|
+
name: rubocop-packaging
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
|
-
- - "
|
129
|
+
- - "~>"
|
116
130
|
- !ruby/object:Gem::Version
|
117
|
-
version: '0.
|
131
|
+
version: '0.5'
|
118
132
|
type: :development
|
119
133
|
prerelease: false
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
|
-
- - "
|
136
|
+
- - "~>"
|
123
137
|
- !ruby/object:Gem::Version
|
124
|
-
version: '0.
|
138
|
+
version: '0.5'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
140
|
+
name: rubocop-performance
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
|
-
- - "
|
143
|
+
- - "~>"
|
130
144
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
132
|
-
type: :
|
145
|
+
version: '1.8'
|
146
|
+
type: :development
|
133
147
|
prerelease: false
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
|
-
- - "
|
150
|
+
- - "~>"
|
137
151
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
152
|
+
version: '1.8'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
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: :
|
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
|