prometheus_exporter 0.4.17 → 0.5.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: ca59b198973bbfb5df6e5204f7a74138df05759f6a44839a60eaabd1d0d58697
4
- data.tar.gz: 384a5a138d1eb8c24ccc47984d6f6437bcced89f058cc55460bf3dcb60f326fb
3
+ metadata.gz: c77ede3528c6008266620498f698c8a0e9e17bfa0c0691fedf5a3c4c3bdb8ebd
4
+ data.tar.gz: 62f8b159f68036f05b785fea4eebef48df66606b083136eda5c37e4d3c294132
5
5
  SHA512:
6
- metadata.gz: 7406bf4ed7f65ee3dd243ac01294737292b721b9cd04f34a93b84200ad3259bc18ee8326aa8f5bea438a6ada13dab42453dd380e0fd2d34008378ecd8f581504
7
- data.tar.gz: 8834124a60121673f01023a2e564b3afb55f3977d2d0214cccc2b7fb201788c2b15650992c49402180e6468a7676278ce963a0bded8f2fcf6ccc9984937a9199
6
+ metadata.gz: 2c0699014753102b514f1bd6fa965cd82f6d83c34084daf4a3b07537b9224295a1df02aedce3082588e44f4c001e71ea83178456bd7efd8a8eae836b2fc6e9a7
7
+ data.tar.gz: df738517c22422ba9e4e2e7cfd6ea6bbcf7542175a827b1632e7ff69af4651d4acf45bcec9693c4dd899b9b305b952fac989999ebea23013f3ddad0d3c396e00
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ 0.5.0 - 14-02-2019
2
+
3
+ - Breaking change: listen only to localhost by default to prevent unintended insecure configuration
4
+ - FIX: Avoid calling `hostname` aggressively, instead cache it on the exporter instance
5
+
1
6
  0.4.17 - 13-01-2019
2
7
 
3
8
  - FEATURE: add support for `to_h` on all metrics which can be used to query existing key/values
data/README.md CHANGED
@@ -13,6 +13,7 @@ To learn more see [Instrumenting Rails with Prometheus](https://samsaffron.com/a
13
13
  * [Rails integration](#rails-integration)
14
14
  * [Per-process stats](#per-process-stats)
15
15
  * [Sidekiq metrics](#sidekiq-metrics)
16
+ * [Shoryuken metrics](#shoryuken-metrics)
16
17
  * [ActiveRecord Connection Pool Metrics](#activerecord-connection-pool-metrics)
17
18
  * [Delayed Job plugin](#delayed-job-plugin)
18
19
  * [Hutch metrics](#hutch-message-processing-tracer)
@@ -62,8 +63,9 @@ require 'prometheus_exporter/server'
62
63
  require 'prometheus_exporter/client'
63
64
  require 'prometheus_exporter/instrumentation'
64
65
 
66
+ # bind is the address, on which the webserver will listen
65
67
  # port is the port that will provide the /metrics route
66
- server = PrometheusExporter::Server::WebServer.new port: 12345
68
+ server = PrometheusExporter::Server::WebServer.new bind: 'localhost', port: 12345
67
69
  server.start
68
70
 
69
71
  # wire up a default local client
@@ -115,7 +117,7 @@ In some cases (for example, unicorn or puma clusters) you may want to aggregate
115
117
 
116
118
  Simplest way to achieve this is to use the built-in collector.
117
119
 
118
- First, run an exporter on your desired port (we use the default port of 9394):
120
+ First, run an exporter on your desired port (we use the default bind to localhost and port of 9394):
119
121
 
120
122
  ```
121
123
  $ prometheus_exporter
@@ -219,7 +221,7 @@ end
219
221
  For Unicorn / Passenger
220
222
 
221
223
  ```ruby
222
- after_fork do
224
+ after_fork do |_server, _worker|
223
225
  require 'prometheus_exporter/instrumentation'
224
226
  PrometheusExporter::Instrumentation::ActiveRecord.start(
225
227
  custom_labels: { type: "unicorn_worker" }, #optional params
@@ -297,6 +299,19 @@ Sometimes the Sidekiq server shuts down before it can send metrics, that were ge
297
299
  end
298
300
  ```
299
301
 
302
+ #### Shoryuken metrics
303
+
304
+ For Shoryuken metrics (how many jobs ran? how many failed? how long did they take? how many were restarted?)
305
+
306
+ ```ruby
307
+ Shoryuken.configure_server do |config|
308
+ config.server_middleware do |chain|
309
+ require 'prometheus_exporter/instrumentation'
310
+ chain.add PrometheusExporter::Instrumentation::Shoryuken
311
+ end
312
+ end
313
+ ```
314
+
300
315
  #### Delayed Job plugin
301
316
 
302
317
  In an initializer:
@@ -19,6 +19,12 @@ def run
19
19
  "Port exporter should listen on (default: #{PrometheusExporter::DEFAULT_PORT})") do |o|
20
20
  options[:port] = o.to_i
21
21
  end
22
+ opt.on('-b',
23
+ '--bind STRING',
24
+ String,
25
+ "IP address exporter should listen on (default: #{PrometheusExporter::DEFAULT_BIND_ADDRESS})") do |o|
26
+ options[:bind] = o.to_s
27
+ end
22
28
  opt.on('-t',
23
29
  '--timeout INTEGER',
24
30
  Integer,
@@ -81,7 +87,7 @@ def run
81
87
 
82
88
  runner = PrometheusExporter::Server::Runner.new(options)
83
89
 
84
- puts "#{Time.now} Starting prometheus exporter on port #{runner.port}"
90
+ puts "#{Time.now} Starting prometheus exporter on #{runner.bind}:#{runner.port}"
85
91
  runner.start
86
92
  sleep
87
93
  end
@@ -7,6 +7,7 @@ require "thread"
7
7
  module PrometheusExporter
8
8
  # per: https://github.com/prometheus/prometheus/wiki/Default-port-allocations
9
9
  DEFAULT_PORT = 9394
10
+ DEFAULT_BIND_ADDRESS = 'localhost'
10
11
  DEFAULT_PREFIX = 'ruby_'
11
12
  DEFAULT_TIMEOUT = 2
12
13
 
@@ -19,6 +20,17 @@ module PrometheusExporter
19
20
  end
20
21
  end
21
22
 
23
+ def self.hostname
24
+ @hostname ||=
25
+ begin
26
+ require 'socket'
27
+ Socket.gethostname
28
+ rescue => e
29
+ STDERR.puts "Unable to lookup hostname #{e}"
30
+ "unknown-host"
31
+ end
32
+ end
33
+
22
34
  def self.detect_json_serializer(preferred)
23
35
  if preferred.nil?
24
36
  preferred = :oj if has_oj?
@@ -9,3 +9,4 @@ require_relative "instrumentation/puma"
9
9
  require_relative "instrumentation/hutch"
10
10
  require_relative "instrumentation/unicorn"
11
11
  require_relative "instrumentation/active_record"
12
+ require_relative "instrumentation/shoryuken"
@@ -51,17 +51,6 @@ module PrometheusExporter::Instrumentation
51
51
  def initialize(metric_labels, config_labels)
52
52
  @metric_labels = metric_labels
53
53
  @config_labels = config_labels
54
- @hostname = nil
55
- end
56
-
57
- def hostname
58
- @hostname ||=
59
- begin
60
- `hostname`.strip
61
- rescue => e
62
- STDERR.puts "Unable to lookup hostname #{e}"
63
- "unknown-host"
64
- end
65
54
  end
66
55
 
67
56
  def collect
@@ -87,7 +76,7 @@ module PrometheusExporter::Instrumentation
87
76
  metric = {
88
77
  pid: pid,
89
78
  type: "active_record",
90
- hostname: hostname,
79
+ hostname: ::PrometheusExporter.hostname,
91
80
  metric_labels: labels
92
81
  }
93
82
  metric.merge!(pool.stat)
@@ -42,24 +42,13 @@ module PrometheusExporter::Instrumentation
42
42
 
43
43
  def initialize(metric_labels)
44
44
  @metric_labels = metric_labels
45
- @hostname = nil
46
- end
47
-
48
- def hostname
49
- @hostname ||=
50
- begin
51
- `hostname`.strip
52
- rescue => e
53
- STDERR.puts "Unable to lookup hostname #{e}"
54
- "unknown-host"
55
- end
56
45
  end
57
46
 
58
47
  def collect
59
48
  metric = {}
60
49
  metric[:type] = "process"
61
50
  metric[:metric_labels] = @metric_labels
62
- metric[:hostname] = hostname
51
+ metric[:hostname] = ::PrometheusExporter.hostname
63
52
  collect_gc_stats(metric)
64
53
  collect_v8_stats(metric)
65
54
  collect_process_stats(metric)
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PrometheusExporter::Instrumentation
4
+ class Shoryuken
5
+
6
+ def initialize(client: nil)
7
+ @client = client || PrometheusExporter::Client.default
8
+ end
9
+
10
+ def call(worker, queue, msg, body)
11
+ success = false
12
+ start = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
13
+ result = yield
14
+ success = true
15
+ result
16
+ rescue ::Shoryuken::Shutdown => e
17
+ shutdown = true
18
+ raise e
19
+ ensure
20
+ duration = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - start
21
+ @client.send_json(
22
+ type: "shoryuken",
23
+ queue: queue,
24
+ name: worker.class.name,
25
+ success: success,
26
+ shutdown: shutdown,
27
+ duration: duration
28
+ )
29
+ end
30
+ end
31
+ end
@@ -14,3 +14,4 @@ require_relative "server/puma_collector"
14
14
  require_relative "server/hutch_collector"
15
15
  require_relative "server/unicorn_collector"
16
16
  require_relative "server/active_record_collector"
17
+ require_relative "server/shoryuken_collector"
@@ -18,6 +18,7 @@ module PrometheusExporter::Server
18
18
  register_collector(HutchCollector.new)
19
19
  register_collector(UnicornCollector.new)
20
20
  register_collector(ActiveRecordCollector.new)
21
+ register_collector(ShoryukenCollector.new)
21
22
  end
22
23
 
23
24
  def register_collector(collector)
@@ -32,69 +32,46 @@ module PrometheusExporter::Server
32
32
  )
33
33
  end
34
34
 
35
- server = server_class.new port: port, collector: collector, timeout: timeout, verbose: verbose
35
+ server = server_class.new port: port, bind: bind, collector: collector, timeout: timeout, verbose: verbose
36
36
  server.start
37
37
  end
38
38
 
39
- def prefix=(prefix)
40
- @prefix = prefix
41
- end
39
+ attr_accessor :unicorn_listen_address, :unicorn_pid_file
40
+ attr_writer :prefix, :port, :bind, :collector_class, :type_collectors, :timeout, :verbose, :server_class
42
41
 
43
42
  def prefix
44
43
  @prefix || PrometheusExporter::DEFAULT_PREFIX
45
44
  end
46
45
 
47
- def port=(port)
48
- @port = port
49
- end
50
-
51
46
  def port
52
47
  @port || PrometheusExporter::DEFAULT_PORT
53
48
  end
54
49
 
55
- def collector_class=(collector_class)
56
- @collector_class = collector_class
50
+ def bind
51
+ @bind || PrometheusExporter::DEFAULT_BIND_ADDRESS
57
52
  end
58
53
 
59
54
  def collector_class
60
55
  @collector_class || PrometheusExporter::Server::Collector
61
56
  end
62
57
 
63
- def type_collectors=(type_collectors)
64
- @type_collectors = type_collectors
65
- end
66
-
67
58
  def type_collectors
68
59
  @type_collectors || []
69
60
  end
70
61
 
71
- def timeout=(timeout)
72
- @timeout = timeout
73
- end
74
-
75
62
  def timeout
76
63
  @timeout || PrometheusExporter::DEFAULT_TIMEOUT
77
64
  end
78
65
 
79
- def verbose=(verbose)
80
- @verbose = verbose
81
- end
82
-
83
66
  def verbose
84
67
  return @verbose if defined? @verbose
85
68
  false
86
69
  end
87
70
 
88
- def server_class=(server_class)
89
- @server_class = server_class
90
- end
91
-
92
71
  def server_class
93
72
  @server_class || PrometheusExporter::Server::WebServer
94
73
  end
95
74
 
96
- attr_accessor :unicorn_listen_address, :unicorn_pid_file
97
-
98
75
  def collector
99
76
  @_collector ||= collector_class.new
100
77
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PrometheusExporter::Server
4
+ class ShoryukenCollector < TypeCollector
5
+
6
+ def type
7
+ "shoryuken"
8
+ end
9
+
10
+ def collect(obj)
11
+ default_labels = { job_name: obj['name'] , queue_name: obj['queue'] }
12
+ custom_labels = obj['custom_labels']
13
+ labels = custom_labels.nil? ? default_labels : default_labels.merge(custom_labels)
14
+
15
+ ensure_shoryuken_metrics
16
+ @shoryuken_job_duration_seconds.observe(obj["duration"], labels)
17
+ @shoryuken_jobs_total.observe(1, labels)
18
+ @shoryuken_restarted_jobs_total.observe(1, labels) if obj["shutdown"]
19
+ @shoryuken_failed_jobs_total.observe(1, labels) if !obj["success"] && !obj["shutdown"]
20
+ end
21
+
22
+ def metrics
23
+ if @shoryuken_jobs_total
24
+ [
25
+ @shoryuken_job_duration_seconds,
26
+ @shoryuken_jobs_total,
27
+ @shoryuken_restarted_jobs_total,
28
+ @shoryuken_failed_jobs_total,
29
+ ]
30
+ else
31
+ []
32
+ end
33
+ end
34
+
35
+ protected
36
+
37
+ def ensure_shoryuken_metrics
38
+ if !@shoryuken_jobs_total
39
+
40
+ @shoryuken_job_duration_seconds =
41
+ PrometheusExporter::Metric::Counter.new(
42
+ "shoryuken_job_duration_seconds", "Total time spent in shoryuken jobs.")
43
+
44
+ @shoryuken_jobs_total =
45
+ PrometheusExporter::Metric::Counter.new(
46
+ "shoryuken_jobs_total", "Total number of shoryuken jobs executed.")
47
+
48
+ @shoryuken_restarted_jobs_total =
49
+ PrometheusExporter::Metric::Counter.new(
50
+ "shoryuken_restarted_jobs_total", "Total number of shoryuken jobs that we restarted because of a shoryuken shutdown.")
51
+
52
+ @shoryuken_failed_jobs_total =
53
+ PrometheusExporter::Metric::Counter.new(
54
+ "shoryuken_failed_jobs_total", "Total number of failed shoryuken jobs.")
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -9,7 +9,7 @@ module PrometheusExporter::Server
9
9
  class WebServer
10
10
  attr_reader :collector
11
11
 
12
- def initialize(port: , collector: nil, timeout: PrometheusExporter::DEFAULT_TIMEOUT, verbose: false)
12
+ def initialize(port: , bind: nil, collector: nil, timeout: PrometheusExporter::DEFAULT_TIMEOUT, verbose: false)
13
13
 
14
14
  @verbose = verbose
15
15
 
@@ -38,6 +38,7 @@ module PrometheusExporter::Server
38
38
 
39
39
  @server = WEBrick::HTTPServer.new(
40
40
  Port: port,
41
+ BindAddress: bind,
41
42
  Logger: logger,
42
43
  AccessLog: access_log,
43
44
  )
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PrometheusExporter
4
- VERSION = "0.4.17"
4
+ VERSION = '0.5.0'
5
5
  end
@@ -5,22 +5,24 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require "prometheus_exporter/version"
6
6
 
7
7
  Gem::Specification.new do |spec|
8
- spec.name = "prometheus_exporter"
9
- spec.version = PrometheusExporter::VERSION
10
- spec.authors = ["Sam Saffron"]
11
- spec.email = ["sam.saffron@gmail.com"]
8
+ spec.name = "prometheus_exporter"
9
+ spec.version = PrometheusExporter::VERSION
10
+ spec.authors = ["Sam Saffron"]
11
+ spec.email = ["sam.saffron@gmail.com"]
12
12
 
13
- spec.summary = %q{Prometheus Exporter}
14
- spec.description = %q{Prometheus metric collector and exporter for Ruby}
15
- spec.homepage = "https://github.com/discourse/prometheus_exporter"
16
- spec.license = "MIT"
13
+ spec.summary = %q{Prometheus Exporter}
14
+ spec.description = %q{Prometheus metric collector and exporter for Ruby}
15
+ spec.homepage = "https://github.com/discourse/prometheus_exporter"
16
+ spec.license = "MIT"
17
17
 
18
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ spec.post_install_message = "prometheus_exporter will only bind to localhost by default as of v0.5"
19
+
20
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
21
  f.match(%r{^(test|spec|features|bin)/})
20
22
  end
21
- spec.bindir = "bin"
22
- spec.executables = ["prometheus_exporter"]
23
- spec.require_paths = ["lib"]
23
+ spec.bindir = "bin"
24
+ spec.executables = ["prometheus_exporter"]
25
+ spec.require_paths = ["lib"]
24
26
 
25
27
  spec.add_development_dependency "rubocop", ">= 0.69"
26
28
  spec.add_development_dependency "bundler", "> 1.16"
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.17
4
+ version: 0.5.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-01-13 00:00:00.000000000 Z
11
+ date: 2020-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -194,6 +194,7 @@ files:
194
194
  - lib/prometheus_exporter/instrumentation/method_profiler.rb
195
195
  - lib/prometheus_exporter/instrumentation/process.rb
196
196
  - lib/prometheus_exporter/instrumentation/puma.rb
197
+ - lib/prometheus_exporter/instrumentation/shoryuken.rb
197
198
  - lib/prometheus_exporter/instrumentation/sidekiq.rb
198
199
  - lib/prometheus_exporter/instrumentation/unicorn.rb
199
200
  - lib/prometheus_exporter/metric.rb
@@ -212,6 +213,7 @@ files:
212
213
  - lib/prometheus_exporter/server/process_collector.rb
213
214
  - lib/prometheus_exporter/server/puma_collector.rb
214
215
  - lib/prometheus_exporter/server/runner.rb
216
+ - lib/prometheus_exporter/server/shoryuken_collector.rb
215
217
  - lib/prometheus_exporter/server/sidekiq_collector.rb
216
218
  - lib/prometheus_exporter/server/type_collector.rb
217
219
  - lib/prometheus_exporter/server/unicorn_collector.rb
@@ -223,7 +225,8 @@ homepage: https://github.com/discourse/prometheus_exporter
223
225
  licenses:
224
226
  - MIT
225
227
  metadata: {}
226
- post_install_message:
228
+ post_install_message: prometheus_exporter will only bind to localhost by default as
229
+ of v0.5
227
230
  rdoc_options: []
228
231
  require_paths:
229
232
  - lib