prometheus_exporter 0.5.3 → 0.6.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/.github/workflows/ci.yml +36 -0
- data/CHANGELOG +4 -0
- data/README.md +71 -14
- data/bin/prometheus_exporter +17 -0
- data/lib/prometheus_exporter.rb +1 -0
- data/lib/prometheus_exporter/client.rb +23 -2
- data/lib/prometheus_exporter/instrumentation/active_record.rb +1 -1
- data/lib/prometheus_exporter/instrumentation/sidekiq.rb +44 -3
- data/lib/prometheus_exporter/instrumentation/sidekiq_queue.rb +12 -1
- data/lib/prometheus_exporter/middleware.rb +13 -2
- data/lib/prometheus_exporter/server/runner.rb +12 -2
- data/lib/prometheus_exporter/server/sidekiq_collector.rb +2 -2
- data/lib/prometheus_exporter/server/web_server.rb +29 -17
- data/lib/prometheus_exporter/version.rb +1 -1
- metadata +3 -3
- data/.travis.yml +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f516c39448418a2216851149f0479f3f9e0f5feadae5a5468e7953fc0551d318
|
4
|
+
data.tar.gz: dcc937b79e05d4cd74a64ab2135425c75c4bba1be053bec99e8db0695a3ac998
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5664f24c1c4a1520bafe789e5df8a9f1c40b118933cab9b73baa953f633ec6e81c3a11bbc9fc63097a2a2acdd2390daeade9449e6451cc83207fc2162575b359
|
7
|
+
data.tar.gz: ca4aeedbc6e211818569257e8a3e9fde93be363a2da246abae45749bc9cc232052ac52f0850cd54d0f600904bed193a10db1f76e4fc9567b837b20a78264158b
|
@@ -0,0 +1,36 @@
|
|
1
|
+
name: Test Exporter
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
pull_request:
|
6
|
+
schedule:
|
7
|
+
- cron: '0 0 * * 0' # weekly
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
build:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
name: Ruby ${{ matrix.ruby }}
|
13
|
+
strategy:
|
14
|
+
matrix:
|
15
|
+
ruby: ["2.7", "2.6", "2.5", "2.4"]
|
16
|
+
steps:
|
17
|
+
- uses: actions/checkout@master
|
18
|
+
with:
|
19
|
+
fetch-depth: 1
|
20
|
+
- uses: actions/setup-ruby@v1
|
21
|
+
with:
|
22
|
+
ruby-version: ${{ matrix.ruby }}
|
23
|
+
- uses: actions/cache@v2
|
24
|
+
with:
|
25
|
+
path: vendor/bundle
|
26
|
+
key: ${{ runner.os }}-${{ matrix.ruby }}-gems-${{ hashFiles('**/Gemfile.lock') }}
|
27
|
+
restore-keys: |
|
28
|
+
${{ runner.os }}-${{ matrix.ruby }}-gems-
|
29
|
+
- name: Setup gems
|
30
|
+
run: |
|
31
|
+
bundle config path vendor/bundle
|
32
|
+
bundle install --jobs 4
|
33
|
+
- name: Rubocop
|
34
|
+
run: bundle exec rubocop
|
35
|
+
- name: Run tests
|
36
|
+
run: bundle exec rake
|
data/CHANGELOG
CHANGED
data/README.md
CHANGED
@@ -200,12 +200,27 @@ $ bundle exec prometheus_exporter
|
|
200
200
|
| Summary | `http_sql_duration_seconds`² | Time spent in HTTP reqs in SQL in seconds |
|
201
201
|
| Summary | `http_queue_duration_seconds`³ | Time spent queueing the request in load balancer in seconds |
|
202
202
|
|
203
|
-
All metrics have a `controller` and an `action` label.
|
204
|
-
`http_requests_total` additionally has a (HTTP response) `status` label.
|
203
|
+
All metrics have a `controller` and an `action` label.
|
204
|
+
`http_requests_total` additionally has a (HTTP response) `status` label.
|
205
205
|
|
206
|
-
|
207
|
-
|
208
|
-
|
206
|
+
To add your own labels to the default metrics, create a subclass of `PrometheusExporter::Middleware`, override `custom_labels`, and use it in your initializer.
|
207
|
+
```ruby
|
208
|
+
class MyMiddleware < PrometheusExporter::Middleware
|
209
|
+
def custom_labels(env)
|
210
|
+
labels = {}
|
211
|
+
|
212
|
+
if env['HTTP_X_PLATFORM']
|
213
|
+
labels['platform'] = env['HTTP_X_PLATFORM']
|
214
|
+
end
|
215
|
+
|
216
|
+
labels
|
217
|
+
end
|
218
|
+
end
|
219
|
+
```
|
220
|
+
|
221
|
+
¹) Only available when Redis is used.
|
222
|
+
²) Only available when Mysql or PostgreSQL are used.
|
223
|
+
³) Only available when [Instrumenting Request Queueing Time](#instrumenting-request-queueing-time) is set up.
|
209
224
|
|
210
225
|
#### Activerecord Connection Pool Metrics
|
211
226
|
|
@@ -365,19 +380,19 @@ Sometimes the Sidekiq server shuts down before it can send metrics, that were ge
|
|
365
380
|
**PrometheusExporter::Instrumentation::Sidekiq**
|
366
381
|
| Type | Name | Description |
|
367
382
|
| --- | --- | --- |
|
368
|
-
|
|
383
|
+
| Summary | `sidekiq_job_duration_seconds` | Time spent in sidekiq jobs |
|
369
384
|
| Counter | `sidekiq_jobs_total` | Total number of sidekiq jobs executed |
|
370
385
|
| Counter | `sidekiq_restarted_jobs_total` | Total number of sidekiq jobs that we restarted because of a sidekiq shutdown |
|
371
386
|
| Counter | `sidekiq_failed_jobs_total` | Total number of failed sidekiq jobs |
|
372
387
|
|
373
|
-
All metrics have a `job_name` label.
|
388
|
+
All metrics have a `job_name` label and a `queue` label.
|
374
389
|
|
375
390
|
**PrometheusExporter::Instrumentation::Sidekiq.death_handler**
|
376
391
|
| Type | Name | Description |
|
377
392
|
| --- | --- | --- |
|
378
393
|
| Counter | `sidekiq_dead_jobs_total` | Total number of dead sidekiq jobs |
|
379
394
|
|
380
|
-
This metric
|
395
|
+
This metric has a `job_name` label and a `queue` label.
|
381
396
|
|
382
397
|
**PrometheusExporter::Instrumentation::SidekiqQueue**
|
383
398
|
| Type | Name | Description |
|
@@ -387,7 +402,7 @@ This metric also has a `job_name` label.
|
|
387
402
|
|
388
403
|
Both metrics will have a `queue` label with the name of the queue.
|
389
404
|
|
390
|
-
_See [Metrics collected by Process Instrumentation](#metrics-collected-by-process-instrumentation) for a list of metrics the Process instrumentation will produce._
|
405
|
+
_See [Metrics collected by Process Instrumentation](#metrics-collected-by-process-instrumentation) for a list of metrics the Process instrumentation will produce._
|
391
406
|
|
392
407
|
#### Shoryuken metrics
|
393
408
|
|
@@ -411,7 +426,7 @@ end
|
|
411
426
|
| Counter | `shoryuken_restarted_jobs_total` | Total number of shoryuken jobs that we restarted because of a shoryuken shutdown |
|
412
427
|
| Counter | `shoryuken_failed_jobs_total` | Total number of failed shoryuken jobs |
|
413
428
|
|
414
|
-
All metrics have labels for `job_name` and `queue_name`.
|
429
|
+
All metrics have labels for `job_name` and `queue_name`.
|
415
430
|
|
416
431
|
#### Delayed Job plugin
|
417
432
|
|
@@ -456,7 +471,7 @@ end
|
|
456
471
|
| Counter | `hutch_jobs_total` | Total number of hutch jobs executed |
|
457
472
|
| Counter | `hutch_failed_jobs_total` | Total number failed hutch jobs executed |
|
458
473
|
|
459
|
-
All metrics have a `job_name` label.
|
474
|
+
All metrics have a `job_name` label.
|
460
475
|
|
461
476
|
#### Instrumenting Request Queueing Time
|
462
477
|
|
@@ -494,7 +509,7 @@ end
|
|
494
509
|
| Gauge | `puma_thread_pool_capacity_total` | Number of puma threads available at current scale |
|
495
510
|
| Gauge | `puma_max_threads_total` | Number of puma threads at available at max scale |
|
496
511
|
|
497
|
-
All metrics may have a `phase` label.
|
512
|
+
All metrics may have a `phase` label.
|
498
513
|
|
499
514
|
### Unicorn process metrics
|
500
515
|
|
@@ -577,8 +592,8 @@ Then you can collect the metrics you need on demand:
|
|
577
592
|
|
578
593
|
```ruby
|
579
594
|
def metrics
|
580
|
-
|
581
|
-
|
595
|
+
user_count_gauge = PrometheusExporter::Metric::Gauge.new('user_count', 'number of users in the app')
|
596
|
+
user_count_gauge.observe User.count
|
582
597
|
[user_count_gauge]
|
583
598
|
end
|
584
599
|
```
|
@@ -692,6 +707,25 @@ ruby_web_requests{hostname="app-server-01"} 1
|
|
692
707
|
When running the process for `prometheus_exporter` using `bin/prometheus_exporter`, there are several configurations that
|
693
708
|
can be passed in:
|
694
709
|
|
710
|
+
```
|
711
|
+
Usage: prometheus_exporter [options]
|
712
|
+
-p, --port INTEGER Port exporter should listen on (default: 9394)
|
713
|
+
-b, --bind STRING IP address exporter should listen on (default: localhost)
|
714
|
+
-t, --timeout INTEGER Timeout in seconds for metrics endpoint (default: 2)
|
715
|
+
--prefix METRIC_PREFIX Prefix to apply to all metrics (default: ruby_)
|
716
|
+
--label METRIC_LABEL Label to apply to all metrics (default: {})
|
717
|
+
-c, --collector FILE (optional) Custom collector to run
|
718
|
+
-a, --type-collector FILE (optional) Custom type collectors to run in main collector
|
719
|
+
-v, --verbose
|
720
|
+
--auth FILE (optional) enable basic authentication using a htpasswd FILE
|
721
|
+
--realm REALM (optional) Use REALM for basic authentication (default: "Prometheus Exporter")
|
722
|
+
--unicorn-listen-address ADDRESS
|
723
|
+
(optional) Address where unicorn listens on (unix or TCP address)
|
724
|
+
--unicorn-master PID_FILE (optional) PID file of unicorn master process to monitor unicorn
|
725
|
+
```
|
726
|
+
|
727
|
+
#### Example
|
728
|
+
|
695
729
|
The following will run the process at
|
696
730
|
- Port `8080` (default `9394`)
|
697
731
|
- Bind to `0.0.0.0` (default `localhost`)
|
@@ -707,6 +741,29 @@ prometheus_exporter -p 8080 \
|
|
707
741
|
--prefix 'foo_'
|
708
742
|
```
|
709
743
|
|
744
|
+
#### Enabling Basic Authentication
|
745
|
+
|
746
|
+
If you desire authentication on your `/metrics` route, you can enable basic authentication with the `--auth` option.
|
747
|
+
|
748
|
+
```
|
749
|
+
$ prometheus_exporter --auth my-htpasswd-file
|
750
|
+
```
|
751
|
+
|
752
|
+
Additionally, the `--realm` option may be used to provide a customized realm for the challenge request.
|
753
|
+
|
754
|
+
Notes:
|
755
|
+
|
756
|
+
* You will need to create a `htpasswd` formatted file before hand which contains one or more user:password entries
|
757
|
+
* Only the basic `crypt` encryption is currently supported
|
758
|
+
|
759
|
+
A simple `htpasswd` file can be created with the Apache `htpasswd` utility; e.g:
|
760
|
+
|
761
|
+
```
|
762
|
+
$ htpasswd -cdb my-htpasswd-file my-user my-unencrypted-password
|
763
|
+
```
|
764
|
+
|
765
|
+
This will create a file named `my-htpasswd-file` which is suitable for use the `--auth` option.
|
766
|
+
|
710
767
|
### Client default labels
|
711
768
|
|
712
769
|
You can specify a default label for instrumentation metrics sent by a specific client. For example:
|
data/bin/prometheus_exporter
CHANGED
@@ -47,6 +47,12 @@ def run
|
|
47
47
|
opt.on('-v', '--verbose') do |o|
|
48
48
|
options[:verbose] = true
|
49
49
|
end
|
50
|
+
opt.on('--auth FILE', String, "(optional) enable basic authentication using a htpasswd FILE") do |o|
|
51
|
+
options[:auth] = o
|
52
|
+
end
|
53
|
+
opt.on('--realm REALM', String, "(optional) Use REALM for basic authentication (default: \"#{PrometheusExporter::DEFAULT_REALM}\")") do |o|
|
54
|
+
options[:realm] = o
|
55
|
+
end
|
50
56
|
|
51
57
|
opt.on('--unicorn-listen-address ADDRESS', String, '(optional) Address where unicorn listens on (unix or TCP address)') do |o|
|
52
58
|
options[:unicorn_listen_address] = o
|
@@ -57,6 +63,17 @@ def run
|
|
57
63
|
end
|
58
64
|
end.parse!
|
59
65
|
|
66
|
+
if options.has_key?(:realm) && !options.has_key?(:auth)
|
67
|
+
STDERR.puts "[Warn] Providing REALM without AUTH has no effect"
|
68
|
+
end
|
69
|
+
|
70
|
+
if options.has_key?(:auth)
|
71
|
+
unless File.exist?(options[:auth]) && File.readable?(options[:auth])
|
72
|
+
STDERR.puts "[Error] The AUTH file either doesn't exist or we don't have access to it"
|
73
|
+
exit 1
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
60
77
|
if custom_collector_filename
|
61
78
|
eval File.read(custom_collector_filename), nil, File.expand_path(custom_collector_filename)
|
62
79
|
found = false
|
data/lib/prometheus_exporter.rb
CHANGED
@@ -64,8 +64,10 @@ module PrometheusExporter
|
|
64
64
|
@metrics = []
|
65
65
|
|
66
66
|
@queue = Queue.new
|
67
|
+
|
67
68
|
@socket = nil
|
68
69
|
@socket_started = nil
|
70
|
+
@socket_pid = nil
|
69
71
|
|
70
72
|
max_queue_size ||= MAX_QUEUE_SIZE
|
71
73
|
max_queue_size = max_queue_size.to_i
|
@@ -107,7 +109,16 @@ module PrometheusExporter
|
|
107
109
|
end
|
108
110
|
|
109
111
|
def send_json(obj)
|
110
|
-
payload =
|
112
|
+
payload =
|
113
|
+
if @custom_labels
|
114
|
+
if obj[:custom_labels]
|
115
|
+
obj.merge(custom_labels: @custom_labels.merge(obj[:custom_labels]))
|
116
|
+
else
|
117
|
+
obj.merge(custom_labels: @custom_labels)
|
118
|
+
end
|
119
|
+
else
|
120
|
+
obj
|
121
|
+
end
|
111
122
|
send(@json_serializer.dump(payload))
|
112
123
|
end
|
113
124
|
|
@@ -191,12 +202,20 @@ module PrometheusExporter
|
|
191
202
|
end
|
192
203
|
|
193
204
|
def close_socket_if_old!
|
194
|
-
if @socket && ((@socket_started + MAX_SOCKET_AGE) < Time.now.to_f)
|
205
|
+
if @socket_pid == Process.pid && @socket && @socket_started && ((@socket_started + MAX_SOCKET_AGE) < Time.now.to_f)
|
195
206
|
close_socket!
|
196
207
|
end
|
197
208
|
end
|
198
209
|
|
199
210
|
def ensure_socket!
|
211
|
+
# if process was forked socket may be owned by parent
|
212
|
+
# leave it alone and reset
|
213
|
+
if @socket_pid != Process.pid
|
214
|
+
@socket = nil
|
215
|
+
@socket_started = nil
|
216
|
+
@socket_pid = nil
|
217
|
+
end
|
218
|
+
|
200
219
|
close_socket_if_old!
|
201
220
|
if !@socket
|
202
221
|
@socket = TCPSocket.new @host, @port
|
@@ -207,12 +226,14 @@ module PrometheusExporter
|
|
207
226
|
@socket.write("Content-Type: application/octet-stream\r\n")
|
208
227
|
@socket.write("\r\n")
|
209
228
|
@socket_started = Time.now.to_f
|
229
|
+
@socket_pid = Process.pid
|
210
230
|
end
|
211
231
|
|
212
232
|
nil
|
213
233
|
rescue
|
214
234
|
@socket = nil
|
215
235
|
@socket_started = nil
|
236
|
+
@socket_pid = nil
|
216
237
|
raise
|
217
238
|
end
|
218
239
|
|
@@ -69,7 +69,7 @@ module PrometheusExporter::Instrumentation
|
|
69
69
|
|
70
70
|
labels_from_config = pool.spec.config
|
71
71
|
.select { |k, v| @config_labels.include? k }
|
72
|
-
.map { |k, v| [k.to_s.prepend("dbconfig_"), v] }
|
72
|
+
.map { |k, v| [k.to_s.dup.prepend("dbconfig_"), v] }
|
73
73
|
|
74
74
|
labels = @metric_labels.merge(pool_name: pool.spec.name).merge(Hash[labels_from_config])
|
75
75
|
|
@@ -1,6 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'yaml'
|
4
|
+
|
3
5
|
module PrometheusExporter::Instrumentation
|
6
|
+
JOB_WRAPPER_CLASS_NAME = 'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper'
|
7
|
+
DELAYED_CLASS_NAMES = [
|
8
|
+
'Sidekiq::Extensions::DelayedClass',
|
9
|
+
'Sidekiq::Extensions::DelayedModel',
|
10
|
+
'Sidekiq::Extensions::DelayedMailer',
|
11
|
+
]
|
12
|
+
|
4
13
|
class Sidekiq
|
5
14
|
def self.death_handler
|
6
15
|
-> (job, ex) do
|
@@ -32,15 +41,47 @@ module PrometheusExporter::Instrumentation
|
|
32
41
|
raise e
|
33
42
|
ensure
|
34
43
|
duration = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - start
|
35
|
-
class_name = worker.class.to_s == 'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper' ?
|
36
|
-
msg['wrapped'] : worker.class.to_s
|
37
44
|
@client.send_json(
|
38
45
|
type: "sidekiq",
|
39
|
-
name:
|
46
|
+
name: get_name(worker, msg),
|
47
|
+
queue: queue,
|
40
48
|
success: success,
|
41
49
|
shutdown: shutdown,
|
42
50
|
duration: duration
|
43
51
|
)
|
44
52
|
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def get_name(worker, msg)
|
57
|
+
class_name = worker.class.to_s
|
58
|
+
if class_name == JOB_WRAPPER_CLASS_NAME
|
59
|
+
get_job_wrapper_name(msg)
|
60
|
+
elsif DELAYED_CLASS_NAMES.include?(class_name)
|
61
|
+
get_delayed_name(msg, class_name)
|
62
|
+
else
|
63
|
+
class_name
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_job_wrapper_name(msg)
|
68
|
+
msg['wrapped']
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_delayed_name(msg, class_name)
|
72
|
+
# fallback to class_name since we're relying on the internal implementation
|
73
|
+
# of the delayed extensions
|
74
|
+
# https://github.com/mperham/sidekiq/blob/master/lib/sidekiq/extensions/class_methods.rb
|
75
|
+
begin
|
76
|
+
(target, method_name, _args) = YAML.load(msg['args'].first)
|
77
|
+
if target.class == Class
|
78
|
+
"#{target.name}##{method_name}"
|
79
|
+
else
|
80
|
+
"#{target.class.name}##{method_name}"
|
81
|
+
end
|
82
|
+
rescue
|
83
|
+
class_name
|
84
|
+
end
|
85
|
+
end
|
45
86
|
end
|
46
87
|
end
|
@@ -27,13 +27,24 @@ module PrometheusExporter::Instrumentation
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def collect_queue_stats
|
30
|
+
hostname = Socket.gethostname
|
31
|
+
pid = ::Process.pid
|
32
|
+
ps = ::Sidekiq::ProcessSet.new
|
33
|
+
|
34
|
+
process = ps.find do |sp|
|
35
|
+
sp['hostname'] == hostname && sp['pid'] == pid
|
36
|
+
end
|
37
|
+
|
38
|
+
queues = process.nil? ? [] : process['queues']
|
39
|
+
|
30
40
|
::Sidekiq::Queue.all.map do |queue|
|
41
|
+
next unless queues.include? queue.name
|
31
42
|
{
|
32
43
|
backlog_total: queue.size,
|
33
44
|
latency_seconds: queue.latency.to_i,
|
34
45
|
labels: { queue: queue.name }
|
35
46
|
}
|
36
|
-
end
|
47
|
+
end.compact
|
37
48
|
end
|
38
49
|
end
|
39
50
|
end
|
@@ -44,14 +44,25 @@ class PrometheusExporter::Middleware
|
|
44
44
|
controller = params["controller"]
|
45
45
|
end
|
46
46
|
|
47
|
-
|
47
|
+
obj = {
|
48
48
|
type: "web",
|
49
49
|
timings: info,
|
50
50
|
queue_time: queue_time,
|
51
51
|
action: action,
|
52
52
|
controller: controller,
|
53
53
|
status: status
|
54
|
-
|
54
|
+
}
|
55
|
+
labels = custom_labels(env)
|
56
|
+
if labels
|
57
|
+
obj = obj.merge(custom_labels: labels)
|
58
|
+
end
|
59
|
+
|
60
|
+
@client.send_json(obj)
|
61
|
+
end
|
62
|
+
|
63
|
+
# allows subclasses to add custom labels based on env
|
64
|
+
def custom_labels(env)
|
65
|
+
nil
|
55
66
|
end
|
56
67
|
|
57
68
|
private
|
@@ -15,6 +15,8 @@ module PrometheusExporter::Server
|
|
15
15
|
@collector_class = nil
|
16
16
|
@type_collectors = nil
|
17
17
|
@prefix = nil
|
18
|
+
@auth = nil
|
19
|
+
@realm = nil
|
18
20
|
|
19
21
|
options.each do |k, v|
|
20
22
|
send("#{k}=", v) if self.class.method_defined?("#{k}=")
|
@@ -40,12 +42,20 @@ module PrometheusExporter::Server
|
|
40
42
|
)
|
41
43
|
end
|
42
44
|
|
43
|
-
server = server_class.new
|
45
|
+
server = server_class.new(port: port, bind: bind, collector: collector, timeout: timeout, verbose: verbose, auth: auth, realm: realm)
|
44
46
|
server.start
|
45
47
|
end
|
46
48
|
|
47
49
|
attr_accessor :unicorn_listen_address, :unicorn_pid_file
|
48
|
-
attr_writer :prefix, :port, :bind, :collector_class, :type_collectors, :timeout, :verbose, :server_class, :label
|
50
|
+
attr_writer :prefix, :port, :bind, :collector_class, :type_collectors, :timeout, :verbose, :server_class, :label, :auth, :realm
|
51
|
+
|
52
|
+
def auth
|
53
|
+
@auth || nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def realm
|
57
|
+
@realm || PrometheusExporter::DEFAULT_REALM
|
58
|
+
end
|
49
59
|
|
50
60
|
def prefix
|
51
61
|
@prefix || PrometheusExporter::DEFAULT_PREFIX
|
@@ -17,7 +17,7 @@ module PrometheusExporter::Server
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def collect(obj)
|
20
|
-
default_labels = { job_name: obj['name'] }
|
20
|
+
default_labels = { job_name: obj['name'], queue: obj['queue'] }
|
21
21
|
custom_labels = obj['custom_labels']
|
22
22
|
labels = custom_labels.nil? ? default_labels : default_labels.merge(custom_labels)
|
23
23
|
|
@@ -52,7 +52,7 @@ module PrometheusExporter::Server
|
|
52
52
|
if !@sidekiq_jobs_total
|
53
53
|
|
54
54
|
@sidekiq_job_duration_seconds =
|
55
|
-
PrometheusExporter::Metric::
|
55
|
+
PrometheusExporter::Metric::Summary.new(
|
56
56
|
"sidekiq_job_duration_seconds", "Total time spent in sidekiq jobs.")
|
57
57
|
|
58
58
|
@sidekiq_jobs_total =
|
@@ -9,9 +9,14 @@ module PrometheusExporter::Server
|
|
9
9
|
class WebServer
|
10
10
|
attr_reader :collector
|
11
11
|
|
12
|
-
def initialize(
|
13
|
-
|
14
|
-
@
|
12
|
+
def initialize(opts)
|
13
|
+
@port = opts[:port] || PrometheusExporter::DEFAULT_PORT
|
14
|
+
@bind = opts[:bind] || PrometheusExporter::DEFAULT_BIND_ADDRESS
|
15
|
+
@collector = opts[:collector] || Collector.new
|
16
|
+
@timeout = opts[:timeout] || PrometheusExporter::DEFAULT_TIMEOUT
|
17
|
+
@verbose = opts[:verbose] || false
|
18
|
+
@auth = opts[:auth]
|
19
|
+
@realm = opts[:realm] || PrometheusExporter::DEFAULT_REALM
|
15
20
|
|
16
21
|
@metrics_total = PrometheusExporter::Metric::Counter.new("collector_metrics_total", "Total metrics processed by exporter web.")
|
17
22
|
|
@@ -23,33 +28,33 @@ module PrometheusExporter::Server
|
|
23
28
|
@sessions_total.observe(0)
|
24
29
|
@bad_metrics_total.observe(0)
|
25
30
|
|
26
|
-
access_log, logger = nil
|
31
|
+
@access_log, @logger = nil
|
27
32
|
|
28
|
-
if verbose
|
29
|
-
access_log = [
|
33
|
+
if @verbose
|
34
|
+
@access_log = [
|
30
35
|
[$stderr, WEBrick::AccessLog::COMMON_LOG_FORMAT],
|
31
36
|
[$stderr, WEBrick::AccessLog::REFERER_LOG_FORMAT],
|
32
37
|
]
|
33
|
-
logger = WEBrick::Log.new($stderr)
|
38
|
+
@logger = WEBrick::Log.new($stderr)
|
34
39
|
else
|
35
|
-
access_log = []
|
36
|
-
logger = WEBrick::Log.new("/dev/null")
|
40
|
+
@access_log = []
|
41
|
+
@logger = WEBrick::Log.new("/dev/null")
|
37
42
|
end
|
38
43
|
|
44
|
+
@logger.info "Using Basic Authentication via #{@auth}" if @verbose && @auth
|
45
|
+
|
39
46
|
@server = WEBrick::HTTPServer.new(
|
40
|
-
Port: port,
|
41
|
-
BindAddress: bind,
|
42
|
-
Logger: logger,
|
43
|
-
AccessLog: access_log,
|
47
|
+
Port: @port,
|
48
|
+
BindAddress: @bind,
|
49
|
+
Logger: @logger,
|
50
|
+
AccessLog: @access_log,
|
44
51
|
)
|
45
52
|
|
46
|
-
@collector = collector || Collector.new
|
47
|
-
@port = port
|
48
|
-
@timeout = timeout
|
49
|
-
|
50
53
|
@server.mount_proc '/' do |req, res|
|
51
54
|
res['Content-Type'] = 'text/plain; charset=utf-8'
|
52
55
|
if req.path == '/metrics'
|
56
|
+
authenticate(req, res) if @auth
|
57
|
+
|
53
58
|
res.status = 200
|
54
59
|
if req.header["accept-encoding"].to_s.include?("gzip")
|
55
60
|
sio = StringIO.new
|
@@ -159,5 +164,12 @@ module PrometheusExporter::Server
|
|
159
164
|
gauge
|
160
165
|
end
|
161
166
|
|
167
|
+
def authenticate(req, res)
|
168
|
+
htpasswd = WEBrick::HTTPAuth::Htpasswd.new(@auth)
|
169
|
+
basic_auth = WEBrick::HTTPAuth::BasicAuth.new({ Realm: @realm, UserDB: htpasswd, Logger: @logger })
|
170
|
+
|
171
|
+
basic_auth.authenticate(req, res)
|
172
|
+
end
|
173
|
+
|
162
174
|
end
|
163
175
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prometheus_exporter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Saffron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -172,9 +172,9 @@ executables:
|
|
172
172
|
extensions: []
|
173
173
|
extra_rdoc_files: []
|
174
174
|
files:
|
175
|
+
- ".github/workflows/ci.yml"
|
175
176
|
- ".gitignore"
|
176
177
|
- ".rubocop.yml"
|
177
|
-
- ".travis.yml"
|
178
178
|
- CHANGELOG
|
179
179
|
- CODE_OF_CONDUCT.md
|
180
180
|
- Gemfile
|
data/.travis.yml
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
sudo: required
|
2
|
-
language: ruby
|
3
|
-
dist: trusty
|
4
|
-
rvm:
|
5
|
-
- 2.3
|
6
|
-
- 2.4
|
7
|
-
- 2.5
|
8
|
-
- 2.6
|
9
|
-
before_install: gem install bundler -v 1.16.1
|
10
|
-
before_script: sudo sh -c 'echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6'
|
11
|
-
|
12
|
-
script: bundle exec rubocop && bundle exec rake
|