prometheus_exporter 0.5.3 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a284b77cbd17e80457e94520d18976dc3dd6fb8c238d8a90cda6513e291f01ad
4
- data.tar.gz: 4464419fc9c67d387edd9d6d5bdfac1411d0864d29c0cd3a6f10d2f02b3d7e24
3
+ metadata.gz: f516c39448418a2216851149f0479f3f9e0f5feadae5a5468e7953fc0551d318
4
+ data.tar.gz: dcc937b79e05d4cd74a64ab2135425c75c4bba1be053bec99e8db0695a3ac998
5
5
  SHA512:
6
- metadata.gz: 84c2e2af95a8839cd9deecca9fbc26bacff590ae5cb3677862f1eb1d476401114406130cc78d2248cec0380e70c1b74b306e1265b3343bbac9c09d8400e692a3
7
- data.tar.gz: 41898546588ef7eafa772252ef5ed1a8c222e4009e64ccec35d463217336597a94f1c844f3e2174e030c19a7c1b90d1028e5729cc393cf797654362f5d66b7f2
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
@@ -1,3 +1,7 @@
1
+ 0.6.0 - 10-11-2020
2
+
3
+ - FEATURE: add support for basic-auth in the prometheus_exporter web server
4
+
1
5
  0.5.3 - 29-07-2020
2
6
 
3
7
  - FEATURE: added #remove to all metric types so users can remove specific labels if needed
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
- ¹) Only available when Redis is used.
207
- ²) Only available when Mysql or PostgreSQL are used.
208
- ³) Only available when [Instrumenting Request Queueing Time](#instrumenting-request-queueing-time) is set up.
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
- | Counter | `sidekiq_job_duration_seconds` | Total time spent in sidekiq jobs |
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 also has a `job_name` label.
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
- user_count_gague = PrometheusExporter::Metric::Gauge.new('user_count', 'number of users in the app')
581
- user_count_gague.observe User.count
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:
@@ -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
@@ -11,6 +11,7 @@ module PrometheusExporter
11
11
  DEFAULT_PREFIX = 'ruby_'
12
12
  DEFAULT_LABEL = {}
13
13
  DEFAULT_TIMEOUT = 2
14
+ DEFAULT_REALM = 'Prometheus Exporter'
14
15
 
15
16
  class OjCompat
16
17
  def self.parse(obj)
@@ -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 = @custom_labels.nil? ? obj : obj.merge(custom_labels: @custom_labels)
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: class_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
- @client.send_json(
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 port: port, bind: bind, collector: collector, timeout: timeout, verbose: verbose
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::Counter.new(
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(port: , bind: nil, collector: nil, timeout: PrometheusExporter::DEFAULT_TIMEOUT, verbose: false)
13
-
14
- @verbose = verbose
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PrometheusExporter
4
- VERSION = '0.5.3'
4
+ VERSION = '0.6.0'
5
5
  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.5.3
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-07-29 00:00:00.000000000 Z
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
@@ -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