prometheus_client_addons 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +273 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/prometheus_client_addons.rb +9 -0
- data/lib/prometheus_client_addons/prometheus/client/active_record.rb +34 -0
- data/lib/prometheus_client_addons/prometheus/client/custom_collector.rb +26 -0
- data/lib/prometheus_client_addons/prometheus/client/fake_gauge.rb +17 -0
- data/lib/prometheus_client_addons/prometheus/client/formats/text_extended.rb +48 -0
- data/lib/prometheus_client_addons/prometheus/client/gc.rb +54 -0
- data/lib/prometheus_client_addons/prometheus/client/multi_metric.rb +38 -0
- data/lib/prometheus_client_addons/prometheus/client/puma.rb +97 -0
- data/lib/prometheus_client_addons/puma/plugin/prometheus_client_addons.rb +19 -0
- data/lib/prometheus_client_addons/version.rb +3 -0
- data/prometheus_client_addons.gemspec +38 -0
- metadata +136 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e92df93c0d837d7a85176aaf94e7c954f4eb1de51e0f0f7f87341414514e614b
|
4
|
+
data.tar.gz: 80329fa945177a4acabfca5be1caacfc4f57b6dcbc6d567a8a92bd6f14391d57
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fb58dc08009041432e37ff55b1e3a14cbbb36ee9545154671ad1ea1dae62bfece3544c016601c49348984c7da12878e10e9d6adfefa04179446e7b5849981eb0
|
7
|
+
data.tar.gz: df185a4b8b278471a3c4e49d9e96e17daca4050e5eb3a34548589b96721425507b03ee227eeea2c2fd0a9173178e66e8b62e903353b65ece62308b8e333c4f9f
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 kraaaken
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,273 @@
|
|
1
|
+
# Prometheus Ruby Client Addons
|
2
|
+
|
3
|
+
## Usage (with Rails)
|
4
|
+
|
5
|
+
### Puma server
|
6
|
+
|
7
|
+
config/initializers/prometheus.rb
|
8
|
+
```ruby
|
9
|
+
require 'prometheus/client'
|
10
|
+
require 'prometheus_client_addons'
|
11
|
+
|
12
|
+
prometheus = Prometheus::Client.registry
|
13
|
+
puma = PrometheusClientAddons::Prometheus::Client::Puma.new(
|
14
|
+
prefix: 'puma',
|
15
|
+
base_labels: { my_label: 'baz' }
|
16
|
+
)
|
17
|
+
prometheus.register(puma)
|
18
|
+
```
|
19
|
+
|
20
|
+
config/puma.rb
|
21
|
+
```ruby
|
22
|
+
activate_control_app('auto')
|
23
|
+
plugin :prometheus_client_addons
|
24
|
+
```
|
25
|
+
|
26
|
+
Example response in non-clustered mode
|
27
|
+
```
|
28
|
+
# TYPE puma_backlog gauge
|
29
|
+
# HELP puma_backlog How many requests are waiting
|
30
|
+
puma_backlog{my_label="baz"} 0
|
31
|
+
# TYPE puma_running gauge
|
32
|
+
# HELP puma_running Number of running threads
|
33
|
+
puma_running{my_label="baz"} 5
|
34
|
+
# TYPE puma_pool_capacity gauge
|
35
|
+
# HELP puma_pool_capacity Number of requests that can be processed right now
|
36
|
+
puma_pool_capacity{my_label="baz"} 4
|
37
|
+
# TYPE puma_max_threads gauge
|
38
|
+
# HELP puma_max_threads Maximum number of worker threads
|
39
|
+
puma_max_threads{my_label="baz"} 5
|
40
|
+
```
|
41
|
+
|
42
|
+
Example response in clustered mode
|
43
|
+
```
|
44
|
+
# TYPE puma_workers gauge
|
45
|
+
# HELP puma_workers Number of workers
|
46
|
+
puma_workers{my_label="baz"} 2
|
47
|
+
# TYPE puma_phase gauge
|
48
|
+
# HELP puma_phase Phase of worker
|
49
|
+
puma_phase{my_label="baz"} 0
|
50
|
+
# TYPE puma_booted_workers gauge
|
51
|
+
# HELP puma_booted_workers Number of booted workers
|
52
|
+
puma_booted_workers{my_label="baz"} 2
|
53
|
+
# TYPE puma_old_workers gauge
|
54
|
+
# HELP puma_old_workers Number of old workers
|
55
|
+
puma_old_workers{my_label="baz"} 0
|
56
|
+
# TYPE puma_worker_status_phase gauge
|
57
|
+
# HELP puma_worker_status_phase Phase of worker
|
58
|
+
puma_worker_status_phase{my_label="baz",worker_index="0"} 0
|
59
|
+
puma_worker_status_phase{my_label="baz",worker_index="1"} 0
|
60
|
+
# TYPE puma_worker_status_booted gauge
|
61
|
+
# HELP puma_worker_status_booted Booted or not
|
62
|
+
puma_worker_status_booted{my_label="baz",worker_index="0"} true
|
63
|
+
puma_worker_status_booted{my_label="baz",worker_index="1"} true
|
64
|
+
# TYPE puma_worker_status_last_checkin gauge
|
65
|
+
# HELP puma_worker_status_last_checkin Last update
|
66
|
+
puma_worker_status_last_checkin{my_label="baz",worker_index="0"} 2019-09-04T15:01:33Z
|
67
|
+
puma_worker_status_last_checkin{my_label="baz",worker_index="1"} 2019-09-04T15:01:33Z
|
68
|
+
# TYPE puma_worker_status_last_status_backlog gauge
|
69
|
+
# HELP puma_worker_status_last_status_backlog How many objects have yet to be processed by the pool
|
70
|
+
puma_worker_status_last_status_backlog{my_label="baz",worker_index="0"} 0
|
71
|
+
puma_worker_status_last_status_backlog{my_label="baz",worker_index="1"} 0
|
72
|
+
# TYPE puma_worker_status_last_status_running gauge
|
73
|
+
# HELP puma_worker_status_last_status_running Number of running threads
|
74
|
+
puma_worker_status_last_status_running{my_label="baz",worker_index="0"} 5
|
75
|
+
puma_worker_status_last_status_running{my_label="baz",worker_index="1"} 5
|
76
|
+
# TYPE puma_worker_status_last_status_pool_capacity gauge
|
77
|
+
# HELP puma_worker_status_last_status_pool_capacity Number of requests that can be processed right now
|
78
|
+
puma_worker_status_last_status_pool_capacity{my_label="baz",worker_index="0"} 5
|
79
|
+
puma_worker_status_last_status_pool_capacity{my_label="baz",worker_index="1"} 5
|
80
|
+
# TYPE puma_worker_status_last_status_max_threads gauge
|
81
|
+
# HELP puma_worker_status_last_status_max_threads Maximum number of worker threads
|
82
|
+
puma_worker_status_last_status_max_threads{my_label="baz",worker_index="0"} 5
|
83
|
+
puma_worker_status_last_status_max_threads{my_label="baz",worker_index="1"} 5
|
84
|
+
```
|
85
|
+
|
86
|
+
### ActiveRecord::Base.connection_pool.stat
|
87
|
+
|
88
|
+
*Now it's not working with pre-forked/clustered-mode web servers. Sorry.*
|
89
|
+
|
90
|
+
config/initializers/prometheus.rb
|
91
|
+
```ruby
|
92
|
+
require 'prometheus/client'
|
93
|
+
require 'prometheus_client_addons'
|
94
|
+
|
95
|
+
prometheus = Prometheus::Client.registry
|
96
|
+
pool = PrometheusClientAddons::Prometheus::Client::ActiveRecord.new(
|
97
|
+
prefix: 'activerecord',
|
98
|
+
base_labels: { my_label: 'foo' }
|
99
|
+
)
|
100
|
+
prometheus.register(pool)
|
101
|
+
```
|
102
|
+
|
103
|
+
Example response
|
104
|
+
```
|
105
|
+
# TYPE activerecord_size gauge
|
106
|
+
# HELP activerecord_size Size of pool
|
107
|
+
activerecord_size{my_label="foo"} 5
|
108
|
+
# TYPE activerecord_connections gauge
|
109
|
+
# HELP activerecord_connections Connections count
|
110
|
+
activerecord_connections{my_label="foo"} 0
|
111
|
+
# TYPE activerecord_busy gauge
|
112
|
+
# HELP activerecord_busy Busy count
|
113
|
+
activerecord_busy{my_label="foo"} 0
|
114
|
+
# TYPE activerecord_dead gauge
|
115
|
+
# HELP activerecord_dead Dead count
|
116
|
+
activerecord_dead{my_label="foo"} 0
|
117
|
+
# TYPE activerecord_idle gauge
|
118
|
+
# HELP activerecord_idle Idle count
|
119
|
+
activerecord_idle{my_label="foo"} 0
|
120
|
+
# TYPE activerecord_waiting gauge
|
121
|
+
# HELP activerecord_waiting Num waiting in queue
|
122
|
+
activerecord_waiting{my_label="foo"} 0
|
123
|
+
# TYPE activerecord_checkout_timeout gauge
|
124
|
+
# HELP activerecord_checkout_timeout Checkout timeout
|
125
|
+
activerecord_checkout_timeout{my_label="foo"} 5
|
126
|
+
```
|
127
|
+
|
128
|
+
### GC.stat
|
129
|
+
|
130
|
+
config/initializers/prometheus.rb
|
131
|
+
```ruby
|
132
|
+
require 'prometheus/client'
|
133
|
+
require 'prometheus_client_addons'
|
134
|
+
|
135
|
+
prometheus = Prometheus::Client.registry
|
136
|
+
gc = PrometheusClientAddons::Prometheus::Client::GC.new(
|
137
|
+
prefix: 'gc',
|
138
|
+
base_labels: { my_label: 'foo' }
|
139
|
+
)
|
140
|
+
prometheus.register(gc)
|
141
|
+
```
|
142
|
+
|
143
|
+
Example response
|
144
|
+
```
|
145
|
+
# TYPE gc_count gauge
|
146
|
+
# HELP gc_count count
|
147
|
+
gc_count{my_label="foo"} 62
|
148
|
+
# TYPE gc_heap_allocated_pages gauge
|
149
|
+
# HELP gc_heap_allocated_pages heap_allocated_pages
|
150
|
+
gc_heap_allocated_pages{my_label="foo"} 3593
|
151
|
+
# TYPE gc_heap_sorted_length gauge
|
152
|
+
# HELP gc_heap_sorted_length heap_sorted_length
|
153
|
+
gc_heap_sorted_length{my_label="foo"} 3593
|
154
|
+
# TYPE gc_heap_allocatable_pages gauge
|
155
|
+
# HELP gc_heap_allocatable_pages heap_allocatable_pages
|
156
|
+
gc_heap_allocatable_pages{my_label="foo"} 0
|
157
|
+
# TYPE gc_heap_available_slots gauge
|
158
|
+
# HELP gc_heap_available_slots heap_available_slots
|
159
|
+
gc_heap_available_slots{my_label="foo"} 1464501
|
160
|
+
# TYPE gc_heap_live_slots gauge
|
161
|
+
# HELP gc_heap_live_slots heap_live_slots
|
162
|
+
gc_heap_live_slots{my_label="foo"} 1464445
|
163
|
+
# TYPE gc_heap_free_slots gauge
|
164
|
+
# HELP gc_heap_free_slots heap_free_slots
|
165
|
+
gc_heap_free_slots{my_label="foo"} 56
|
166
|
+
# TYPE gc_heap_final_slots gauge
|
167
|
+
# HELP gc_heap_final_slots heap_final_slots
|
168
|
+
gc_heap_final_slots{my_label="foo"} 0
|
169
|
+
# TYPE gc_heap_marked_slots gauge
|
170
|
+
# HELP gc_heap_marked_slots heap_marked_slots
|
171
|
+
gc_heap_marked_slots{my_label="foo"} 999525
|
172
|
+
# TYPE gc_heap_eden_pages gauge
|
173
|
+
# HELP gc_heap_eden_pages heap_eden_pages
|
174
|
+
gc_heap_eden_pages{my_label="foo"} 3593
|
175
|
+
# TYPE gc_heap_tomb_pages gauge
|
176
|
+
# HELP gc_heap_tomb_pages heap_tomb_pages
|
177
|
+
gc_heap_tomb_pages{my_label="foo"} 0
|
178
|
+
# TYPE gc_total_allocated_pages gauge
|
179
|
+
# HELP gc_total_allocated_pages total_allocated_pages
|
180
|
+
gc_total_allocated_pages{my_label="foo"} 3593
|
181
|
+
# TYPE gc_total_freed_pages gauge
|
182
|
+
# HELP gc_total_freed_pages total_freed_pages
|
183
|
+
gc_total_freed_pages{my_label="foo"} 0
|
184
|
+
# TYPE gc_total_allocated_objects gauge
|
185
|
+
# HELP gc_total_allocated_objects total_allocated_objects
|
186
|
+
gc_total_allocated_objects{my_label="foo"} 4665284
|
187
|
+
# TYPE gc_total_freed_objects gauge
|
188
|
+
# HELP gc_total_freed_objects total_freed_objects
|
189
|
+
gc_total_freed_objects{my_label="foo"} 3200839
|
190
|
+
# TYPE gc_malloc_increase_bytes gauge
|
191
|
+
# HELP gc_malloc_increase_bytes malloc_increase_bytes
|
192
|
+
gc_malloc_increase_bytes{my_label="foo"} 16693664
|
193
|
+
# TYPE gc_malloc_increase_bytes_limit gauge
|
194
|
+
# HELP gc_malloc_increase_bytes_limit malloc_increase_bytes_limit
|
195
|
+
gc_malloc_increase_bytes_limit{my_label="foo"} 30330547
|
196
|
+
# TYPE gc_minor_gc_count gauge
|
197
|
+
# HELP gc_minor_gc_count minor_gc_count
|
198
|
+
gc_minor_gc_count{my_label="foo"} 48
|
199
|
+
# TYPE gc_major_gc_count gauge
|
200
|
+
# HELP gc_major_gc_count major_gc_count
|
201
|
+
gc_major_gc_count{my_label="foo"} 14
|
202
|
+
# TYPE gc_remembered_wb_unprotected_objects gauge
|
203
|
+
# HELP gc_remembered_wb_unprotected_objects remembered_wb_unprotected_objects
|
204
|
+
gc_remembered_wb_unprotected_objects{my_label="foo"} 4357
|
205
|
+
# TYPE gc_remembered_wb_unprotected_objects_limit gauge
|
206
|
+
# HELP gc_remembered_wb_unprotected_objects_limit remembered_wb_unprotected_objects_limit
|
207
|
+
gc_remembered_wb_unprotected_objects_limit{my_label="foo"} 8690
|
208
|
+
# TYPE gc_old_objects gauge
|
209
|
+
# HELP gc_old_objects old_objects
|
210
|
+
gc_old_objects{my_label="foo"} 992074
|
211
|
+
# TYPE gc_old_objects_limit gauge
|
212
|
+
# HELP gc_old_objects_limit old_objects_limit
|
213
|
+
gc_old_objects_limit{my_label="foo"} 1743172
|
214
|
+
# TYPE gc_oldmalloc_increase_bytes gauge
|
215
|
+
# HELP gc_oldmalloc_increase_bytes oldmalloc_increase_bytes
|
216
|
+
gc_oldmalloc_increase_bytes{my_label="foo"} 37700816
|
217
|
+
# TYPE gc_oldmalloc_increase_bytes_limit gauge
|
218
|
+
# HELP gc_oldmalloc_increase_bytes_limit oldmalloc_increase_bytes_limit
|
219
|
+
gc_oldmalloc_increase_bytes_limit{my_label="foo"} 33438324
|
220
|
+
```
|
221
|
+
|
222
|
+
### CustomCollector
|
223
|
+
|
224
|
+
config/initializers/prometheus.rb
|
225
|
+
```ruby
|
226
|
+
require 'prometheus/client'
|
227
|
+
require 'prometheus_client_addons'
|
228
|
+
|
229
|
+
prometheus = Prometheus::Client.registry
|
230
|
+
custom_collector = PrometheusClientAddons::Prometheus::Client::CustomCollector.new(
|
231
|
+
name: 'custom_metric',
|
232
|
+
docstring: 'This is a custom metric',
|
233
|
+
base_labels: { my_label: 'foo' },
|
234
|
+
&Proc.new {
|
235
|
+
# return custom value from block
|
236
|
+
Time.now.to_i
|
237
|
+
}
|
238
|
+
)
|
239
|
+
prometheus.register(custom_collector)
|
240
|
+
```
|
241
|
+
|
242
|
+
Example response
|
243
|
+
```
|
244
|
+
# TYPE custom_metric gauge
|
245
|
+
# HELP custom_metric This is a custom metric
|
246
|
+
custom_metric{my_label="foo"} 1567612321
|
247
|
+
```
|
248
|
+
|
249
|
+
## Installation
|
250
|
+
|
251
|
+
```ruby
|
252
|
+
gem 'prometheus_client_addons'
|
253
|
+
```
|
254
|
+
|
255
|
+
```bash
|
256
|
+
bundle install
|
257
|
+
# or
|
258
|
+
gem install prometheus_client_addons
|
259
|
+
```
|
260
|
+
|
261
|
+
## Development
|
262
|
+
|
263
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
264
|
+
|
265
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
266
|
+
|
267
|
+
## Contributing
|
268
|
+
|
269
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/prometheus_client_addons.
|
270
|
+
|
271
|
+
## License
|
272
|
+
|
273
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "prometheus_client_addons"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require "prometheus_client_addons/version"
|
2
|
+
|
3
|
+
module PrometheusClientAddons
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'prometheus_client_addons/prometheus/client/puma'
|
7
|
+
require 'prometheus_client_addons/prometheus/client/active_record'
|
8
|
+
require 'prometheus_client_addons/prometheus/client/custom_collector'
|
9
|
+
require 'prometheus_client_addons/prometheus/client/gc'
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'prometheus_client_addons/prometheus/client/formats/text_extended'
|
2
|
+
require 'prometheus_client_addons/prometheus/client/multi_metric'
|
3
|
+
|
4
|
+
module PrometheusClientAddons
|
5
|
+
module Prometheus
|
6
|
+
module Client
|
7
|
+
class ActiveRecord < MultiMetric
|
8
|
+
HANDLES = {
|
9
|
+
size: 'Size of pool',
|
10
|
+
connections: 'Connections count',
|
11
|
+
busy: 'Busy count',
|
12
|
+
dead: 'Dead count',
|
13
|
+
idle: 'Idle count',
|
14
|
+
waiting: 'Num waiting in queue',
|
15
|
+
checkout_timeout: 'Checkout timeout'
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
def multi_name_type
|
19
|
+
full_handles = HANDLES.keys.map { |key| "#{prefix}#{key}" }.map(&:to_sym)
|
20
|
+
Hash[full_handles.zip([:gauge] * HANDLES.size)]
|
21
|
+
end
|
22
|
+
|
23
|
+
def multi_name_docstring
|
24
|
+
Hash[HANDLES.map { |key, value| ["#{prefix}#{key}".to_sym, value] }]
|
25
|
+
end
|
26
|
+
|
27
|
+
def multi_values
|
28
|
+
stat = ::ActiveRecord::Base.connection_pool.stat
|
29
|
+
Hash[stat.map { |key, value| ["#{prefix}#{key}".to_sym, { {} => value }] }]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'prometheus/client/metric'
|
2
|
+
|
3
|
+
module PrometheusClientAddons
|
4
|
+
module Prometheus
|
5
|
+
module Client
|
6
|
+
class CustomCollector < ::Prometheus::Client::Metric
|
7
|
+
def initialize(name:, docstring:, base_labels: {}, &block)
|
8
|
+
@custom_collector = block
|
9
|
+
super(name.to_sym, docstring, base_labels)
|
10
|
+
end
|
11
|
+
|
12
|
+
def get(labels = {})
|
13
|
+
@custom_collector.call
|
14
|
+
end
|
15
|
+
|
16
|
+
def values
|
17
|
+
{ {} => @custom_collector.call }
|
18
|
+
end
|
19
|
+
|
20
|
+
def type
|
21
|
+
:gauge
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module PrometheusClientAddons
|
2
|
+
module Prometheus
|
3
|
+
module Client
|
4
|
+
FakeGauge = Struct.new(:name, :docstring, :base_labels) do
|
5
|
+
def initialize(*)
|
6
|
+
self.base_labels ||= {}
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def type
|
11
|
+
:gauge
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'prometheus/middleware/exporter'
|
2
|
+
require 'prometheus/client/formats/text'
|
3
|
+
require 'prometheus_client_addons/prometheus/client/multi_metric'
|
4
|
+
require 'prometheus_client_addons/prometheus/client/fake_gauge'
|
5
|
+
|
6
|
+
module PrometheusClientAddons
|
7
|
+
module Prometheus
|
8
|
+
module Client
|
9
|
+
module Formats
|
10
|
+
TextExtended = ::Prometheus::Client::Formats::Text.dup
|
11
|
+
|
12
|
+
module TextExtended
|
13
|
+
def self.marshal(registry)
|
14
|
+
lines = []
|
15
|
+
|
16
|
+
registry.metrics.each do |metric|
|
17
|
+
if metric.is_a?(MultiMetric)
|
18
|
+
metric.multi_values.each do |name, values|
|
19
|
+
lines << format(self::TYPE_LINE, name, metric.multi_name_type[name])
|
20
|
+
lines << format(self::HELP_LINE, name, escape(metric.multi_name_docstring[name]))
|
21
|
+
|
22
|
+
values.each do |label_set, value|
|
23
|
+
_metric = FakeGauge.new(name, metric.multi_name_docstring[name], metric.base_labels)
|
24
|
+
representation(_metric, label_set, value) { |l| lines << l }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
else
|
28
|
+
lines << format(self::TYPE_LINE, metric.name, metric.type)
|
29
|
+
lines << format(self::HELP_LINE, metric.name, escape(metric.docstring))
|
30
|
+
|
31
|
+
metric.values.each do |label_set, value|
|
32
|
+
representation(metric, label_set, value) { |l| lines << l }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
(lines << nil).join(self::DELIMITER)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Prometheus::Middleware::Exporter.send(:remove_const, 'FORMATS')
|
46
|
+
Prometheus::Middleware::Exporter.send(:remove_const, 'FALLBACK')
|
47
|
+
Prometheus::Middleware::Exporter.send(:const_set, 'FORMATS', [PrometheusClientAddons::Prometheus::Client::Formats::TextExtended].freeze)
|
48
|
+
Prometheus::Middleware::Exporter.send(:const_set, 'FALLBACK', PrometheusClientAddons::Prometheus::Client::Formats::TextExtended)
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'prometheus_client_addons/prometheus/client/formats/text_extended'
|
2
|
+
require 'prometheus_client_addons/prometheus/client/multi_metric'
|
3
|
+
|
4
|
+
module PrometheusClientAddons
|
5
|
+
module Prometheus
|
6
|
+
module Client
|
7
|
+
class GC < MultiMetric
|
8
|
+
KEYS = [
|
9
|
+
:count,
|
10
|
+
:heap_allocated_pages,
|
11
|
+
:heap_sorted_length,
|
12
|
+
:heap_allocatable_pages,
|
13
|
+
:heap_available_slots,
|
14
|
+
:heap_live_slots,
|
15
|
+
:heap_free_slots,
|
16
|
+
:heap_final_slots,
|
17
|
+
:heap_marked_slots,
|
18
|
+
:heap_eden_pages,
|
19
|
+
:heap_tomb_pages,
|
20
|
+
:total_allocated_pages,
|
21
|
+
:total_freed_pages,
|
22
|
+
:total_allocated_objects,
|
23
|
+
:total_freed_objects,
|
24
|
+
:malloc_increase_bytes,
|
25
|
+
:malloc_increase_bytes_limit,
|
26
|
+
:minor_gc_count,
|
27
|
+
:major_gc_count,
|
28
|
+
:remembered_wb_unprotected_objects,
|
29
|
+
:remembered_wb_unprotected_objects_limit,
|
30
|
+
:old_objects,
|
31
|
+
:old_objects_limit,
|
32
|
+
:oldmalloc_increase_bytes,
|
33
|
+
:oldmalloc_increase_bytes_limit
|
34
|
+
].freeze
|
35
|
+
|
36
|
+
HANDLES = Hash[KEYS.zip(KEYS)].freeze
|
37
|
+
|
38
|
+
def multi_name_type
|
39
|
+
full_handles = HANDLES.keys.map { |key| "#{prefix}#{key}" }.map(&:to_sym)
|
40
|
+
Hash[full_handles.zip([:gauge] * HANDLES.size)]
|
41
|
+
end
|
42
|
+
|
43
|
+
def multi_name_docstring
|
44
|
+
Hash[HANDLES.map { |key, value| ["#{prefix}#{key}".to_sym, value] }]
|
45
|
+
end
|
46
|
+
|
47
|
+
def multi_values
|
48
|
+
stat = ::GC.stat
|
49
|
+
Hash[stat.map { |key, value| ["#{prefix}#{key}".to_sym, { {} => value }] }]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'prometheus/client/metric'
|
2
|
+
require 'prometheus/client/label_set_validator'
|
3
|
+
|
4
|
+
module PrometheusClientAddons
|
5
|
+
module Prometheus
|
6
|
+
module Client
|
7
|
+
class MultiMetric < ::Prometheus::Client::Metric
|
8
|
+
attr_reader :name, :prefix, :base_labels
|
9
|
+
|
10
|
+
def initialize(prefix: '', base_labels: {})
|
11
|
+
prefix = "#{prefix}_" unless prefix == ''
|
12
|
+
|
13
|
+
@prefix = prefix
|
14
|
+
@name = prefix
|
15
|
+
@base_labels = base_labels
|
16
|
+
|
17
|
+
multi_name_type.keys.each { |name| validate_name("#{prefix}#{name}".to_sym) }
|
18
|
+
multi_name_docstring.keys.each { |name| validate_name("#{prefix}#{name}".to_sym) }
|
19
|
+
multi_name_docstring.values.each(&method(:validate_docstring))
|
20
|
+
@validator = ::Prometheus::Client::LabelSetValidator.new
|
21
|
+
@validator.valid?(base_labels)
|
22
|
+
end
|
23
|
+
|
24
|
+
def multi_name_type
|
25
|
+
fail('Should return hash {name => type}')
|
26
|
+
end
|
27
|
+
|
28
|
+
def multi_name_docstring
|
29
|
+
fail('Should return hash {name => docstrings}')
|
30
|
+
end
|
31
|
+
|
32
|
+
def multi_values
|
33
|
+
fail('Should return hash {name => {label_set => value, label_set => value, }}')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'prometheus_client_addons/prometheus/client/formats/text_extended'
|
3
|
+
require 'prometheus_client_addons/prometheus/client/multi_metric'
|
4
|
+
require 'prometheus_client_addons/puma/plugin/prometheus_client_addons'
|
5
|
+
|
6
|
+
module PrometheusClientAddons
|
7
|
+
module Prometheus
|
8
|
+
module Client
|
9
|
+
class Puma < MultiMetric
|
10
|
+
class << self
|
11
|
+
attr_accessor :control_url, :control_auth_token
|
12
|
+
end
|
13
|
+
|
14
|
+
HANDLES = {
|
15
|
+
backlog: 'How many requests are waiting',
|
16
|
+
running: 'Number of running threads',
|
17
|
+
pool_capacity: 'Number of requests that can be processed right now',
|
18
|
+
max_threads: 'Maximum number of worker threads',
|
19
|
+
|
20
|
+
workers: 'Number of workers',
|
21
|
+
phase: 'Phase of worker',
|
22
|
+
booted_workers: 'Number of booted workers',
|
23
|
+
old_workers: 'Number of old workers',
|
24
|
+
|
25
|
+
worker_status_phase: 'Phase of worker',
|
26
|
+
worker_status_booted: 'Booted or not',
|
27
|
+
worker_status_last_checkin: 'Last update',
|
28
|
+
|
29
|
+
worker_status_last_status_backlog: 'How many objects have yet to be processed by the pool',
|
30
|
+
worker_status_last_status_running: 'Number of running threads',
|
31
|
+
worker_status_last_status_pool_capacity: 'Number of requests that can be processed right now',
|
32
|
+
worker_status_last_status_max_threads: 'Maximum number of worker threads'
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
def multi_name_type
|
36
|
+
full_handles = HANDLES.keys.map { |key| "#{prefix}#{key}" }.map(&:to_sym)
|
37
|
+
Hash[full_handles.zip([:gauge] * HANDLES.size)]
|
38
|
+
end
|
39
|
+
|
40
|
+
def multi_name_docstring
|
41
|
+
Hash[HANDLES.map { |key, value| ["#{prefix}#{key}".to_sym, value] }]
|
42
|
+
end
|
43
|
+
|
44
|
+
def extract(input, output, nested, label_set = {})
|
45
|
+
key = if input.key?(nested.last.to_s)
|
46
|
+
nested.last.to_s
|
47
|
+
elsif input.key?(nested.last.to_sym)
|
48
|
+
nested.last.to_sym
|
49
|
+
end
|
50
|
+
return unless key
|
51
|
+
|
52
|
+
output["#{prefix}#{nested.join('_')}".to_sym] ||= {}
|
53
|
+
output["#{prefix}#{nested.join('_')}".to_sym][label_set] = input[key]
|
54
|
+
end
|
55
|
+
|
56
|
+
def multi_values
|
57
|
+
body = Socket.unix(self.class.control_url.gsub("unix://", '')) do |socket|
|
58
|
+
socket << "GET /stats?token=#{self.class.control_auth_token} HTTP/1.0\r\n\r\n"
|
59
|
+
socket.read
|
60
|
+
end
|
61
|
+
|
62
|
+
data = JSON.parse(body.split("\n").last, symbolize_names: true)
|
63
|
+
|
64
|
+
result = {}
|
65
|
+
|
66
|
+
extract(data, result, [:backlog])
|
67
|
+
extract(data, result, [:running])
|
68
|
+
extract(data, result, [:pool_capacity])
|
69
|
+
extract(data, result, [:max_threads])
|
70
|
+
|
71
|
+
extract(data, result, [:workers])
|
72
|
+
extract(data, result, [:phase])
|
73
|
+
extract(data, result, [:booted_workers])
|
74
|
+
extract(data, result, [:old_workers])
|
75
|
+
|
76
|
+
if data.key?(:worker_status) && !data[:worker_status].empty?
|
77
|
+
data[:worker_status].each do |worker_status|
|
78
|
+
worker_index = worker_status[:index]
|
79
|
+
|
80
|
+
extract(worker_status, result, [:worker_status, :phase], { worker_index: worker_index })
|
81
|
+
extract(worker_status, result, [:worker_status, :booted], { worker_index: worker_index })
|
82
|
+
extract(worker_status, result, [:worker_status, :last_checkin], { worker_index: worker_index })
|
83
|
+
|
84
|
+
last_status = worker_status[:last_status]
|
85
|
+
extract(last_status, result, [:worker_status, :last_status, :backlog], { worker_index: worker_index })
|
86
|
+
extract(last_status, result, [:worker_status, :last_status, :running], { worker_index: worker_index })
|
87
|
+
extract(last_status, result, [:worker_status, :last_status, :pool_capacity], { worker_index: worker_index })
|
88
|
+
extract(last_status, result, [:worker_status, :last_status, :max_threads], { worker_index: worker_index })
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
result
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'puma/plugin'
|
2
|
+
|
3
|
+
module PrometheusClientAddons
|
4
|
+
module Puma
|
5
|
+
module Plugin
|
6
|
+
::Puma::Plugin.create do
|
7
|
+
def start(launcher)
|
8
|
+
control_url = launcher.options[:control_url]
|
9
|
+
raise StandardError, "Need Puma's activate_control_app" if control_url == nil
|
10
|
+
|
11
|
+
Prometheus::Client::Puma.tap do |puma|
|
12
|
+
puma.control_url = control_url
|
13
|
+
puma.control_auth_token = launcher.options[:control_auth_token]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "prometheus_client_addons/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "prometheus_client_addons"
|
7
|
+
spec.version = PrometheusClientAddons::VERSION
|
8
|
+
spec.authors = ["Anton Osenenko"]
|
9
|
+
spec.email = ["anton.osenenko@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = 'The missed parts of prometheus/client_ruby'
|
12
|
+
spec.description = 'The missed parts of prometheus/client_ruby'
|
13
|
+
spec.homepage = "https://github.com/a0s/prometheus_client_addons"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
if spec.respond_to?(:metadata)
|
17
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
20
|
+
else
|
21
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
22
|
+
"public gem pushes."
|
23
|
+
end
|
24
|
+
|
25
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
26
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
27
|
+
end
|
28
|
+
spec.bindir = "exe"
|
29
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
30
|
+
spec.require_paths = ["lib"]
|
31
|
+
|
32
|
+
spec.add_dependency "prometheus-client", "~> 0.9.0"
|
33
|
+
|
34
|
+
spec.add_development_dependency "bundler", "~> 1.17"
|
35
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
36
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
37
|
+
spec.add_development_dependency "puma"
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: prometheus_client_addons
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anton Osenenko
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-09-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: prometheus-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.9.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.9.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.17'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.17'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: puma
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: The missed parts of prometheus/client_ruby
|
84
|
+
email:
|
85
|
+
- anton.osenenko@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
92
|
+
- ".travis.yml"
|
93
|
+
- Gemfile
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- bin/console
|
98
|
+
- bin/setup
|
99
|
+
- lib/prometheus_client_addons.rb
|
100
|
+
- lib/prometheus_client_addons/prometheus/client/active_record.rb
|
101
|
+
- lib/prometheus_client_addons/prometheus/client/custom_collector.rb
|
102
|
+
- lib/prometheus_client_addons/prometheus/client/fake_gauge.rb
|
103
|
+
- lib/prometheus_client_addons/prometheus/client/formats/text_extended.rb
|
104
|
+
- lib/prometheus_client_addons/prometheus/client/gc.rb
|
105
|
+
- lib/prometheus_client_addons/prometheus/client/multi_metric.rb
|
106
|
+
- lib/prometheus_client_addons/prometheus/client/puma.rb
|
107
|
+
- lib/prometheus_client_addons/puma/plugin/prometheus_client_addons.rb
|
108
|
+
- lib/prometheus_client_addons/version.rb
|
109
|
+
- prometheus_client_addons.gemspec
|
110
|
+
homepage: https://github.com/a0s/prometheus_client_addons
|
111
|
+
licenses:
|
112
|
+
- MIT
|
113
|
+
metadata:
|
114
|
+
allowed_push_host: https://rubygems.org
|
115
|
+
homepage_uri: https://github.com/a0s/prometheus_client_addons
|
116
|
+
source_code_uri: https://github.com/a0s/prometheus_client_addons
|
117
|
+
post_install_message:
|
118
|
+
rdoc_options: []
|
119
|
+
require_paths:
|
120
|
+
- lib
|
121
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
requirements: []
|
132
|
+
rubygems_version: 3.0.3
|
133
|
+
signing_key:
|
134
|
+
specification_version: 4
|
135
|
+
summary: The missed parts of prometheus/client_ruby
|
136
|
+
test_files: []
|